Skip to content

feat(analysis): taint propagation engine + source/sink/sanitizer catalog#72

Closed
smochan wants to merge 1 commit into
feat/data-edges-pythonfrom
feat/taint-engine
Closed

feat(analysis): taint propagation engine + source/sink/sanitizer catalog#72
smochan wants to merge 1 commit into
feat/data-edges-pythonfrom
feat/taint-engine

Conversation

@smochan

@smochan smochan commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Summary

Track C3, stacked on #68the Phase-4 flagship from docs/GAP_ANALYSIS_VS_LLM_REVIEWER.md. codegraph now tracks untrusted values from sources to dangerous sinks with witness paths.

  • analysis/taint_catalog.py: YAML catalog (.codegraph/taint.yml, extend-by-default / replace: true) of sources (route params, request.*, fetch responses, LLM output), sinks (network/sql/eval/exec/dom/path with per-class severity), sanitizers (clear specific sink classes)
  • analysis/taint.py: worklist propagation over C1's DATA_* edges; route-param seeding via DF1 ROUTE edges; call-through bridging (arg → ret sentinels, ×0.9 confidence); sanitizer absorption tracked as cleared-class sets in visited state (node, frozenset(cleared)) — re-visits allowed on different sanitizer histories, termination guaranteed; depth cap 6
  • Scope honestly stated: intra-procedural + one CALLS hop; no attribute/field sensitivity; no inter-procedural return flow yet

Adversarial e2e validation by reviewer (full build pipeline on a deliberately vulnerable FastAPI app):

  • SSRF: target_url param → requests.gethigh, confidence 1.0 ✓
  • Command injection: cmd param → expanded = cmd + …subprocess.runcritical, witness path includes the intermediate assignment ✓
  • Self-graph + cross-stack-demo: 0 findings (verified true negatives), propagation 25ms

Test plan

  • 27 tests: direct/chain/sanitizer-suppression/class-mismatch/inter-procedural/depth-cap/cycles/custom-YAML/loop-element/catalog validation
  • Full suite 753 passed; ruff + mypy --strict + self-lint clean

🤖 Generated with Claude Code

Implements Capability A from docs/GAP_ANALYSIS_VS_LLM_REVIEWER.md (C3, PR C3).

codegraph/analysis/taint_catalog.py:
- SourceSpec / SinkSpec / SanitizerSpec dataclasses
- Bundled default catalog: 7 sources (http_request, fetch_response, llm_output,
  file_read, scraped_dom, route_param), 14 sinks (network/sql/eval/exec/path/dom),
  6 sanitizers (url-allowlist, html-escape, shell-quote, zod/pydantic, sql-escape)
- os.environ explicitly excluded from sources (operator config, not user data)
- load_taint_catalog(): searches .codegraph/taint.yml with merge/replace semantics

codegraph/analysis/taint.py:
- TaintFinding / TaintHop dataclasses with to_dict() for serialisation
- propagate(graph, catalog, max_depth=6) -> list[TaintFinding]
- Seed kinds: route-param (PARAMETER nodes of ROUTE-decorated handlers) +
  call-result (VARIABLE nodes assigned from matching unresolved::ret:: sentinels)
- Forward propagation over DATA_ASSIGN + DATA_RETURN edges (node-to-node)
- Call-through propagation: taint flows through unresolvable external calls
  to their return-value variables (enables shlex.quote class-mismatch detection)
- Inter-procedural hop: DATA_ARG -> resolved callee PARAMETER node via
  CALLS edges or tail-qualname scan; confidence x0.8 for indirect hops
- Sanitizer absorption: cleared_classes frozenset tracks per-path cleared sinks;
  at sink time, suppressed when sink class is covered
- Visited-set on (node_id, cleared_classes) for cycle/termination safety
- Depth cap (default 6) mirrors DF4 max_depth

tests/test_taint.py: 27 tests covering all 9 required spec cases plus unit
tests for catalog validation, YAML loading, to_dict, and edge cases.

Performance: propagate() on codegraph's own 14K-node graph completes in 25ms
(well under the 5s gate). Finding count: 0 (expected — codegraph has no
route-decorated handlers matching the default catalog patterns).
@smochan smochan deleted the branch feat/data-edges-python June 10, 2026 14:14
@smochan smochan closed this Jun 10, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 10, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant