feat(flow): add opt-in FLOWS_TO data-flow edges for intra-procedural taint#707
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces significant improvements to the codebase, including a new dead code detection feature, enhanced C++ frontend integration with a hybrid mode, and robust handling of import edge verification and class inheritance. I have identified a critical bug in the embedding logic where global is incorrectly used instead of nonlocal for a variable defined in an enclosing scope, and an improvement opportunity for the C++ qualified name resolution to ensure consistent separator usage.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
@greptile review |
|
@greptile review |
|
@greptile review |
|



What
Adds
FLOWS_TO, an opt-in relationship type that records intra-procedural value flow (taint/provenance) between resources and callables. Turns questions like "does a value read here reach a write over there?" into graph reachability, which coarseCALLSco-occurrence cannot answer.Stacked on #638 (base branch
feat/relationship-capture-io):FLOWS_TObuilds on that PR'sResourcenodes and I/O source/sink registry, so it must land after #638. When #638 merges this PR auto-retargets tomain.Behavior
FLOWS_TOis emitted in three shapes, distinguished by akindedge property (plus aviaconduit label):kind=resource): a value read from one resource reaches a write to another within a body, e.g.x = os.getenv("K"); print(x)yieldsResource(ENV::K) -FLOWS_TO-> Resource(STDOUT).kind=arg,via=arg:<i>/kw:<name>): a tainted local is passed as an argument to a first-party callee.kind=return,via=return): a callee whose return value is tainted flows it back to the assignment in its caller.Taint propagates through plain
x = yassignments.Opt-in / zero default cost
FLOWS_TOjoins the existingiocapture group, which is excluded from the default capture set. A default build emits zeroFLOWS_TOedges and skips the body pass entirely. Enable with--capture io(orCGR_CAPTURE=io).Design
Self-contained
codebase_rag/parsers/flow_access/submodule mirroringio_access/: one scope-pruned body DFS per caller, invoked once besideprocess_io_for_caller, reusing the resolver for callee resolution. Pure extractors shared withio_accesswere promoted toio_access/extract.py(no behavior change; the io suite is unchanged). No new node types:FLOWS_TOconnects existingFunction/Method/Module/Resourcenodes.Phase-1 scope is deliberately conservative and documented inline: Python-only, single function body plus one level of argument/return hand-off, direct source/sink calls, no SSA/parameter nodes. Upgrade paths are noted at each ceiling.
Tests
RED → GREEN: failing tests committed first (
2c3f1fe), then the implementation (2cc78d2). Eighttest_flow_edges.pycases cover each edge shape, taint propagation, the anti-false-positive negative case (co-occurrence is not flow), default-off gating, and the dangling-endpoint guard, plus capture-selection membership. Full suite green (4853 passed);tyandruffclean; relationshippropertiesconfirmed to round-trip the protobuf path.Docs
docs/architecture/graph-schema.mdgains theResourcenode row, theREADS_FROM/WRITES_TO/FLOWS_TOrelationship rows, and an I/O and data-flow section.