Skip to content

Commit 9101cb7

Browse files
committed
Fix: install -t<dir> attached short bypass (sec 114, FN, Codex sweep 5 Q4)
The install walker has its own in-line flag-skip loop that discards every `-*` token (except for the explicit `--target-directory=val` long form). Attached `install -t/tmp src dst` therefore landed in the generic skip branch and never reached the boundary check — install proceeded to copy into `/tmp` with no validation. Verified locally before fix: install -t/tmp src.txt dst.txt # ALLOW (bypass) install -t /tmp src.txt # BLOCK (positional walk catches /tmp) install --target-directory=/tmp # BLOCK (explicit long form) Patch: in the install walker's `-*` arm, recognise `-t?*` attached form before the generic continue-skip and validate the value via `validate_command_path strict "install -t"`. The split form keeps working because the next-token positional walk already validates `/tmp` as a target — no change needed there. Tests: sec 114 in test_bypass_reproducers_pentest_d.sh — two outside-project attached shapes block; in-project attached allowed. Regression: tests/test_guard.sh — 1579/1579. Pre-existing gap; surfaced by Codex sweep 5 Q4. Not introduced by 939c9f4 (extract_option_values is not called from the install walker — install has its own flag-handling code).
1 parent b058a57 commit 9101cb7

2 files changed

Lines changed: 37 additions & 0 deletions

File tree

hooks/lib/detectors/write_targets.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,17 @@ run_write_target_detectors() {
8484
validate_command_path strict "install --target-directory" "${install_tok#*=}"
8585
continue
8686
fi
87+
# Attached short `-t<dir>` (Codex sweep 5 Q4): the
88+
# generic `-*` skip below treated this as a plain flag,
89+
# so `install -t/tmp src.txt dst.txt` slipped past the
90+
# boundary entirely. Split form `install -t /tmp src`
91+
# already blocks because the next-token positional walk
92+
# validates `/tmp` as a target; only the attached form
93+
# needs explicit handling here.
94+
if [[ "$install_tok" == -t?* ]]; then
95+
validate_command_path strict "install -t" "${install_tok#-t}"
96+
continue
97+
fi
8798
case "$install_tok" in
8899
-m|--mode|-o|--owner|-g|--group)
89100
install_skip_next=1 ;;

tests/test_bypass_reproducers_pentest_d.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,3 +1234,29 @@ expect_blocked "cpio -i -D /etc (real)" \
12341234
"cpio -i -D /etc"
12351235

12361236
echo ""
1237+
1238+
# ============================================================
1239+
# 114. install -t<dir> attached short bypass (FN, Codex sweep 5 Q4)
1240+
# ------------------------------------------------------------
1241+
# The install walker has its own in-line flag-skip loop that
1242+
# discards every `-*` token (except for the explicit
1243+
# --target-directory= long form). Attached `install -t/tmp src`
1244+
# fell into the generic skip branch and never reached the
1245+
# boundary check, so the install destination was an
1246+
# unvalidated outside-project path.
1247+
#
1248+
# Split form `install -t /tmp src` already blocked because the
1249+
# next-token positional walk validated `/tmp` as a target.
1250+
# ============================================================
1251+
echo "--- 114. install -t<dir> attached short ---"
1252+
1253+
expect_blocked "install -t/tmp src dst (attached short)" \
1254+
"install -t/tmp src.txt dst.txt"
1255+
expect_blocked "install -t/etc src (system attached)" \
1256+
"install -t/etc src.txt"
1257+
1258+
# In-project attached must still allow.
1259+
expect_allowed "install -t<project> src (attached, in-project)" \
1260+
"install -t$PROJECT src.txt"
1261+
1262+
echo ""

0 commit comments

Comments
 (0)