Files
2026-07-13 13:12:33 +08:00

105 lines
3.7 KiB
Python

from __future__ import annotations
from opensquilla.safety.secret_redaction import redact_secret_text, redact_secret_value
def test_redact_secret_text_masks_env_assignments_and_provider_keys() -> None:
text = (
"env.OPENROUTER_API_KEY=sk-or-v1-abcdefghijklmnopqrstuvwxyz "
"DASHSCOPE_API_KEY:sk-123456789012345678901234 "
"Authorization: Bearer secret-token"
)
redacted = redact_secret_text(text)
assert "sk-or-v1-abcdefghijklmnopqrstuvwxyz" not in redacted
assert "sk-123456789012345678901234" not in redacted
assert "secret-token" not in redacted
assert "env.OPENROUTER_API_KEY=[REDACTED]" in redacted
assert "DASHSCOPE_API_KEY:[REDACTED]" in redacted
assert "Authorization: Bearer [REDACTED]" in redacted
def test_redact_secret_text_masks_bare_tokenrhythm_keys() -> None:
# Provider errors echo credentials verbatim with no key=value structure
# ("Incorrect API key sk_tr_... provided"); the underscore prefix is
# invisible to the hyphen-anchored sk- patterns.
text = "Incorrect API key sk_tr_FAKEabc123def456ghi789 provided"
redacted = redact_secret_text(text)
assert "sk_tr_FAKEabc123def456ghi789" not in redacted
assert "[REDACTED]" in redacted
def test_redact_secret_text_masks_tokenrhythm_keys_abutting_punctuation() -> None:
# A key glued to '-' or '_' must over-mask, never fail the trailing
# boundary and leak whole (the sk- pattern's tail class behaves the same).
for tail in ("-rotated", "_old"):
redacted = redact_secret_text(f"old key sk_tr_FAKEabc123def456ghi789{tail} replaced")
assert "FAKEabc123def456ghi789" not in redacted, tail
def test_redact_secret_text_masks_quoted_assignment_values() -> None:
text = (
'password: "hunter2hunter2" '
"token = 'abcdefabcdef' "
'api_key="quoted with spaces inside" '
"client_secret: 'unterminated"
)
redacted = redact_secret_text(text)
assert "hunter2hunter2" not in redacted
assert "abcdefabcdef" not in redacted
assert "quoted with spaces inside" not in redacted
assert "unterminated" not in redacted
assert "password:[REDACTED]" in redacted
assert "token=[REDACTED]" in redacted
assert "api_key=[REDACTED]" in redacted
assert "client_secret:[REDACTED]" in redacted
def test_redact_secret_text_keeps_quoted_values_for_non_secret_keys() -> None:
text = 'name: "alice" retry_count = \'3\''
assert redact_secret_text(text) == text
def test_redact_secret_text_does_not_mask_token_counters() -> None:
assert redact_secret_text("total_tokens=123 cached_tokens:100") == (
"total_tokens=123 cached_tokens:100"
)
def test_redact_secret_text_masks_non_bearer_authorization_credentials() -> None:
basic = redact_secret_text("Authorization: Basic dXNlcjpwYXNz")
assert "dXNlcjpwYXNz" not in basic
proxy = redact_secret_text("Proxy-Authorization: Basic Zm9vOmJhcg==")
assert "Zm9vOmJhcg==" not in proxy
digest = redact_secret_text('Authorization: Digest username="admin", response="deadbeef"')
assert "deadbeef" not in digest
def test_redact_secret_value_masks_basic_auth_in_string() -> None:
out = redact_secret_value("curl -v ... > Authorization: Basic dXNlcjpwYXNz")
assert "dXNlcjpwYXNz" not in out
def test_redact_secret_value_masks_secret_keys_and_nested_strings() -> None:
payload = {
"api_key": "plain-secret",
"messages": [
{
"content": "debug env.OPENROUTER_API_KEY=sk-or-v1-abcdefghijklmnopqrstuvwxyz"
}
],
}
redacted = redact_secret_value(payload)
assert redacted["api_key"] == "[REDACTED]"
assert "sk-or-v1-abcdefghijklmnopqrstuvwxyz" not in str(redacted)