fix(secret-guard): treat env as a dump only when no command follows
`env -u VAR cmd` and `env FOO=bar cmd` exec a command with a modified environment and print nothing themselves. The old rule matched any `env` token followed anywhere later by a pipe into a filter, so it blocked the documented 1Password write path and forced a `(unset VAR; cmd)` workaround. False positives only — never a leak — but a guard people route around is a guard on its way out. The rule now denies only when everything after `env` is exhausted by options and VAR=value assignments. That is strictly the dumping shape, and it also closes a hole the two previous rules left open: `env FOO=bar` with no command word prints the whole environment and was allowed. Three new deny/allow pairs pin it, including the 1Password write shape that motivated the report. 20 cases now, up from 14, all passing. Closes #25 Bump-Type: patch
This commit is contained in:
+12
-5
@@ -50,11 +50,18 @@ if printf '%s' "$CMD" | grep -Eqi '(^|[;&|]|\s)op\s+document\s+get\b'; then
|
||||
fi
|
||||
|
||||
# Raw env/secret-file dumps (infra#228/#229 root cause).
|
||||
if printf '%s' "$CMD" | grep -Eqi '(^|[;&|]|\s)env(\s|$).*\|.*grep'; then
|
||||
deny "Blocked: 'env | grep' prints matching values in full. Use an existence-only check: [ -n \"\$VAR\" ] && echo set"
|
||||
fi
|
||||
if printf '%s' "$CMD" | grep -Eq '(^|[;&|])[[:space:]]*env[[:space:]]*($|[;&|])'; then
|
||||
deny "Blocked: bare 'env' prints every variable's value, including secrets. Use an existence-only check: [ -n \"\$VAR\" ] && echo set"
|
||||
#
|
||||
# `env` is a dump only when nothing but options and VAR=value assignments
|
||||
# follow it. `env -u VAR cmd` and `env FOO=bar cmd` EXEC a command with a
|
||||
# modified environment and print nothing themselves — piping those into grep
|
||||
# filters the command's own output, not the environment (#25). The earlier
|
||||
# pattern matched any `env` token followed anywhere later by a pipe into
|
||||
# grep, which blocked the documented 1Password write path
|
||||
# (`env -u OP_SERVICE_ACCOUNT_TOKEN op item create`) and cost a workaround.
|
||||
# Denying only the "no command word follows" shape also catches `env FOO=bar`
|
||||
# with no command, which the two previous rules let through.
|
||||
if printf '%s' "$CMD" | grep -Eqi '(^|[;&|]|[[:space:]])env([[:space:]]+-[iu][[:space:]]*[A-Za-z_][A-Za-z0-9_]*|[[:space:]]+-[iu]|[[:space:]]+[A-Za-z_][A-Za-z0-9_]*=[^[:space:]]*)*[[:space:]]*($|[|;&])'; then
|
||||
deny "Blocked: this 'env' prints every variable's value, including secrets (no command word follows it, so it dumps rather than execs). Use an existence-only check: [ -n \"\$VAR\" ] && echo set. Note 'env -u VAR cmd' and 'env FOO=bar cmd' are allowed — they run a command."
|
||||
fi
|
||||
if printf '%s' "$CMD" | grep -Eqi '(^|[;&|]|\s)printenv\b'; then
|
||||
deny "Blocked: printenv dumps all env values. Use: [ -n \"\$VAR\" ] && echo set"
|
||||
|
||||
Reference in New Issue
Block a user