fix: cover secret_access_key/aws_secret_access_key multi-segment key patterns

The bounded key prefix pattern (api_key=/secret_key= etc.) avoids
monkey/turkey false positives, but compound keys like secret_access_key
and aws_secret_access_key only matched on the access_key= suffix, leaking
the secret_ / aws_secret_ prefix. Added these as explicit alternations.

Also added bearer_token and secret_token to the token prefix list.
This commit is contained in:
Patrick Buckley
2026-07-05 22:51:24 +00:00
parent bfcfb0c791
commit c5ff3147ce
2 changed files with 11 additions and 7 deletions
+8 -4
View File
@@ -142,9 +142,12 @@ _CREDENTIAL_PATTERNS: list[tuple[re.Pattern[str], str]] = [
# The trailing _? allows both snake_case and compact forms (api_key / apikey).
# Bare key=/token= are included as alternatives so standalone assignments like
# key=<20+ chars> still match.
# Multi-segment keys like secret_access_key and aws_secret_access_key are
# included explicitly so the prefix doesn't leak as "secret_".
(
re.compile(
r"(?:(?:api|secret|session|auth|encryption|signing|private|public|access)_?key|"
r"(?:(?:api|secret|session|auth|encryption|signing|private|public|access|"
r"secret_access|aws_secret_access)_?key|"
r"(?<![a-zA-Z0-9_])key)="
r"[a-zA-Z0-9]{20,}"
),
@@ -152,7 +155,7 @@ _CREDENTIAL_PATTERNS: list[tuple[re.Pattern[str], str]] = [
),
(
re.compile(
r"(?:(?:access|refresh|auth|api|session)_?token|"
r"(?:(?:access|refresh|auth|api|session|bearer|secret)_?token|"
r"(?<![a-zA-Z0-9_])token)="
r"[a-zA-Z0-9]{20,}"
),
@@ -458,7 +461,7 @@ _BUILTIN_OG_PATTERNS: list[OutputGuardPatternDef] = [
category="credentials",
risk_level="high",
compiled=re.compile(
r"(?:(?:access|refresh|auth|api|session)_?token|"
r"(?:(?:access|refresh|auth|api|session|bearer|secret)_?token|"
r"(?<![a-zA-Z0-9_])token)="
r"[a-zA-Z0-9]{20,}"
),
@@ -473,7 +476,8 @@ _BUILTIN_OG_PATTERNS: list[OutputGuardPatternDef] = [
category="credentials",
risk_level="high",
compiled=re.compile(
r"(?:(?:api|secret|session|auth|encryption|signing|private|public|access)_?key|"
r"(?:(?:api|secret|session|auth|encryption|signing|private|public|access|"
r"secret_access|aws_secret_access)_?key|"
r"(?<![a-zA-Z0-9_])key)="
r"[a-zA-Z0-9]{20,}"
),
@@ -64,11 +64,11 @@ const _CREDENTIAL_REPLACEMENTS = [
// like "monkey=" or "turkey=". Bare "token=" included via negative
// lookbehind so standalone assignments still match (token=abcdef...)
// without matching word suffixes like "over_tokenized=".
[/(?:(?:access|refresh|auth|api|session)_?token|(?<![a-zA-Z0-9_])token)=[a-zA-Z0-9]{20,}/g, "[REDACTED:api_key]"],
[/(?:(?:access|refresh|auth|api|session|bearer|secret)_?token|(?<![a-zA-Z0-9_])token)=[a-zA-Z0-9]{20,}/g, "[REDACTED:api_key]"],
// key=<value> (20+). Same bounded prefix approach: api_key=/secret_key= etc.
// but not monkey= or turkey=. Bare "key=" included with negative lookbehind.
// The _? allows both snake_case and compact forms.
[/(?:(?:api|secret|session|auth|encryption|signing|private|public|access)_?key|(?<![a-zA-Z0-9_])key)=[a-zA-Z0-9]{20,}/g, "[REDACTED:api_key]"],
// Multi-segment keys secret_access_key / aws_secret_access_key included explicitly.
[/(?:(?:api|secret|session|auth|encryption|signing|private|public|access|secret_access|aws_secret_access)_?key|(?<![a-zA-Z0-9_])key)=[a-zA-Z0-9]{20,}/g, "[REDACTED:api_key]"],
];
// ---------------------------------------------------------------------------