From 321cbcc2e2d702c0acf177f57720f4c5628c3bcb Mon Sep 17 00:00:00 2001 From: kshitij <82637225+kshitijk4poor@users.noreply.github.com> Date: Sat, 1 Aug 2026 15:43:34 +0530 Subject: [PATCH] test(redact): add YAML ReDoS test, strengthen existing test with keyword MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Relax timing bound from 1.0s to 2.0s (CI machine robustness). - Add test_long_dotted_run_with_keyword_completes_fast: includes a secret keyword so the pre-gate does NOT skip _CFG_DOTTED_RE — directly exercises the possessive-quantifier regex, not just the pre-gate. - Add test_yaml_assign_redos_resistance: _YAML_ASSIGN_RE was modified but had no ReDoS test — add 100-line stress input. - Add test_yaml_assign_secret_still_redacted: verify YAML matching behavior preserved with possessive quantifiers. --- tests/agent/test_redact.py | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/tests/agent/test_redact.py b/tests/agent/test_redact.py index 3d40be4e3f..68307c7381 100644 --- a/tests/agent/test_redact.py +++ b/tests/agent/test_redact.py @@ -560,7 +560,22 @@ class TestConfigKeyRedosResistance: text = ".".join(["segment"] * 100) + " end" t0 = time.perf_counter() assert redact_sensitive_text(text) == text - assert time.perf_counter() - t0 < 1.0 + assert time.perf_counter() - t0 < 2.0 + + def test_long_dotted_run_with_keyword_completes_fast(self): + """Exercise _CFG_DOTTED_RE directly (bypasses the keyword pre-gate). + + The pre-gate skips the regex when no secret keyword is present, so + test_long_dotted_run_completes_fast only guards the pre-gate. This + test includes a keyword but no '=' so the regex runs and must still + complete quickly thanks to the possessive quantifiers. + """ + import time + + text = ".".join(["segment"] * 100) + ".token end" + t0 = time.perf_counter() + assert redact_sensitive_text(text) == text + assert time.perf_counter() - t0 < 2.0 def test_long_dotted_secret_still_redacted(self): # Possessive quantifiers must not change matching behavior. @@ -569,6 +584,25 @@ class TestConfigKeyRedosResistance: assert "Sup3rS3cret!" not in result assert ".password=" in result + def test_yaml_assign_redos_resistance(self): + """_YAML_ASSIGN_RE must not backtrack excessively on long inputs.""" + import time + + # 100 lines of a long dotted key with a secret keyword but no + # matching colon-value form — stresses the regex without matching. + line = "a." * 50 + "token not_an_assignment" + text = "\n".join([line] * 100) + t0 = time.perf_counter() + redact_sensitive_text(text) + assert time.perf_counter() - t0 < 2.0 + + def test_yaml_assign_secret_still_redacted(self): + # Possessive quantifiers must not change YAML matching behavior. + text = "spring.datasource.password: hunter2" + result = redact_sensitive_text(text) + assert "hunter2" not in result + assert "password:" in result + class TestXaiToken: KEY = "xai-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstu"