unboundcompute/security-agent-skills/adjudicating-taint-paths

Claude Code and agent skill by unboundcompute/security-agent-skills

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Decide whether a whitebox lead is a real bug by tracing taint from an untrusted source to a dangerous sink and confirming every hop against live source. Use after a scanner, a candidate list, or your own reading surfaces a "this looks dangerous" sink (SQL exec, system/exec, file open, deserialize, template render, redirect target, memcpy) and you must decide whether attacker- controlled input actually reaches it - or kill the lead with evidence. Covers forward and reverse taint, witness paths, sanitizer analysis, and the evidence rules that separate a finding from a false positive.

Install

npx vskill@latest install unboundcompute/security-agent-skills/adjudicating-taint-paths

SKILL.md

Adjudicating taint paths: lead → decided finding

A lead is a fact about structure - "an input-shaped value can reach a dangerous sink." It is never a verdict. Adjudication is the disciplined work of deciding whether that structural possibility is a real, reachable bug on the current source, and recording the decision so it isn't re-litigated next pass.

When to use

  • A scanner or candidate list flagged a sink and you must confirm or kill it.
  • You spotted a sink by hand and want to know if attacker input reaches it.
  • You need to kill a plausible-looking lead with evidence, not vibes.

Scope check

Authorized source only (your own, OSS, CTF, in-scope engagement). If you can't name the authorization, stop.

The loop

  1. Name source and sink precisely. Which exact argument of which sink is

dangerous, and what is the actual untrusted entry - a request param, header, filename, env var, deserialized field? Vague framing ("user input reaches it somewhere") is how false positives survive.

  1. Trace the reverse cone into the sink. What values can flow into this sink

argument? This enumerates every origin. If none trace back to an untrusted source, the lead is dead - kill it, record why.

  1. Trace the forward cone from the source. Where does the untrusted value go?

If it never touches the sink, the lead is dead. Forward and reverse must agree; if they don't, you mis-specified an endpoint - fix it and redo.

  1. Get a witness path. The strongest evidence is a concrete `source → … →

sink` path. Good tooling returns either a witness or an honest negative ("no path"). A witness is a hypothesis to verify, not a proof.

  1. Confirm every hop against live source. Read the actual body of each

function on the path at the commit you're adjudicating. Verify the value is genuinely carried hop-to-hop and is not: reassigned to a constant/trusted value; validated, sanitized, or encoded by a guard on the path; narrowed to a safe type or bounded before the sink; or never actually passed by any caller.

  1. Decide and record - in the schema. Survivor → confirmed: source, path,

sink, evidence, impact. Killed → record the exact hop where taint breaks. Both go in the finding schema; killed findings are kept.

Evidence rules

  • Confidence is not truth. A high-confidence edge is strong support; a

conservative/over-approximated edge is included to avoid missing a path and is frequently spurious - a witness leaning on one demands extra source confirmation.

  • An absent edge is not proof of safety. The tool may not model that path.

Dynamic dispatch (attribute/vtable), function pointers, and getattr/eval/reflection are standard blind spots - "no path" through one of those is inconclusive, not clean. Confirm by reading source.

  • A sanitizer only helps if it covers the payload class. An HTML encoder does

nothing for a SQL context; a realpath check does nothing for a symlink race. Match the guard to the sink's context, not to its name.

Worked example (a kill and a confirm)

Kill. Lead: GET /search?q= → cursor.execute(sql). Reverse cone shows
q reaches execute, but reading the hop shows execute(sql, (q,)) - q is
a bound parameter, never concatenated into sql. Killed, kill_reason =
"bound param at the sink; q never enters the SQL string."
Confirm. Lead: body.filename → open(path, 'w'). Forward cone reaches
the sink; reading each hop shows name = body['filename'] (unchecked) →
path = base / name → open. /etc/x-style input escapes base. Confirmed,
high, impact = arbitrary file write → RCE via config/cron drop.

Rationalizations to reject

  • "The witness path is enough." → Not without reading source on every hop.
  • "There's a sanitizer, it's fine." → Only if it covers this sink's context.

Check what it actually enforces.

  • "No path found, so it's safe." → Not if the path would run through a blind

spot (reflection, function pointers, dynamic dispatch). Confirm by hand.

  • "I'll skip writing down why I killed it." → Then you re-open it next pass.

Record the kill reason.

Executing this in practice

Run the loop with whatever answers three questions from a real parse: what reaches a sink argument (reverse cone), where a source value flows (forward cone), and the exact current source of any function on the path. A code property graph answers all three; a taint-tracking analyzer covers most; on a small target you trace by hand. Step 5 (source confirmation) is never optional - the tool proposes, you confirm.

Related

  • hunting-bugs-with-a-code-graph - the master loop that surfaces leads.
  • auditing-guard-gaps - when the "sanitizer" is present on one path but missing

on a sibling.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/unboundcompute/security-agent-skills/adjudicating-taint-paths/badge)](https://verified-skill.com/skills/unboundcompute/security-agent-skills/adjudicating-taint-paths)

Something wrong with this skill or its page? Tell us.