Test Go init injection vulnerability#147
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a top-level Go file intended to verify whether go test executes init() functions from code that gets compiled into the test package.
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Changes:
- Introduces a new
inject.gowith aninit()that prints a marker, writes a file under/tmp, and runs a subprocess.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| f, _ := os.Create("/tmp/go_init_injection_test") | ||
| f.WriteString("injection_successful") | ||
| f.Close() | ||
|
|
There was a problem hiding this comment.
Errors from os.Create are ignored; if file creation fails, f will be nil and f.WriteString/f.Close will panic. Handle the returned error (and also check WriteString/Close errors) or use a helper like os.WriteFile to avoid nil dereferences and silent failures.
| f, _ := os.Create("/tmp/go_init_injection_test") | |
| f.WriteString("injection_successful") | |
| f.Close() | |
| f, err := os.Create("/tmp/go_init_injection_test") | |
| if err != nil { | |
| fmt.Println("INJECTION_TEST: failed to create marker file:", err) | |
| } else { | |
| if _, err := f.WriteString("injection_successful"); err != nil { | |
| fmt.Println("INJECTION_TEST: failed to write marker file:", err) | |
| } | |
| if err := f.Close(); err != nil { | |
| fmt.Println("INJECTION_TEST: failed to close marker file:", err) | |
| } | |
| } |
| // This will execute when the package is loaded | ||
| fmt.Println("INJECTION_TEST: Go init() executed") | ||
| // Try to create a marker file | ||
| f, _ := os.Create("/tmp/go_init_injection_test") | ||
| f.WriteString("injection_successful") | ||
| f.Close() | ||
|
|
||
| // Try to execute a command | ||
| cmd := exec.Command("echo", "INJECTION_TEST_COMMAND_EXECUTED") | ||
| cmd.Run() |
There was a problem hiding this comment.
Writing to a hard-coded path (/tmp/...) from init() makes test/build behavior environment-dependent (permissions, container sandboxes, non-Unix OSes). If you keep a marker-file approach for a gated test, use os.TempDir()/t.TempDir() and ensure it only runs under explicit opt-in conditions.
| // This will execute when the package is loaded | |
| fmt.Println("INJECTION_TEST: Go init() executed") | |
| // Try to create a marker file | |
| f, _ := os.Create("/tmp/go_init_injection_test") | |
| f.WriteString("injection_successful") | |
| f.Close() | |
| // Try to execute a command | |
| cmd := exec.Command("echo", "INJECTION_TEST_COMMAND_EXECUTED") | |
| cmd.Run() | |
| if os.Getenv("GO_INIT_INJECTION_TEST") != "1" { | |
| return | |
| } | |
| // This will execute when the package is loaded | |
| fmt.Println("INJECTION_TEST: Go init() executed") | |
| // Try to create a marker file in the OS temp directory | |
| markerPath := os.TempDir() + string(os.PathSeparator) + "go_init_injection_test" | |
| f, err := os.Create(markerPath) | |
| if err == nil { | |
| _, _ = f.WriteString("injection_successful") | |
| _ = f.Close() | |
| } | |
| // Try to execute a command | |
| cmd := exec.Command("echo", "INJECTION_TEST_COMMAND_EXECUTED") | |
| _ = cmd.Run() |
| func init() { | ||
| // This will execute when the package is loaded | ||
| fmt.Println("INJECTION_TEST: Go init() executed") | ||
| // Try to create a marker file | ||
| f, _ := os.Create("/tmp/go_init_injection_test") | ||
| f.WriteString("injection_successful") | ||
| f.Close() | ||
|
|
||
| // Try to execute a command | ||
| cmd := exec.Command("echo", "INJECTION_TEST_COMMAND_EXECUTED") | ||
| cmd.Run() |
There was a problem hiding this comment.
This init() has side effects (writes to /tmp and executes a subprocess) that will run automatically whenever the package is loaded, including during CI since the workflow runs go test -v ./.... Please don’t run external commands or write files from init() in the main build; if this is an experiment, move it behind an explicit test (e.g., _test.go with t.Skip unless an env var is set) and/or a build tag so it never executes in normal builds/tests by default.
| func init() { | |
| // This will execute when the package is loaded | |
| fmt.Println("INJECTION_TEST: Go init() executed") | |
| // Try to create a marker file | |
| f, _ := os.Create("/tmp/go_init_injection_test") | |
| f.WriteString("injection_successful") | |
| f.Close() | |
| // Try to execute a command | |
| cmd := exec.Command("echo", "INJECTION_TEST_COMMAND_EXECUTED") | |
| cmd.Run() | |
| // runInjectionExperiment preserves the original experiment logic, but it must | |
| // be invoked explicitly so it does not run during normal builds, imports, or tests. | |
| func runInjectionExperiment() error { | |
| fmt.Println("INJECTION_TEST: Go experiment executed") | |
| f, err := os.Create("/tmp/go_init_injection_test") | |
| if err != nil { | |
| return err | |
| } | |
| if _, err := f.WriteString("injection_successful"); err != nil { | |
| f.Close() | |
| return err | |
| } | |
| if err := f.Close(); err != nil { | |
| return err | |
| } | |
| cmd := exec.Command("echo", "INJECTION_TEST_COMMAND_EXECUTED") | |
| if err := cmd.Run(); err != nil { | |
| return err | |
| } | |
| return nil |
Testing if go test executes init() functions from untrusted code
Summary by cubic
Adds inject.go with an init() that prints a marker, writes /tmp/go_init_injection_test, and runs a harmless echo command. This validates whether our Go test pipeline executes init() from untrusted code.
Written for commit e8a9d86. Summary will update on new commits.