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: