Skip to content

feat(context): gate local-only suppression on trust_boundaries, not just app type#118

Open
gadievron wants to merge 1 commit into
masterfrom
fix/threat-model-untrusted-input-gate
Open

feat(context): gate local-only suppression on trust_boundaries, not just app type#118
gadievron wants to merge 1 commit into
masterfrom
fix/threat-model-untrusted-input-gate

Conversation

@gadievron

Copy link
Copy Markdown
Collaborator

fix(context): gate the local-only suppression on trust_boundaries, not app-type alone

Problem

The context generator sets requires_remote_trigger: False for every library/cli_tool. The Stage 1 and Stage 2 prompts (prompts/vulnerability_analysis.py, prompts/verification_prompts.py) then emit "This is a CLI tool/library… only flag vulnerabilities exploitable by a REMOTE attacker, not local users." That framing is correct for a library whose inputs are all operator-controlled — but wrong for a data-processing library (parser, deserializer, codec) whose untrusted input data is the attack surface even with no network listener. It tells the analyzer to discard exactly that bug class.

Observed on tree-sitter (a C parsing library): every parser memory-safety finding was suppressed by this clause until requires_remote_trigger was hand-set.

Fix

Add ApplicationContext.suppress_local_only() — keep the suppression only when no trust boundary is untrusted. This reuses the already-captured trust_boundaries (values: trusted/semi_trusted/untrusted); no new schema field. Gate all 7 emission sites (6 live in prompts/, 1 display in context/). Generator instruction reworded to set requires_remote_trigger from whether untrusted input is processed, not blanket-false per type (defense-in-depth; the gate holds even if the model keeps the old behavior).

  • A library with all-trusted boundaries → unchanged (still suppressed; genuine no-attack-surface libraries are not affected).
  • A library with any untrusted boundary (e.g. tree-sitter's source_code_being_parsed: untrusted) → now analyzed.

Scope note

This fixes the requires_remote_trigger suppression mechanism only. A separate over-suppression — the generator sometimes emits over-broad not_a_vulnerability entries (e.g. "memory operations in C are fine") — is not addressed here and is worth a follow-up.

Not a security fix

This is an analyzer-targeting/coverage change (it changes which findings the LLM is told to consider), not a code-vulnerability patch.

Tests

9 in tests/test_threat_model_untrusted_input_gate.py: suppress_local_only() unit cases (incl. case-insensitive untrusted match, since the values are LLM-generated) + Stage 1 and Stage 2 formatter present/absent for all-trusted vs untrusted-input contexts. No existing test pinned the prior behavior (verified: grep -rn suppress_local_only tests/ = 1 file).

Depends-on

None (standalone; the suppression clause is pre-existing on master). Co-exists with #94's application_context.py changes (different region; no conflict).

…ust app type

A data-processing library (parser, deserializer, codec) takes untrusted INPUT
DATA — that data crossing into the code is the attack surface even with no
network listener. The generator sets requires_remote_trigger=False for every
library, so the Stage 1/2 prompts emitted 'only flag REMOTE attacker, not local
users' and discarded exactly those bugs (tree-sitter: all parser memory-safety
findings suppressed until requires_remote_trigger was hand-set).

Add ApplicationContext.suppress_local_only(): suppress ONLY when no trust
boundary is 'untrusted'. Reuses the already-captured trust_boundaries — no new
field. Gate all 7 sites (6 live in prompts/, 1 display in context/). A genuine
no-attack-surface library (all-trusted) is unchanged; an untrusted-input library
is now analysed. Generator instruction reworded to set the flag from untrusted
input, not blanket-false per type.

Tests: 8 new (suppress_local_only unit + Stage 1 + Stage 2 present/absent).
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