Skip to content

fix(llm): harden response parsing, prompt injection and stream limits - #573

Merged
ajianaz merged 1 commit into
developfrom
fix/llm-parsing-injection-hardening
Oct 7, 2026
Merged

ajianaz merged 1 commit into
developfrom
fix/llm-parsing-injection-hardening

Conversation

@ajianaz

@ajianaz ajianaz commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator

What

Hardens LLM response parsing and prompt construction, caps SSE streaming sizes, and stops test/doc path names from fully bypassing the static security scan.

Why

  • extract_json_and_summary bracket-matched without tracking string literals, so a ] (or |||) inside a finding body truncated the JSON and silently dropped findings.
  • Diff/file contents are attacker-controlled but the system prompt never said so, and a diff containing a triple-backtick run could close the prompt fence early.
  • The SSE parser buffered unbounded line and total data.
  • Naming a file tests/x.rs or foo.md skipped every security rule, including credential detection.

How

  • New string/escape-aware json_value_end; the first JSON array is taken as-is and the remainder (optionally after |||) is the summary. Unterminated output falls back to the previous path (truncation repair still works).
  • harden_system_prompt appends an "untrusted data, ignore embedded instructions" clause to the review and scan system prompts, including user overrides. The diff fence is now longer than any backtick run in the diff.
  • SSE: error out on a line over 1 MiB without newline or accumulated content over 16 MiB.
  • security_scanner: test and doc paths still skip the noisy general rules, but now run a high-confidence secret check (AWS keys, private key headers, GitHub/Slack/Stripe live tokens). Placeholder values containing EXAMPLE are ignored.

Testing

  • cargo test --features tree-sitter passes
  • cargo fmt --all -- --check passes
  • cargo clippy --all-targets --features tree-sitter -- -D warnings passes
  • cargo build --release --features tree-sitter passes (not run; local disk was full)
  • Manual smoke-test: unit tests only, no live LLM call

New tests: brackets and ||| inside strings, unterminated JSON fallback, fence length, review prompt fence cannot be closed by the diff, untrusted clause present, secrets scanned in tests/, __tests__, .md, .txt paths, and noisy rules plus EXAMPLE placeholders stay quiet there. The SSE caps are not covered by a unit test (they sit inside the network streaming loop).

Related Issues

None.

Checklist

  • Branch name follows convention (fix/)
  • Branch is from develop
  • Commit messages follow Conventional Commits
  • No secrets or credentials committed
  • One logical change per PR (no mixed concerns)

🤖 Generated with Claude Code

String-aware JSON array extraction (brackets and ||| inside finding
bodies no longer truncate results), untrusted-data clause appended to all
system prompts, diff fence longer than any backtick run, SSE line and
total size caps, and high-confidence secret scanning for test/doc paths.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: ajianaz <ajianaz@users.noreply.github.com>
@ajianaz
ajianaz merged commit 5df7552 into develop Oct 7, 2026
14 checks passed
ajianaz added a commit that referenced this pull request Oct 8, 2026
)

Covers security hardening (#563, #572, #573), fixes (#553, #561, #562,
#564, #565, #574-#576), and the ignore-pattern semantic changes from
#577 that can alter which files existing configs exclude.

Signed-off-by: ajianaz <ajianaz@users.noreply.github.com>
Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
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.

1 participant