Skip to content

Strip exec-class keys from sanitized git config#128

Merged
JAORMX merged 2 commits intomainfrom
sec/git-sanitizer-exec-keys
Apr 17, 2026
Merged

Strip exec-class keys from sanitized git config#128
JAORMX merged 2 commits intomainfrom
sec/git-sanitizer-exec-keys

Conversation

@JAORMX
Copy link
Copy Markdown
Contributor

@JAORMX JAORMX commented Apr 17, 2026

Summary

SanitizeConfig preserved entire [core], [merge], [diff], [submodule], and [lfs] sections once the section name was on the allowlist. A malicious host .git/config could therefore smuggle command-execution keys through the sanitizer into the VM snapshot, where git (or git-lfs) would honor them on the next operation inside the guest — giving RCE on content an agent might fetch via git clone / git fetch inside the VM.

Three distinct gaps fixed, each with dedicated tests:

  1. Section-scoped denylist for exec-class keys: core.sshCommand, core.pager, core.editor, core.fsmonitor, core.alternateRefsCommand, core.hooksPath, merge.<name>.driver, diff.external, diff.<name>.{driver,textconv,command}, and submodule.<name>.update (CVE-2017-1000117). Applied in filterLine before section-specific handling; matched case-insensitively.

  2. [lfs] dropped from allowedSections. [lfs \"customtransfer.<name>\"] carries a path key that git-lfs executes, and parseSectionName collapses subsections so a per-key denylist cannot distinguish lfs.customtransfer.*.path from a hypothetical benign lfs.path. LFS configuration typically lives in ~/.gitconfig, so stripping the section from the repo-local snapshot does not affect real LFS workflows.

  3. Continuation lines belonging to denied keys are dropped. A denied key with a trailing backslash (sshCommand = ssh \\) previously suppressed the key line but still emitted the attacker-controlled continuation lines as orphan fragments under the allowed section. Track a swallowContinuation flag alongside inContinuation.

Test plan

  • task fmt && task lint && task test — all green
  • Targeted TestSanitizeConfig covers: each exec-class key per section, case-insensitive matching, subsection form ([merge \"driver1\"], [diff \"pdf\"], [submodule \"lib\"]), LFS customtransfer stripping, continuation-after-denied-key dropping, and continuation reset after a subsequent kept line
  • Benign core.* keys (autocrlf, quotepath, whitespace, etc.) still pass through
  • Existing user/remote/submodule URL sanitization behavior unchanged
  • Headless end-to-end: bbox claude-code --no-mcp --exec /bin/sh -- -c 'git config --list' inside a VM shows only safe keys; no core.sshCommand / core.pager / [lfs] / merge.driver in the output

🤖 Generated with Claude Code

JAORMX and others added 2 commits April 17, 2026 09:51
Picks up the security hardening series from
https://github.com/stacklok/go-microvm/releases/tag/v0.0.32 —
symlink-safe rootfs hooks, whiteout path re-validation during
OCI layer apply, DNS answer filtering by CNAME bailiwick, TTL
clamp on dynamic egress rules, relay frame-length cap, non-IPv4
drop under deny-default, hosted-service HTTP timeouts,
stale-runner identity guard, symmetric provider wiring, and
per-file integrity manifest on the extract cache.

No brood-box code changes required — all hardening is wired
through interfaces brood-box already uses.

Verified end-to-end: VM boots, hooks run, workspace round-trip
flushes, DNS egress allows api.anthropic.com and denies unknown
hosts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SanitizeConfig preserved entire [core], [merge], [diff], [submodule],
and [lfs] sections once the section name was on the allowlist. This
let a malicious host .git/config smuggle command-execution keys into
the snapshot, where git (or git-lfs) would honor them on the next
operation inside the VM.

Fixes three distinct gaps:

1. Section-scoped denylist for exec-class keys: core.sshCommand,
   core.pager, core.editor, core.fsmonitor, core.alternateRefsCommand,
   core.hooksPath, merge.<name>.driver, diff.external,
   diff.<name>.{driver,textconv,command}, and submodule.<name>.update
   (CVE-2017-1000117). Applied in filterLine before section-specific
   handling; matched case-insensitively.

2. Drop [lfs] from allowedSections. The [lfs "customtransfer.<name>"]
   form carries a `path` key that git-lfs executes, and
   parseSectionName collapses subsections so a per-key denylist cannot
   distinguish lfs.customtransfer.*.path from a hypothetical benign
   lfs.path. LFS configuration typically lives in ~/.gitconfig so
   stripping the section from the repo-local snapshot config does not
   affect real LFS workflows.

3. Drop continuation lines belonging to denied keys. A denied key with
   a trailing backslash (`sshCommand = ssh \`) previously suppressed
   the key line but still emitted attacker-controlled continuation
   lines as orphan fragments under the allowed section. Track a
   swallowContinuation flag alongside inContinuation to gate the
   continuation branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@JAORMX JAORMX merged commit ed4755c into main Apr 17, 2026
8 checks passed
@JAORMX JAORMX deleted the sec/git-sanitizer-exec-keys branch April 17, 2026 07:28
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