Repository navigation
Research: evaluate Tabby-style stateful path pruning for bounded ownership diagnostics #424
Description
Classification
- Type: bounded research / external prior-art evaluation
- Priority: P2 / backlog, not a production implementation request
- Area: OwnIR → MOS/interprocedural summaries → diagnostic evidence
- External project: tabby-sec/tabby and tabby-path-finder
- Related Own.NET work: Canonical first-party call facts: preserve interprocedural calls instead of collapsing them into frontend release/use/escape guesses #382 (canonical first-party calls), P2: Extend MOS/effect summaries to protocol and barrier effects #274 (protocol/effect summaries), Post-cutover: summary-backed lifecycle release reachability (generalize the landed #293/#302 predicates) #304 (frozen post-cutover lifecycle-reachability scope), Heap-effect summaries: typed write targets, to admit writes provably unrelated to the protected entity #395 (typed heap writes)
Why look at this?
Tabby uses Soot to extract Java code-property graphs into Neo4j and queries them for potentially vulnerable chains. The separate tabby-path-finder extension applies stateful taint-aware pruning during path traversal, including forward/backward searches, rather than returning every syntactically connected call path.
This is interesting as an algorithmic pattern, not as a proposed Java-to-.NET port. In Own.NET, several precision/recall problems involve whether a resource-affecting operation is actually connected to a relevant resource through calls, aliases and control flow.
However, the comparison needs discipline:
- A call graph path does not establish executable reachability or valid ownership transfer.
- A taint path is not an ownership/lifetime proof. Any borrowed idea requires a new, explicit state model (resource identity, may/must transfer, release/use, uncertainty).
- Tabby's own path-finder documentation warns that pruning can increase false negatives. Its anecdotal reduction from >2,000 candidates to >10 is not evidence of recall preservation or runtime speedup.
- Own.NET already has MOS, flow-sensitive facts and interprocedural work in progress. Do not replace these with Neo4j because a graph screenshot looks attractive.
Research question
Can a small, domain-specific path-state/pruning technique improve a measurable Own.NET result (confirmed diagnostic recall, precision, or auditable witness quality) over existing CFG/MOS behaviour, without hiding true positives?
Two deliberately separate possible benefits:
- Analysis: avoid reporting infeasible/irrelevant chains, or recover a real missed chain where current representation/analysis is too coarse.
- Evidence: present a concise, reproducible source-to-effect witness to help an auditor judge an existing diagnostic. Better evidence alone must not be reported as an accuracy gain.
Scope and proposed investigation
1. Read the implementation, not just the README
Document the exact path-finder traversal state, edge/argument propagation, pruning conditions, treatment of aliases, depth limits, unresolved calls, and any assumptions about reachability. Distinguish verified source-code behaviour from claims in docs/paper.
References:
2. Map to Own.NET's existing facts
Inventory exactly what can already be expressed in OwnIR / MOS / Python and Rust cores:
- resource identity and parameter/receiver bindings;
- call-site-to-callee relationship, including unresolved targets;
no / may / must / unknowntransfer and uncertainty policy;- control-flow conditions, alias/escape boundaries, and source locations;
- existing witness/diagnostic output.
Important dependency: #382 documents first-party calls that are currently collapsed by the Roslyn frontend. Path search cannot reconstruct edges discarded during lowering. Treat that as a blocker/constraint, not as justification to silently implement #382 here.
3. Choose one concrete, falsifiable slice
Candidate: guarded/partial resource handoff, e.g. the ForwardDynamic → MaybeClose fixture described in #382 and related OWN051 evidence. Assess whether any path-state algorithm adds something beyond the already specified MOS semantics.
Before implementation, pin:
- one existing baseline and commit SHA;
- source-level adjudicated positive and negative witnesses;
- adversarial near-neighbours: unconditional vs guarded release, alternate branches, forwarded argument identity, aliases/escapes, unresolved/virtual calls, loops and recursive boundaries;
- expected positive/negative/degraded outcomes.
If the candidate is fully explained by the missing canonical call representation, conclude no independent pruning value and stop or choose a separately justified slice. Do not claim that implementing #382 is a Tabby-derived improvement.
4. Optional small experiment only after the above gate
If a distinct gap survives:
- implement a disposable offline prototype or narrow query over existing facts; no production engine/schema change by default;
- evaluate against the same pinned baseline;
- measure newly recovered confirmed bugs, existing confirmed bugs lost, false findings introduced/removed, unknown/degraded cases, analysis cost, and witness usefulness;
- include parity implications for Python/Rust if it touches language-neutral semantics.
No automatic suppression based only on an incomplete/inconclusive path search. Absence of a found path under depth/alias/call-target limits is not proof of safety.
Acceptance / kill criteria
- Source-backed technical note: what Tabby's path-finder actually does, assumptions, and known failure modes.
- Mapping to specific Own.NET facts/issues, explicitly identifying what P2: Extend MOS/effect summaries to protocol and barrier effects #274/Canonical first-party call facts: preserve interprocedural calls instead of collapsing them into frontend release/use/escape guesses #382 already cover.
- At least one well-specified candidate with fixed baseline + adversarial controls, or an explicit NO-GO with reasons.
- If prototyped: reproducible commands, fixtures, measured TP/FP/FN deltas and resource cost; improvements in witness presentation reported separately from detection quality.
- Promote only if there is demonstrable incremental value on real/adjudicated cases, with no unexplained lost true positives and an acceptable, measured cost.
- KILL if no independent defect/triage benefit survives, the result depends entirely on Canonical first-party call facts: preserve interprocedural calls instead of collapsing them into frontend release/use/escape guesses #382, pruning merely hides uncertainty, or the benefit requires a new graph database/general taint engine.
Explicit non-goals
- No Neo4j or Soot integration.
- No generic CPG implementation or cross-language graph platform.
- No general-purpose Java security/taint analyzer inside Own.NET.
- No arbitrary predicate solver or claim of path feasibility.
- No reopening Post-cutover: summary-backed lifecycle release reachability (generalize the landed #293/#302 predicates) #304 or changing existing diagnostic verdict policy under this research issue.
- No broad refactoring of the already planned interprocedural summary architecture.
Deliverable: short evidence-backed feasibility note and GO/NO-GO, not a feature PR by default.
Activity