fix(tools): parse bash option grammar before extracting the -c script
The guard's _shell_script_arg treated any leading option containing 'c' as -c and looked no further, so 'bash -o pipefail -c "git checkout main"' returned None and the script was never scanned (fail-open). approval.py's _bash_exec_payload already parses bash's real option grammar (-O/-o consume operands, short-option bundles, --init-file); delegate to it instead of keeping a second, weaker parser.
This commit is contained in:
parent
4cc3ea01f6
commit
bb311b3951
|
|
@ -80,6 +80,8 @@ class TestBlocksMutationsInSourceRepo:
|
|||
"/usr/bin/git checkout main",
|
||||
"sh -c 'git checkout main'",
|
||||
"bash -lc 'git switch main'",
|
||||
"bash -o pipefail -c 'git checkout main'",
|
||||
"bash +O extglob -c 'git checkout main'",
|
||||
],
|
||||
)
|
||||
def test_wrappers_and_nested_shells(self, repo, command):
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from dataclasses import dataclass, field
|
|||
from pathlib import Path
|
||||
|
||||
from tools.approval import (
|
||||
_bash_exec_payload,
|
||||
_deobfuscate_shell_word_for_detection,
|
||||
_iter_shell_command_starts,
|
||||
_read_shell_word,
|
||||
|
|
@ -308,14 +309,16 @@ def _cd_target(executable: str, args: list[str], cwd: Path) -> Path | None:
|
|||
|
||||
|
||||
def _shell_script_arg(args: list[str]) -> str | None:
|
||||
for index, arg in enumerate(args):
|
||||
if arg == "--":
|
||||
break
|
||||
if arg.startswith("-") and "c" in arg[1:]:
|
||||
return args[index + 1] if index + 1 < len(args) else None
|
||||
if not arg.startswith("-"):
|
||||
break
|
||||
return None
|
||||
"""Return the script string owned by a shell's ``-c``, if present.
|
||||
|
||||
Delegates to approval.py's ``_bash_exec_payload``, which parses bash's
|
||||
real option grammar (``-O/-o`` consume the next argument, short-option
|
||||
bundles, ``--init-file``/``--rcfile``). A naive "leading option containing
|
||||
'c'" scan fails open on ``bash -o pipefail -c '<script>'`` — the ``-o``
|
||||
operand hides the ``-c`` and the script is never scanned.
|
||||
"""
|
||||
has_c, payload = _bash_exec_payload(args)
|
||||
return payload if has_c else None
|
||||
|
||||
|
||||
def _heredoc_specs(line: str) -> list[_Heredoc]:
|
||||
|
|
|
|||
Loading…
Reference in New Issue