In late 2023, a security vulnerability was discovered in Go’s standard library—specifically in the filepath package. Known as CVE-2023-45283, this bug affected how certain Windows file paths were handled, opening the door to unexpected (and potentially dangerous) file access.
This post will break down what went wrong, provide example code, explain the possible risks, and summarize how the Go team fixed it—all in simple American language.
\\?\ (UNC path): Used to bypass normal path processing and directly access device files.
- \??\ (Root Local Device path): Works in a similar way, letting you get to underlying devices and locations.
Normally, these are only used internally, but if a program doesn’t recognize these prefixes as “special,” anyone could use them to sneak around the filesystem. For example, \??\c:\Windows\System32 points right at the heart of your system.
Quick Example
// Go pseudo-code showing the bug
import "path/filepath"
func main() {
path := \??\c:\Windows\System32
cleaned := filepath.Clean(path)
// What you expect:
// cleaned == "\??\c:\Windows\System32"
// What before fix might allow:
// cleaned == "\??\c:\Windows\System32" (direct access, skipped normal checks!)
}
Before the fix, Go didn’t treat paths beginning with \??\ as special—they were just another “normal” path. This could let attackers trick applications using Go into opening, writing, or deleting files by using sneaky path tricks.
Absolute Path Confusion:
The function filepath.IsAbs might say \??\c:\x was NOT absolute, when it really *is*—opening up even more confusion.
filepath.VolumeName *didn't* recognize \??\ as a volume name, so volume detection failed.
In effect:
With a specially-crafted path, attackers could trick Go apps into reading, writing, or deleting files outside intended directories or sandboxes on Windows. That’s especially dangerous for servers or CLI tools processing untrusted input.
Consider a Go program that should only let users work inside a uploads folder, like this
// Vulnerable code
import "path/filepath"
userInput := \??\c:\Windows\System32\config\SAM
safePath := filepath.Clean(filepath.Join("uploads", userInput))
// safePath == \??\c:\Windows\System32\config\SAM
// Now the program can read or write to SYSTEM files, instead of just uploads!
*No check or restriction works here—because Clean and Join turn attacker input into a powerful device path.*
Recognizes \??\ as a volume (so checks don’t miss it).
Here’s the official fix in Go’s repo and the Go blog advisory.
Important Note—Update Correction (2023/2024)
After Go 1.20.11 and Go 1.21.4, they tried to fix volume name parsing, but it broke filepath.Clean(\?\c:): it returned \?\c: instead of the expected \?\c:\. That was fixed again quickly, restoring previous behavior.
*Always use the latest patched Go version for safety.*
Table: How Path Handling Changed
| Function | Path Input | Old Output | New Output |
|-----------------|-----------------------------------|----------------------|-------------------|
| Clean | \a\..\??\b | \??\b | .\??\b |
| Join | "\", "??", "b" | \??\b | \.\??\b |
| IsAbs | \??\foo\bar | false | true |
| VolumeName | \??\c:\something | "" | \??\ |
References
- Go issue #64891 (CVE-2023-45283)
- Official Go Security Advisory GO-2023-2225
- Go file path handling bugs
- Go 1.20.12 / 1.21.5 Release Notes
For details about Windows device paths:
- Microsoft documentation - Naming Files, Paths, and Namespaces
Conclusion: Patched, But Stay Aware
CVE-2023-45283 shows how subtle file path handling can blow open security on even well-maintained packages (like Go’s standard library). If you’re writing Go code that deals with files, especially on Windows, always sanitize user input and keep dependencies updated.
### Pro Tip: Always check path handling across OSes—protections you expect on UNIX may not work the same on Windows!
More Reading
- How Go’s filepath works across platforms
- Understanding Windows device paths
Spread the word! If you use Go on Windows, make sure you aren’t vulnerable to CVE-2023-45283.
*This was an exclusive breakdown. Stay safe and code securely!*
Timeline
Published on: 11/09/2023 17:15:08 UTC
Last modified on: 12/14/2023 10:15:07 UTC