Context
CodeQL reports 3 high-severity js/second-order-command-line-injection alerts in src/resolve.ts on main. They are pre-existing in the git resolver (NOT introduced by the discovery or npm features — those are tracked separately). Source-descriptor fields (repo, url, ref, sha) flow into the git argv via execFileSync. execFileSync avoids a shell, but git itself interprets a leading-- argument as an option — e.g. a ref of --upload-pack=<cmd> or an --output=… value becomes a flag (second-order argument injection).
This is the "separate PR" agreed during review for the pre-existing git alerts.
Alert locations (src/resolve.ts)
defaultGitRunner — execFileSync("git", args, …) (~line 20).
git clone --filter=blob:none --no-checkout <url> … / git fetch … origin built from source.url/repo (~lines 122/128).
git checkout --detach <wanted> where wanted = source.sha ?? source.ref ?? "HEAD" (~lines 137–138).
Tasks
Acceptance criteria
- The 3 CodeQL alerts are resolved (no high
second-order-command-line-injection on the branch).
- Option-like
repo/url/ref/sha are rejected with SourceError (tests).
src/** stays at 100% coverage; quire validate clean.
References
Context
CodeQL reports 3 high-severity
js/second-order-command-line-injectionalerts insrc/resolve.tsonmain. They are pre-existing in the git resolver (NOT introduced by the discovery or npm features — those are tracked separately). Source-descriptor fields (repo,url,ref,sha) flow into thegitargv viaexecFileSync.execFileSyncavoids a shell, butgititself interprets a leading--argument as an option — e.g. arefof--upload-pack=<cmd>or an--output=…value becomes a flag (second-order argument injection).This is the "separate PR" agreed during review for the pre-existing git alerts.
Alert locations (
src/resolve.ts)defaultGitRunner—execFileSync("git", args, …)(~line 20).git clone --filter=blob:none --no-checkout <url> …/git fetch … originbuilt fromsource.url/repo(~lines 122/128).git checkout --detach <wanted>wherewanted = source.sha ?? source.ref ?? "HEAD"(~lines 137–138).Tasks
reqArgguard (src/sources.ts— added in feat: resolve npm sources via npm pack #3; rejects values beginning with-) to the git source fields innormalizeSource: apply togithub.repo,git.url,git-subdir.url,url.url.ref/shaagainst option-like values (these are not validated innormalizeSourcetoday) — reject a leading-before they reachgit checkout. (Note:git checkout -- <ref>does not accept--cleanly before a ref, so prefer rejection over an argv separator.)resolveSourcecallsnormalizeSourcebefore any git invocation (it does — keep it that way).repo/url/ref/shabeginning with-→SourceError).main(do NOT fold into feat: plugin discovery (search npm/GitHub for compatible plugins) #2/feat: resolve npm sources via npm pack #3).Acceptance criteria
second-order-command-line-injectionon the branch).repo/url/ref/shaare rejected withSourceError(tests).src/**stays at 100% coverage;quire validateclean.References
js/second-order-command-line-injection,src/resolve.ts:20+:77).reqArg+ FR-004-CON-3 in feat: resolve npm sources via npm pack #3.