diff --git a/agent/redact.py b/agent/redact.py index c69003fcf..307e5dc3a 100644 --- a/agent/redact.py +++ b/agent/redact.py @@ -106,6 +106,7 @@ _PREFIX_PATTERNS = [ r"brv_[A-Za-z0-9]{10,}", # ByteRover API key r"xai-[A-Za-z0-9]{30,}", # xAI (Grok) API key r"ntn_[A-Za-z0-9]{10,}", # Notion internal integration token + r"fw_[A-Za-z0-9]{30,}", # Fireworks AI API key ] # ENV assignment patterns: KEY=value where KEY contains a secret-like name. diff --git a/tests/agent/test_redact.py b/tests/agent/test_redact.py index afa841cb0..4174cd58a 100644 --- a/tests/agent/test_redact.py +++ b/tests/agent/test_redact.py @@ -886,3 +886,25 @@ class TestFileReadNonReusableRedaction: out = redact_sensitive_text(f"key: {self.SK}", force=True, file_read=True) assert "«redacted:sk-…»" in out assert self.SK not in out + + +class TestFireworksToken: + KEY = "fw_" + "A" * 40 + + def test_bare_token_masked(self): + result = redact_sensitive_text(f"fireworks error: key {self.KEY}", force=True) + assert self.KEY not in result + assert "fw_AA" in result + + def test_env_assignment_masked(self): + result = redact_sensitive_text(f"FIREWORKS_API_KEY={self.KEY}", force=True) + assert self.KEY not in result + + def test_too_short_not_masked(self): + short = "fw_tooshort" + result = redact_sensitive_text(f"text {short} here", force=True) + assert short in result + + def test_prefix_visible_in_masked_output(self): + result = redact_sensitive_text(self.KEY, force=True) + assert result.startswith("fw_AA")