fix(config): reject path-traversal in version_files (closes #181) #190
No reviewers
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit!190
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/181-version-files-path-traversal"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #181.
Why
Sprint 5 security audit (#156) flagged that
version_files:config accepts arbitrary paths without../rejection. A malicious config likeversion_files: [../../../etc/passwd]would be read + text-parsed bymanifest-check.sh, leaking the file contents into the rolling PR body or release notes.Severity: LOW-MEDIUM per audit framing (information disclosure only, requires a poisoned config merged into the consumer repo). Static config-validation shifts the failure earlier than runtime sandboxing.
What changed
scripts/lib/config.shconfig_validate: add awhile-loop overconfig_get_version_filesoutput that rejects:/etc/passwd)....//../../The match patterns are bash-glob (
==) not regex — see file comments for the exact shape. Critically, it does NOT false-match on:.hidden(single dot prefix)..hidden(double-dot prefix in filename, no/follows)dir/.config(dot-prefix file in subdir)Test coverage (11 new tests + mutation-verify, suite 408/0)
5 rejection tests + 5 accept tests + 1 mixed-with-one-bad rejection (no partial-validation).
Mutation-verify (neuter the guard with
if false; then return 1; fi):Composition
What this PR will NOT do
subdir/VERSION,src/version.txt,.versionmanifest-check.sh(static validation is the audit's recommendation)Refs
scripts/manifest-check.shlines 112-139 (audit-flagged code; the validation runs upstream at config-load, catching the input before it reaches manifest-check)🤖 Generated with Claude Code
https://claude.ai/code/session_01LUEggQMJjaizj2nFVofeyH
APPROVED — path-traversal validation in version_files (closes #181)
The sister remediation to #180, same config-boundary discipline. Verified + mutation-verified. 408/408. FF-feasible (up-to-date, no rebase needed).
The fix is correct + precise ✅
At
config_validate, per version_files entry:.., leading../, trailing/.., interior/../— plus absolute paths. Covers the poisonedversion_files: [../../etc/secret]attack named in #181...only at path boundaries, so it correctly accepts..hidden(a filename that starts with..) and.version(dot-prefix file). A naive*..*denylist would over-reject both. The accept-tests (#8.version, #9..hidden) lock that distinction — that's the careful part of path validation, and it's right.Mutation-verified ✅
Neutering both guards (
if false) reds all 6 rejection tests (absolute / leading / interior / trailing / bare / no-partial) while all 5 accept tests stay green — including..hiddenand.version. So the guards are load-bearing and don't over-reject valid dot-containing filenames. Comprehensive matrix.The Sprint-5 audit remediation closes
#180 (sed-injection allowlist) + #181 (path-traversal) are the two findings from the #156 security audit — both now remediated as config-boundary input validation, both mutation-verified. The audit → trace → defense-in-depth loop closes cleanly on both. Clean to merge. 🎯