Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions skillopt_sleep/staging.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@
),
"[REDACTED_PRIVATE_KEY]",
),
# Azure SAS tokens (URL query param: ?sig=<base64>&...)
(re.compile(r"(?i)\bsig=[A-Za-z0-9%+/]{10,}"), "[REDACTED_SAS_SIG]"),
# Azure Storage account keys (base64, typically 88 chars)
(re.compile(r"(?i)AccountKey=[A-Za-z0-9+/=]{20,}"), "[REDACTED_STORAGE_KEY]"),
# Connection-string passwords (Password=...; up to semicolon/quote/whitespace)
(re.compile(r"(?i)\bPassword=[^;\"'\s]{6,}"), "[REDACTED_DB_PASS]"),
Comment on lines +52 to +56
)


Expand Down
40 changes: 40 additions & 0 deletions tests/test_staging_redaction_azure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""Tests for the additional Azure secret redaction patterns in staging.

``redact_secrets`` scrubs credential-looking substrings before persisting any
free text to the staging directory. This covers the newly added Azure SAS
signature, storage account key, and connection-string password patterns.
"""
from __future__ import annotations

from skillopt_sleep.staging import redact_secrets


def test_azure_sas_signature_redacted() -> None:
url = "https://acct.blob.core.windows.net/c/b?sig=abcDEF123%2Bxyz789QQ&se=2026"
out = redact_secrets(url)
assert "[REDACTED_SAS_SIG]" in out
assert "abcDEF123" not in out


def test_storage_account_key_redacted() -> None:
conn = "DefaultEndpointsProtocol=https;AccountKey=aB3dEfGhIjKlMnOpQrStUvWx==;"
out = redact_secrets(conn)
assert "[REDACTED_STORAGE_KEY]" in out
assert "aB3dEfGhIjKlMnOpQrStUvWx" not in out


def test_connection_string_password_redacted() -> None:
conn = "Server=db;Password=Sup3rSecret!;Database=app"
out = redact_secrets(conn)
assert "[REDACTED_DB_PASS]" in out
assert "Sup3rSecret" not in out


def test_recurses_into_containers() -> None:
payload = {"logs": ["ok", "AccountKey=aB3dEfGhIjKlMnOpQrStUvWx=="]}
out = redact_secrets(payload)
assert "[REDACTED_STORAGE_KEY]" in out["logs"][1]


Comment on lines +26 to +38
def test_plain_text_unchanged() -> None:
assert redact_secrets("the quick brown fox jumps") == "the quick brown fox jumps"