Skip to content

fix(ingest): reject option-shaped --base-ref before invoking git#4

Merged
tzone85 merged 1 commit into
mainfrom
harden/git-heuristic-baseref-injection
Jun 11, 2026
Merged

fix(ingest): reject option-shaped --base-ref before invoking git#4
tzone85 merged 1 commit into
mainfrom
harden/git-heuristic-baseref-injection

Conversation

@tzone85

@tzone85 tzone85 commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Summary

  • safeGitRef rejects empty refs, --, and any ref starting with - at the adapter boundary, returning a wrapped ErrInvalidBaseRef.
  • git diff invocation gains a trailing -- so the rev/pathspec boundary is explicit.
  • No shell was ever involved (exec.Command), so classic shell injection wasn't on the table. The actual risk: git's argument parser treats anything starting with - as an option flag regardless of position. Today git diff happens to reject --upload-pack=…, --exec-path=…, -HEAD, -- — but relying on the downstream tool's error handling is fragile.

TDD

RED first: TestGitHeuristic_RejectsOptionLikeBaseRef table test for 4 option-shaped baserefs. Initial assertion against ErrInvalidBaseRef failed-to-compile (undefined symbol) — proves the test was driving the new sentinel, not git's downstream error.

GREEN: defined ErrInvalidBaseRef, safeGitRef, and the adapter-boundary check. All 4 sub-tests pass.

Test plan

  • go test -race ./... — all packages green
  • bash scripts/cover_check.sh — PASS, ingest 95.2% (target 87), global 88.0% (target 87)
  • golangci-lint run — 0 issues

git_heuristic concatenates the operator-supplied --base-ref into
"<ref>..HEAD" and "<ref>:<path>" and feeds them to `git diff` /
`git show` via exec.Command. There's no shell, so classic shell
injection was never on the table — but git's own argument parser
treats anything starting with `-` as an option flag regardless of
position. Today git diff happens to reject the option-shapes we
care about ("--upload-pack=…", "--exec-path=…", "-HEAD", "--"),
but relying on the downstream tool's error handling is fragile:
a future git version or a different subcommand could turn a
rejected flag into an accepted one.

Now safeGitRef rejects empty refs, refs equal to "--", and any ref
starting with "-" at the adapter boundary, returning a wrapped
ErrInvalidBaseRef so callers can distinguish input rejection from
git-side failure. The `git diff` invocation also gains a trailing
"--" so the rev/pathspec boundary is explicit, belt-and-braces.

Coverage gate: ingest 95.2% (target 87), global 88.0% (target 87).
@tzone85 tzone85 merged commit 3b0e72b into main Jun 11, 2026
2 checks passed
@tzone85 tzone85 deleted the harden/git-heuristic-baseref-injection branch June 11, 2026 09:20
tzone85 added a commit that referenced this pull request Jun 11, 2026
Adds an Unreleased section to CHANGELOG.md covering the five
sequential PRs that landed today:
- #2 chore(security): bump x/sys for GO-2026-5024
- #3 fix(api): validate tenant id at route boundary
- #4 fix(ingest): reject option-shaped --base-ref
- #5 fix(mempalace): validate Kind/Tenant/Key against path traversal
- #6 chore(supply-chain): pin govulncheck + base images by digest

Updates README Status to mention the hardening pass and replaces a
stale `§9` design-spec cross-reference with the section's actual
name (per the project's doc-style rule against the § symbol).

No code changes, no behaviour changes — pure documentation refresh
for the audit story.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant