Skip to content

fix(safety): sanitize newline-based injection patterns - #795

Open
leulAbate wants to merge 8 commits into
ascherj:mainfrom
leulAbate:fix/64-prompt-defense-newline-sanitizer
Open

fix(safety): sanitize newline-based injection patterns#795
leulAbate wants to merge 8 commits into
ascherj:mainfrom
leulAbate:fix/64-prompt-defense-newline-sanitizer

Conversation

@leulAbate

Copy link
Copy Markdown

Summary

safety/prompt_defense.PromptDefense.sanitize() used to strip only template delimiters and angle brackets, so newline-based patterns that is_injection_attempt() already flagged (\n---\n, \nSystem:, \nIgnore ...) passed through the sanitizer unchanged. The two methods disagreed: an input x where is_injection_attempt(x) returned True could survive sanitize(x) intact. This PR reuses the existing INJECTION_PATTERNS list inside sanitize() so both methods reference one canonical list.

Issue

Closes #64

Changes

  • safety/prompt_defense.py: sanitize() now iterates INJECTION_PATTERNS and replaces each match with a single space via re.sub(..., flags=re.IGNORECASE). Angle bracket stripping is kept as defense-in-depth.
  • tests/unit/test_prompt_defense.py: three reproduction tests from the pre-fix commit on this branch are now plain passing tests (xfail markers removed). Added three new tests:
    • test_sanitize_covers_every_injection_pattern — iterates INJECTION_PATTERNS so any newly added pattern is automatically covered by both detector and sanitizer.
    • test_sanitize_preserves_prose_mentioning_system — mid-sentence "system" survives untouched.
    • test_sanitize_preserves_multiparagraph_resume — normal resume with newlines round-trips byte-for-byte.

Testing

  • Unit tests pass (make test-unit) — 37 of 38 pass; the one failure predates this branch (see notes)
  • Integration tests pass (make test-integration) — didn't run locally (no Postgres/Chroma set up); no integration test files touched
  • Linter passes (make lint) — two pre-existing findings on the files I edited, unchanged; my diff introduces none
  • Type checker passes (make typecheck) — mypy clean on safety/prompt_defense.py
  • New/updated tests cover the changes

Screenshots / Demo

N/A — pure library change.

Notes for Reviewers

Design choice — how to neutralize matches: I went with re.sub(pattern, " ", ...) (single space) because it's length-preserving and doesn't concatenate the surrounding characters. Alternatives I considered were dropping the match entirely ("", could join formerly-separated tokens) or replacing with a visible marker like [REMOVED] (more auditable, but changes downstream token counts). Happy to switch if you'd prefer one of those.

sanitize() has no callers today: git grep -n "PromptDefense" outside safety/prompt_defense.py and its test file returns nothing. Fixing it is still correct (it's a public API on a safety class), but the safety pipeline may not be wired into the request path — worth a follow-up issue if that hasn't already been raised.

Pre-existing failures I saw on main before touching anything, and confirmed my changes don't introduce:

  • tests/unit/test_prompt_defense.py::TestPromptDefense::test_whitespace_variations_detected fails on main too. Input "Content\n System : ignore" has spaces before the colon, but INJECTION_PATTERNS[1] (\n\s*(?:System|Human|Assistant):) requires the : to immediately follow the role word. Out of scope for Prompt injection defense doesn't sanitize newline characters in user-supplied resume text #64.
  • ruff I001 on safety/prompt_defense.py (import block ordering) — predates this branch.
  • ruff F841 in tests/unit/test_prompt_defense.py::test_code_blocks_handled (unused local) — predates this branch and lives in a test I didn't modify.

Records selection of issue ascherj#64 (prompt_defense newline sanitizer) and
serves as the setup commit for the Module 3 working branch.
…greement

Three xfail(strict=True) tests showing PromptDefense.sanitize()
leaves newline-based injection patterns intact.
sanitize() only stripped template delimiters and angle brackets, so
patterns is_injection_attempt already flagged (\n---\n, \nSystem:,
\nIgnore ...) passed through unchanged. Iterate INJECTION_PATTERNS
in sanitize() so both methods stay in agreement.

Fixes ascherj#64
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Prompt injection defense doesn't sanitize newline characters in user-supplied resume text

1 participant