본문으로 건너뛰기
cccskills
무료GitHub에 공개

gitnexus-taint-analysis

Understand and extend GitNexus taint analysis, which tracks data from input sources to potentially dangerous operations. Use its implementation guidance to investigate missed or incorrect findings, add detection models, and validate analysis changes.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

원문원문 설명 보기

Use when working on, reviewing, or extending GitNexus's CFG/taint/PDG subsystem (the `--pdg` layers), or when reasoning about source→sink data-flow findings. Examples: "How does taint analysis work here?", "Why didn't explain find this flow?", "Add a new sink/source", "Review the interprocedural taint code".

설치 방법 보기

이럴 때 유용합니다

  • Investigating missed or incorrect data-flow findings
  • Adding input sources, dangerous operations, or sanitizers
  • Reviewing analysis that follows data across functions
  • Validating changes to the optional --pdg subsystem

포함된 파일(1)

  • SKILL.md10.7 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

CFG & Taint Analysis with GitNexus

Expert knowledge for the opt-in --pdg program-analysis subsystem: control-flow graphs, reaching definitions, and intra- + inter-procedural taint. Read this before touching gitnexus/src/core/ingestion/cfg/** or gitnexus/src/core/ingestion/taint/**, or when explaining a finding.

When to Use

  • "How does the taint engine work / why is this flow (not) reported?"
  • Adding a source, sink, or sanitizer to the model.
  • Extending or reviewing the CFG / reaching-defs / taint / summary code.
  • Understanding the explain MCP tool's findings (intra- vs inter-procedural).
  • Debugging a false positive or false negative in --pdg output.

The layered substrate (build order)

Taint runs on the graph, not beside it. Each layer is opt-in behind --pdg and a default analyze run is byte-identical (the golden parity gate is the hard floor for every change here).

L1  CFG            per-function basic blocks + control-flow edges   (M1 #2081)
L2  REACHING_DEF   GEN/KILL def→use data dependence (pure solver)   (M2 #2082)
L3  Taint (intra)  source→sink over RD facts, minus sanitizers      (M3 #2083)
L4  Taint (inter)  per-function summaries composed over CALLS       (M4 #2084)
  • Worker-built, main-thread-solved. The parse worker builds each function's CFG + harvests def/use + call-site facts onto ParsedFile.cfgSideChannel (plain, structured-clone-safe data — never AST nodes). The main thread runs the pure solvers. NEVER re-parse on the main thread (re-introduces the #1983 OOM).
  • In-phase emit (KTD1). L1–L4-harvest all run INSIDE the scope-resolution pdg window (scope-resolution/pipeline/run.ts, gated input.pdg === true), because the disk-backed ParsedFile store is cleared when that phase ends — a standalone post-mro phase would read empty data. The cross-function fixpoint (L4) is the exception: it runs in its OWN registered phase (taintSummaries) AFTER scope-resolution, because it needs the COMPLETE call graph, and consumes small plain summary data threaded out via ScopeResolutionOutput.
  • Pure-solver contract. computeReachingDefs, computeTaintFlows, harvestFunctionSummary, and solveInterprocTaint are pure and deterministic (no graph, no I/O, no logger; sorted outputs). Snapshot tests and content-derived edge ids depend on it.

Intra-procedural taint (L3)

Forward reachability over RD facts from matched sources to matched sinks, killed by sanitizers. Key design points worth internalizing:

  • Occurrence-tagged sites. A flat per-arg binding set cannot tell exec(escape(x)) (safe) from exec(x) (finding); the harvest records nested call structure (SiteRecord.parent/via-tags) so sanitizer interposition is precise.
  • Kind-set sanitizer model. A taint carries a set of neutralized SinkKinds; a sink fires unless its kind is in the set. So escape(req.body) suppresses res.send (xss) but STILL fires db.query (sql) — a kind-blind kill would be a suppressed live injection (the forbidden FN direction). path.basename(t) neutralizes path-traversal only, not command-injection.
  • Statement-level finding identity. NOT block-pair (block conflation drops distinct findings; exec(req.body, req.query) is two findings).
  • Persisted as TAINTED edges (BasicBlock→BasicBlock); the path rides the reason column via the shared versioned codec (taint/path-codec.ts).

Interprocedural taint (L4) — the functional/summary method

The production approach (Sharir-Pnueli 1981; the same shape as Meta's Pysa and Mariana Trench, and FB Infer) — NOT full IFDS tabulation. Each function is reduced to a compact summary, and summaries are composed over the already- resolved CALLS graph.

Summary shape (taint/summary-model.ts, whole-parameter granularity):

EdgeMeaningAnalogue
param→returna param flows to the return valueTITO — reserved (the floor already covers its recall; precision pass deferred)
param→callee-arga param flows into arg j of a call (carries the path's neutralized sink kinds)TITO into callee
param→sinka param reaches a modelled sinkpartial/triggered sink
source→returnthe function generates+returns a sourcegenerative — composed via the caller's callResults
source→callee-arga generated source flows into a callfixpoint SEED
callResultsa user-function call's result flows to a sink/return/callee-arg in the callercomposes with callee source→return

The fixpoint (taint/interproc-solver.ts): the unit is (function, parameter, source). Seed from source→callee-arg, propagate via param→callee-arg, fire a finding when a tainted param meets param→sink.

  • Cycle-safe by monotonicity. The tainted-set is monotone over a finite lattice (fn × param × source), so the worklist converges — a recursive call just re-proposes an already-visited entry. SCC condensation would only refine processing order; correctness/termination don't require it.
  • Source-discriminated state (load-bearing). Key the state by the SOURCE too. Keying only by (fn, param) collapses multi-source flows: a sink param tainted by source A is marked visited and a later flow from source B is dropped before firing — the recurring multi-source bug class. (Bit M3; bit M4 U9.)
  • Name-based call join. Match a summary's call-arg edge to a CALLS edge by CALLEE NAME, not call-site line — line-base parity (CFG 1-based vs reference site) is fragile; the callee identity is exact and context-insensitivity taints the callee's param identically at every call site.
  • Persisted as TAINT_PATH edges (Function→Function), function-level hop chain in reason via the same codec; confidence < the intra-procedural 1.0.

Context-insensitivity is the accepted trade-off at this tier: one summary per function, return/call-site merging accepted (security-conservative). Expect some FP from merging; the bigger FN sources are unmodeled features (below).

Known false-negative classes (documented, deferred)

The largest is closures/callbacks (arr.forEach(() => sink(y))) — taint into a callback is dropped without per-library models (true of CodeQL's JS libs too). Also deferred: field/property flows (obj.x = taint; sink(obj.y)), field-sensitive access paths, guard-style sanitizers, implicit/control-dependence flows, promise/async-await threading, and destructured/rest params before a tainted simple param (the summary port index is the binding ordinal, not the formal arg position — needs a formal-param index threaded from the worker BindingEntry). The interprocedural join is also context-insensitive: when one caller invokes two distinct same-named callees, a flow into one over-attributes to both (sound — over-report, never a missed flow). Absence of a finding is NOT proof of safety.

GitNexus-specific gotchas

  • Function↔CFG join. FunctionCfg.functionStartLine is 1-based; Function/ Method node startLine is 0-based — join at startLine - 1. Function nodes have no column, so same-line functions ({a:()=>x(), b:()=>y()}) are ambiguous → drop (the summary driver counts unresolved) rather than cross-wire.
  • No rel-property index (S1). Kuzu has no secondary index on relationship properties, and unanchored [:TAINTED*]/[:TAINT_PATH*] queries explode. TAINT_PATH is therefore MATERIALIZED + anchored at analyze time, never traversed live; explain reads it source-anchored + LIMIT-guarded.
  • explain is the only discovery surface. TAINTED/TAINT_PATH are deliberately OUT of VALID_RELATION_TYPES (impact's allow-list) and the web schema (pinned in security.test.ts). explain enumerates both layers (cross-function findings carry interprocedural: true).
  • One shared codec. Both the emit path and explain import taint/path-codec.ts. Two hand-rolled copies of a wire format drift — never fork it. New metadata extends the format WITHIN the version when writer + reader ship together.
  • Cache compatibility. Worker-harvest changes invalidate automatically through the PDG artifact identity. Keep extraction-only dependencies in the PDG ownership boundary and verify that ordinary parse keys remain stable. Shared parser changes belong to the base identity. Persisted-graph/config changes ride RepoMeta.pdg's key-union mismatch → full writeback. Model content rides taintModelVersion.

Adding a source / sink / sanitizer

Taint models cover four SupportedLanguages ids across three files: TypeScript and JavaScript use taint/typescript-model.ts, Python uses taint/python-model.ts, and Java uses taint/java-model.ts. Edit the model for the language you are targeting. The explicit registerBuiltinTaintModels seam in typescript-model.ts registers all four; it is not an import side effect.

The spec is hashable data (no functions). A sanitizer's neutralizes lists the EXACT sink kinds it defends — never a blanket kill. Add a fixture + assert the finding (or its absence) in test/unit/taint/. TypeScript and JavaScript use the real-source harness test/helpers/ts-cfg-harness.ts; Python and Java model matches are covered by python-model-match.test.ts and java-model-match.test.ts. The end-to-end proof is test/integration/cfg/.

Validation checklist for any --pdg change

1. tsc clean (schema additions are exhaustiveness-checked; watch the
   api.ts getNodeQuery runtime read-path if a node label is added).
2. Targeted vitest by directory (test/unit/taint, test/unit/cfg,
   test/integration/cfg) — verify by ISOLATION, not full-suite exit
   (known load-flakes). `node scripts/build.js` before worker/integration runs.
3. Flag-off golden byte-identical (pipeline-graph-golden.test.ts).
4. bench/cfg/measure.mjs --check (no fingerprint drift / budget regression).
5. detect_changes() before commit; impact({direction:'upstream'}) before
   editing shared symbols (KnowledgeGraph, RepoMeta, RelationshipType, codec).

Prior art (for deeper design questions)

Sharir & Pnueli 1981 (functional approach); Reps-Horwitz-Sagiv IFDS (POPL 1995); FlowDroid/StubDroid (access-path summaries); Pysa & Mariana Trench (TITO / propagations, parallel SCC fixpoint); CodeQL Models-as-Data (the richest port notation, incl. callback ports); Infer (content-keyed incremental summaries).

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Build and maintain a GitNexus code index, a searchable map of code relationships. Use CLI commands to refresh or remove indexes, check their status, list indexed projects, and generate repository documentation with an LLM.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Create a code index for a new project
  • Refresh the index after code changes
  • Check, remove, or list existing indexes
abhigyanpatwari/GitNexus4.8만2026년 10월 19일 업데이트

Investigate errors and unexpected behavior by finding related code, following function calls, and checking source files. GitNexus helps trace execution paths, while the diagnosis identifies the repository and reports how current its code index is.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Finding where an error originates
  • Investigating an endpoint that returns 500
  • Tracing calls between two functions
abhigyanpatwari/GitNexus4.8만2026년 10월 19일 업데이트

Explore unfamiliar code with GitNexus to understand project structure and execution flows. Find related functions, inspect their callers and callees, and read implementation files to explain how a feature works, with repository and index freshness information.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Understand the structure of an unfamiliar project
  • Trace authentication or payment flows
  • Find a function's callers and callees
abhigyanpatwari/GitNexus4.8만2026년 10월 19일 업데이트

Find the right GitNexus tools and workflows for exploring code relationships. This reference explains available commands, graph queries, and resources, including how to check which branch an answer describes and whether its index is current.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Find a GitNexus tool for a specific task
  • Learn how to query code relationships
  • Check index freshness and branch information
abhigyanpatwari/GitNexus4.8만2026년 10월 19일 업데이트

Assess the impact of code changes with GitNexus by tracing callers, dependencies, and affected execution flows. Check existing changes and report their scope, risk, and uncertainty before editing or committing.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Checking the impact of changing a function
  • Finding code that depends on a target
  • Reviewing affected flows before committing
abhigyanpatwari/GitNexus4.8만2026년 10월 19일 업데이트

Coordinate a development task from planning through implementation and review. Choose whether to proceed after seeing the plan, then receive a report covering commits, verification results, review findings, and any work left unfinished.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Plan, implement, and review a feature
  • Review a plan before authorizing implementation
  • Start implementation from an existing plan
abhigyanpatwari/GitNexus4.8만2026년 10월 19일 업데이트

abhigyanpatwari의 스킬 모두 보기

이 스킬의 문제 신고