validate repo_url and harden git argv against option injection#94
Merged
cert-manager-prow[bot] merged 4 commits intoMay 29, 2026
Merged
Conversation
Signed-off-by: Mladen Rusev <mladen.rusev@cyberark.com>
inteon
reviewed
May 29, 2026
Signed-off-by: Mladen Rusev <mladen.rusev@cyberark.com>
inteon
reviewed
May 29, 2026
Signed-off-by: Mladen Rusev <mladen.rusev@cyberark.com>
Member
|
/approve |
Contributor
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: inteon The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
VC-53817 — argument / transport injection via
repo_urlBranch:
VC-53817.A standalone reviewer script is embedded at the bottom of this description
(see verify.sh — click to expand). It is fully sandboxed under
/tmp/klone-vc-53817.*, makes no network calls, and is removed on exit.The vulnerability
klonereadsrepo_urlfromklone.yamlas an opaque string and hands itto
git ls-remoteandgit cloneas a positional argument. Git acceptstwo URL shapes that are not really URLs:
ext::sh -c <cmd>— git's "external transport" helper runs<cmd>as the remote process. Default git config (
protocol.ext.allow=user)permits it when the URL comes from the command line.
-— git's option parser treats it as a flag.--upload-pack=<cmd>is honoured by bothls-remoteandcloneandruns
<cmd>instead of the realgit-upload-pack.Either gives the manifest author arbitrary code execution as the invoking
user.
Three things were missing:
repo_urlbefore it reachesgit.--end-of-options terminator before the URL positional.trusted.
The fix
pkg/mod/index.go—ValidateRepoURLenforces an allow-list and shapecheck before any git invocation. Rejects: empty, leading
-,::substring (helper transports), and anything that is not
https:///http:///ssh:///git:///file:////abs/path/scp-like
user@host:path. Called at the top of the per-sourcecleanFnin
pkg/sync/sync.go.pkg/download/git/clone.go—--terminator inserted beforerepoURLin thegit cloneargv.-c protocol.ext.allow=neverprepended to everygitinvocation, sothe
ext::helper is denied regardless of the host's git config.(
git checkout <hash>is deliberately not given a--, becausethere git would re-interpret the hash as a pathspec.)
pkg/download/git/hash.go—--terminator inserted beforerepoURLinthe
git ls-remoteargv.What we deliberately did not do
We did not set
GIT_PROTOCOL_FROM_USER=0. That would have told git"treat all URLs as not-from-user," which also denies
file://(andseveral other protocols whose default is
allow=user).file://is alegitimate transport for tests, on-disk mirrors, and local vendoring —
blocking it would break existing users. The scheme allow-list plus the
explicit
-c protocol.ext.allow=nevergive us the same protectionwithout the collateral damage.
How to review
Prerequisites
go(1.23+),gitonPATH.the bottom of this description and save its contents to
/tmp/verify-vc-53817.sh.Step 1 — confirm the CVE exists on pre-fix klone
Expected: exit code
1.ext::):VULNERABLEorBLOCKED_BY_HOSTdepending onyour git config. If your host already sets
protocol.ext.allow=never, the disclosed vector is unfireable there;this is still printed as
BLOCKED_BY_HOST(not credit to klone) so theexit code stays
1.--upload-pack):VULNERABLE—/tmp/klone-vc-53817.*/markers/klone-pwned-optinjectwill exist after the run.Step 2 — confirm the fix blocks both vectors
Expected: both vectors
BLOCKED by klone (repo_url validator rejected ...),exit code
0.Step 3 — run the regression tests
go test ./pkg/mod/...Expected: all green. Notable:
TestValidateRepoURLcovers the validator directly — positive cases(https/http/ssh/git/file/abs/scp-like) and negative cases (ext::,
--upload-pack=…, lone-uX,transport_helper::cmd, empty,relative path, bare hostname,
javascript:).Optional — positive smoke test with a real URL
A
file://sync (the scheme most likely to break ifGIT_PROTOCOL_FROM_USER=0had been set) still works:Side-effect statement
The script creates everything under
/tmp/klone-vc-53817.*(includingits own
markers/directory for the PoC payloads). The trap on exitremoves it (set
KEEP_SANDBOX=1to retain). No file outside thatsandbox is created, modified, or deleted at any point. The PoC payloads
write only inside the sandbox, never to
/tmp/klone-pwnedor otherfixed paths.
verify.sh — click to expand the standalone reviewer script
Save the block below to
/tmp/verify-vc-53817.shbefore running thesteps above.