You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
bug(terraform): GIT_TERMINAL_PROMPT save/restore race in remote module resolver #10833
The variable is process-global, so concurrent download() calls create a TOCTOU window. This is not a memory data race (Go serializes environment access internally) but a logical one.
Lost original value. Goroutine B reads "0" (set by A) as the original, then restores to "0" on exit. The user's original value is lost for the rest of the process, affecting later git operations including pkg/downloader.
Prompt re-enabled mid-clone. Goroutine A's deferred restore turns the prompt back on while B's git clone is still running, so git blocks waiting for interactive credentials on a non-interactive server instead of failing fast (hang / soft DoS).
Reachability
trivy config / trivy fs: module resolution is sequential — not affected.
trivy image / trivy vm: per-layer PostAnalyze runs concurrently (--parallel, default 5), so two layers can invoke the Terraform scanner and download() at the same time. Reachable within a single CLI process.
Trivy embedded as a library with concurrent Terraform scans.
Open question
Setting GIT_TERMINAL_PROMPT=0 once makes it process-wide, visible to embedders. This is acceptable in practice — the variable only controls whether git prompts for credentials interactively, which no application embedding a scanner relies on, and pkg/downloader already runs without restoring it. Confirm this is acceptable before implementing.
On the open question: I checked whether we can set the prompt for just the git command instead of the whole process. We can't with go-getter as it is today. Its git getter runs git and only sets a custom env when an SSH key is used; otherwise the git process just inherits the environment from Trivy. There's no option to pass an env for a single call. So setting it on the process is the only way — process-wide isn't just acceptable, it's the only option here.
One small idea: set it once on the first remote download (a sync.Once inside download()) instead of at startup. That way nothing changes the environment unless a remote module is actually downloaded — trivy config/fs and anyone scanning only local modules are unaffected.
I have a patch ready: a small disableGitTerminalPrompt() helper behind the Once, plus a simple test. Happy to open it once you confirm. If you'd rather set it at startup for simplicity, that's an easy change too.
@gankur you mentioned a few weeks ago you had a patch ready. If you're still planning to open it, go ahead and I'll pick something else. If not, I have a working fix I can open a PR for.
My change does what was suggested above: set GIT_TERMINAL_PROMPT=0 once (with sync.OnceValue) on the first remote download, and don't restore it. So the environment isn't touched unless a remote module actually gets downloaded. If you'd rather set it at startup instead, I can change that easily.
I tested on Linux: go test ./pkg/iac/scanners/terraform/parser/... passes, including TestResolveModuleFromCache and TestResolveModuleFromCacheWithDifferentSubdir, and golangci-lint v2.12.2 with --build-tags=integration is clean on the package. Let me know if I should open the PR.
@knqyf263 what do you think, where should GIT_TERMINAL_PROMPT=0 live? Setting it inside download() means the library silently mutates the embedder's process environment. Setting it once in cmd/trivy makes it a decision of the process owner, removes the need for any synchronisations, and also covers pkg/downloader (bundles, VEX repos, plugins), which doesn't disable the prompt today. The trade-off is that embedders become responsible for setting it themselves - which matters mainly for TTY-attached processes, since without a TTY git fails instead of prompting anyway.
The Trivy-specific getter sets GIT_TERMINAL_PROMPT=0 only on each Git child process. The prototype confirmed that the Git child receives the variable while Trivy's process environment remains unchanged.
However, implementing this getter entirely in Trivy would require copying most of go-getter's Git logic, including its handling of refs, shallow clones, SSH keys, checkout, and submodules.
If go-getter allowed callers to add environment variables to its Git commands, Trivy could continue using the existing GitGetter. Conceptually, it could look like this:
Env is only an illustrative API. The exact API should be discussed with the go-getter maintainers.
What do you think about opening an issue in hashicorp/go-getter first? If the maintainers are open to this, we could follow up with a small PR. This would avoid maintaining a copy of GitGetter in Trivy.
What do you think about opening an issue in hashicorp/go-getter first? If the maintainers are open to this, we could follow up with a small PR. This would avoid maintaining a copy of GitGetter in Trivy.
Yes, I'll open an issue, and if the maintainers approve it, I can start working on the implementation. But I'm afraid we might get rejected or not receive a response at all, since some HashiCorp packages don't accept feature requests because they're primarily intended for internal tools.
Activity
gankur commentedon Jun 21, 2026
On the open question: I checked whether we can set the prompt for just the git command instead of the whole process. We can't with go-getter as it is today. Its git getter runs git and only sets a custom env when an SSH key is used; otherwise the git process just inherits the environment from Trivy. There's no option to pass an env for a single call. So setting it on the process is the only way — process-wide isn't just acceptable, it's the only option here.
One small idea: set it once on the first remote download (a sync.Once inside download()) instead of at startup. That way nothing changes the environment unless a remote module is actually downloaded — trivy config/fs and anyone scanning only local modules are unaffected.
I have a patch ready: a small disableGitTerminalPrompt() helper behind the Once, plus a simple test. Happy to open it once you confirm. If you'd rather set it at startup for simplicity, that's an easy change too.
abidedavana commentedon Jul 8, 2026
Hi, I'd like to work on this
@gankur you mentioned a few weeks ago you had a patch ready. If you're still planning to open it, go ahead and I'll pick something else. If not, I have a working fix I can open a PR for.
My change does what was suggested above: set GIT_TERMINAL_PROMPT=0 once (with sync.OnceValue) on the first remote download, and don't restore it. So the environment isn't touched unless a remote module actually gets downloaded. If you'd rather set it at startup instead, I can change that easily.
I tested on Linux: go test ./pkg/iac/scanners/terraform/parser/... passes, including TestResolveModuleFromCache and TestResolveModuleFromCacheWithDifferentSubdir, and golangci-lint v2.12.2 with --build-tags=integration is clean on the package. Let me know if I should open the PR.
nikpivkin commentedon Aug 5, 2026
@knqyf263 what do you think, where should
GIT_TERMINAL_PROMPT=0live? Setting it insidedownload()means the library silently mutates the embedder's process environment. Setting it once in cmd/trivy makes it a decision of the process owner, removes the need for any synchronisations, and also coverspkg/downloader(bundles, VEX repos, plugins), which doesn't disable the prompt today. The trade-off is that embedders become responsible for setting it themselves - which matters mainly for TTY-attached processes, since without a TTY git fails instead of prompting anyway.knqyf263 commentedon Aug 6, 2026
@nikpivkin I tried a small proof of concept that replaces only go-getter's Git getter in the client-specific getter map:
The Trivy-specific getter sets
GIT_TERMINAL_PROMPT=0only on each Git child process. The prototype confirmed that the Git child receives the variable while Trivy's process environment remains unchanged.However, implementing this getter entirely in Trivy would require copying most of go-getter's Git logic, including its handling of refs, shallow clones, SSH keys, checkout, and submodules.
If go-getter allowed callers to add environment variables to its Git commands, Trivy could continue using the existing
GitGetter. Conceptually, it could look like this:Envis only an illustrative API. The exact API should be discussed with the go-getter maintainers.What do you think about opening an issue in
hashicorp/go-getterfirst? If the maintainers are open to this, we could follow up with a small PR. This would avoid maintaining a copy ofGitGetterin Trivy.nikpivkin commentedon Aug 6, 2026
Yes, I'll open an issue, and if the maintainers approve it, I can start working on the implementation. But I'm afraid we might get rejected or not receive a response at all, since some HashiCorp packages don't accept feature requests because they're primarily intended for internal tools.