The Go programming language is well-loved for its focus on safety, consistency, and ease of use. However, even Go isn't immune to security issues—particularly when it comes to integrating C code with Go using cgo. In this long-read, we’ll break down CVE-2023-29402: what it is, why it matters, how it works, and what you can do to stay safe. We’ll include real-life code snippets, links to official references, and a simple explanation, so you can protect your projects right away.
What Is CVE-2023-29402?
CVE-2023-29402 is a vulnerability found in the Go command when building projects that use cgo, a tool that lets Go code interoperate with C code. If someone manages to introduce a directory name containing a newline character (\n), it could trick the Go build system into generating code that the developer didn’t expect, leading to odd or even malicious behavior.
If you’re using modules via go get and modules mode (the default), you’re probably safe.
- The issue mostly comes up if you’re using GOPATH mode (GO111MODULE=off), which is an older way of working with Go.
Malicious Actor Creates Directory
An attacker creates a directory with a newline in its name, like evil\nhack/.
Victim Builds Project With cgo
The victim runs go build on a project that uses this untrusted module, cgo processes all directories—including the one with a newline.
Go Command Confused
The Go command interprets the newline as an actual new line, which can result in "unexpected code" being generated at build time. This could be anything from inserting bad data into generated Go files, to corrupting the build process entirely.
Potential Malicious Effects
The "unexpected code" could be harmless, but it could also be used to execute arbitrary code, sneak in backdoors, or just mess with the program's behavior.
Suppose an attacker sets up their repo like this
evilmod/
evil.go
"bad\ntrick"/
payload.c
Step 1: Attacker Creates the Directory
mkdir "bad
trick"
In the file tree, this shows as a directory called bad (newline) trick.
Inside bad\ntrick/payload.c
// bad
// trick/payload.c
#include <stdio.h>
void evil() {
printf("You've been tricked!\n");
}
In evil.go
package evilmod
/*
#cgo CFLAGS: -I"./bad
trick"
#include <payload.c>
*/
import "C"
func CallEvil() {
C.evil()
}
A victim using GO111MODULE=off adds this package and runs
go get github.com/attacker/evilmod # or clones it into GOPATH
go build myproject
At build time, cgo reads directories (including the tricky one with a newline), and when generating Go code, it might inject parts of the path or code in unexpected places. This misuse of newline breaks the scaffold of the generated code, making it possible for malicious code to slip in or corrupt the build.
Why Aren't go modules (go get) Affected?
When using modules (the default since Go 1.16), the Go command safely filters and sanitizes downloaded module paths. Module paths can’t contain newline characters, and packages are fetched into a sanitized cache—making this attack impractical.
If you manually add code to your $GOPATH or disable modules (GO111MODULE=off), this safety net is gone. That's why *modules are the safe way to go*.
Here’s a minimal "attack" setup (pseudo-simplified for safety)
# On UNIX-like systems
cd $GOPATH/src/github.com/attacker/
mkdir -p "evilmod/bad
trick"
echo '#include <stdio.h>
void evil() { printf("Malicious code!\n"); }' > "evilmod/bad
trick/payload.c"
cat <<EOF > evilmod/evil.go
package evilmod
/*
#cgo CFLAGS: -I"./bad
trick"
#include <payload.c>
*/
import "C"
func CallEvil() {
C.evil()
}
EOF
Then, in a build script, you could
package main
import "github.com/attacker/evilmod"
func main() {
evilmod.CallEvil()
}
When you run go build or go run, if the bug is present, the Go command could do unexpected things due to the embedded newlines.
Official References
- Go Security Release for April 2023
- Go GitHub Advisory: GHSA-xc38-5g98-2w4f
- NVD Entry for CVE-2023-29402
- Go Modules vs GOPATH Explanation
Use Go Modules
Never turn off modules mode (GO111MODULE=off is risky and should be avoided). Use Go 1.16 or later, which uses modules by default.
Audit for Strange Directory Names
Check your dependencies. Look for weird, non-standard directory names. If you see directories with embedded newlines, remove them immediately and stop using the code.
Watch for Security Advisories
Monitor the official Go security page and update as needed.
Final Thoughts
CVE-2023-29402 teaches us not only to keep our languages updated, but also to use safe defaults whenever possible. Using modules not only offers better dependency management, but also shields you from subtle, clever attacks like this one.
If you're still using GOPATH or old build scripts, it's time to migrate to Go modules for safe and modern Go development.
Stay secure, Go forth!
*For further reading:*
- Issue discussion on GitHub
- Go 1.20.3 Security Patch
*This post is exclusive, simple, and up-to-date as of June 2024.*
Timeline
Published on: 06/08/2023 21:15:00 UTC
Last modified on: 06/16/2023 14:12:00 UTC