fix(hide-secrets): keep spaced assignments in scope when shell text follows the value

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
yucheng 2026-09-11 22:11:09 +00:00
parent 04f21ba8ae
commit 802c05904c
2 changed files with 13 additions and 2 deletions

View file

@ -455,6 +455,8 @@ _SHELL_ASSIGNMENT: Final = re.compile(r"(?P<key>[^\s\[#;:=](?:[^:=]*[^\s:=])?)=(
_SHELL_OPERATORS: Final = ";&|"
_SHELL_TRAILER: Final = re.compile(r"\\|#.*|\S+=\S*")
_SCAN_SUFFIX: Final = ".py"
@ -509,9 +511,12 @@ def _parseable_lines(text: str) -> Iterator[str]:
def _lone_value(line: str) -> str | None:
tokens: Final = line.split()
if not tokens or '"' in tokens[0] or (len(tokens) > 1 and not tokens[1].startswith("#")):
if not tokens or '"' in tokens[0]:
return None
return tokens[0].rstrip(_SHELL_OPERATORS)
value: Final = tokens[0].rstrip(_SHELL_OPERATORS)
if len(tokens) == 1 or value != tokens[0] or _SHELL_TRAILER.fullmatch(tokens[1]) is not None:
return value
return None
def _quoted_assignments(text: str) -> tuple[str, ...]:

View file

@ -123,6 +123,9 @@ def test_scan_message_preserves_quoted_benign_identifiers():
("DB_PASSWORD=Zx4Kp9Lm2Qr7Ns3Vt > setup.log", "Zx4Kp9Lm2Qr7Ns3Vt"),
("docker run -e DB_PASSWORD=Zx4Kp9Lm2Qr7Ns3Vt --name app postgres", "Zx4Kp9Lm2Qr7Ns3Vt"),
("password=correcthorsebattery please", "correcthorsebattery"),
("DB_PASSWORD = Zx4Kp9Lm2Qr7Ns3Vt; systemctl restart app", "Zx4Kp9Lm2Qr7Ns3Vt"),
("DB_PASSWORD = Zx4Kp9Lm2Qr7Ns3Vt \\", "Zx4Kp9Lm2Qr7Ns3Vt"),
("DB_PASSWORD = Zx4Kp9Lm2Qr7Ns3Vt DB_HOST=db.internal", "Zx4Kp9Lm2Qr7Ns3Vt"),
],
ids=[
"env-password",
@ -159,6 +162,9 @@ def test_scan_message_preserves_quoted_benign_identifiers():
"redirect-after-the-value",
"docker-flag-after-the-value",
"prose-after-a-shell-assignment",
"spaced-assignment-then-a-shell-command",
"spaced-assignment-then-a-line-continuation",
"spaced-assignment-then-a-second-assignment",
],
)
def test_scan_message_redacts_credentials_assigned_to_credential_keys(content, secret):