fix(security): address PR #416 review comments on injection guardrails (#422)

1. test_injection_is_truncated: pad inputs beyond SUSPICIOUS_DESCRIPTION_LENGTH so truncation is actually exercised (previously all corpus entries were shorter than the threshold, making the assertion a no-op). 2. test_injection_is_logged: remove permissive 'len > threshold' conditional that skipped the assertion for short inputs. All red-team corpus entries contain injection phrases and must trigger warnings unconditionally. 3. sanitize_text: log boundary-marker escaping so inputs containing only boundary markers (no other injection phrases) still produce a warning. Also treat boundary presence as suspicious for length-capping purposes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Juan Manuel Servera committed Jun 12, 2026 at 13:50 UTC 13afa9531377fd973e3bd3f93ed3fcef3c305403
2 files changed +28 -17
scripts/sanitize_repo_content.py
+10 -2
@@ -83,11 +83,14 @@ def sanitize_text(
83 return ""
84 if not isinstance(text, str):
85 text = str(text)
86 - sanitized = _escape_untrusted_boundaries(text.lstrip())
86 + stripped = text.lstrip()
87 + has_boundary = BOUNDARY_CLOSE in stripped or BOUNDARY_OPEN in stripped
88 + sanitized = _escape_untrusted_boundaries(stripped)
89 lowered = sanitized.lower()
90 suspicious_matches = [phrase for phrase in INJECTION_PHRASES if phrase in lowered]
91
90 - limit = min(SUSPICIOUS_DESCRIPTION_LENGTH, max_length) if suspicious_matches else max_length
92 + is_suspicious = bool(suspicious_matches) or has_boundary
93 + limit = min(SUSPICIOUS_DESCRIPTION_LENGTH, max_length) if is_suspicious else max_length
94 truncated = _truncate(sanitized, limit)
95
96 if suspicious_matches:
@@ -96,6 +99,11 @@ def sanitize_text(
99 label,
100 ", ".join(suspicious_matches),
101 )
102 + if has_boundary:
103 + LOGGER.warning(
104 + "Suspicious %s contained [boundary marker(s)] that were escaped",
105 + label,
106 + )
107 return truncated
108
109
tests/test_prompt_injection_redteam.py
+18 -15
@@ -58,16 +58,20 @@ class TestRedTeamSanitizeText:
58
59 @pytest.mark.parametrize("injection", RED_TEAM_INJECTIONS)
60 def test_injection_is_truncated(self, injection: str) -> None:
61 - result = sanitize_text(injection, max_length=500, label="redteam")
62 - # Should either be truncated (suspicious) or have boundary markers escaped
63 - if BOUNDARY_CLOSE in injection or BOUNDARY_OPEN in injection:
64 - assert BOUNDARY_CLOSE not in result
65 - assert BOUNDARY_OPEN not in result
66 - # Injections longer than the suspicious threshold must be truncated
67 - if len(injection) > SUSPICIOUS_DESCRIPTION_LENGTH:
68 - assert len(result) <= SUSPICIOUS_DESCRIPTION_LENGTH, (
69 - f"Long suspicious input was not truncated: {len(result)} > {SUSPICIOUS_DESCRIPTION_LENGTH}"
70 - )
61 + # Pad input beyond SUSPICIOUS_DESCRIPTION_LENGTH to exercise truncation
62 + long_input = injection + " " + "A" * SUSPICIOUS_DESCRIPTION_LENGTH
63 + result = sanitize_text(long_input, max_length=500, label="redteam")
64 + # Boundary markers must never appear in output
65 + assert BOUNDARY_CLOSE not in result, (
66 + f"Boundary close marker leaked through: {result!r}"
67 + )
68 + assert BOUNDARY_OPEN not in result, (
69 + f"Boundary open marker leaked through: {result!r}"
70 + )
71 + # Suspicious long inputs must be capped to the suspicious threshold
72 + assert len(result) <= SUSPICIOUS_DESCRIPTION_LENGTH, (
73 + f"Suspicious input was not truncated: {len(result)} > {SUSPICIOUS_DESCRIPTION_LENGTH}"
74 + )
75
76 @pytest.mark.parametrize("injection", RED_TEAM_INJECTIONS)
77 def test_injection_is_logged(self, injection: str, caplog) -> None:
@@ -75,11 +79,10 @@ class TestRedTeamSanitizeText:
79
80 with caplog.at_level(logging.WARNING):
81 sanitize_text(injection, max_length=500, label="redteam")
78 - # All entries longer than the threshold should trigger a warning
79 - if len(injection) > SUSPICIOUS_DESCRIPTION_LENGTH:
80 - assert "Suspicious" in caplog.text or "[boundary" in caplog.text, (
81 - f"Long suspicious input did not trigger a warning log"
82 - )
82 + # Every red-team injection must trigger a warning regardless of length
83 + assert "Suspicious" in caplog.text or "[boundary" in caplog.text, (
84 + f"Injection was not logged as suspicious: {injection!r}"
85 + )
86
87 @pytest.mark.parametrize("injection", RED_TEAM_INJECTIONS)
88 def test_description_sanitizer_catches_injection(self, injection: str) -> None: