mantis-chain

Analyzes individual security findings to identify and construct complex exploit chains. Use after validation stages to see if multiple low-severity bugs can be combined into a higher impact vulnerability. Don't use for initial codebase auditing or writing patch code.

By google · 995 installs

npx skills add google/mantis --skill mantis-chain

Source repository · Upstream listing

Vulnerability Chainer (/mantis chain) System Goal Exploit Chain Architect. Analyzes isolated, individually validated security findings and historical knowledge base primitives to identify and construct complex, multi step exploit chains. Command Definition Command: /mantis chain Description: Analyzes individual security findings to identify and construct complex exploit chains. Arguments (all optional; supplied by the orchestrator per the harness lifecycle contract — see schema.json "Non JSON Contracts"): snapshot root / SNAPSHOT ROOT — the pinned, immutable code snapshot root for this pass. Consumed by Block A. snapshot id / SNAPSHOT ID — the snapshot identity string for this pass. Consumed by Block A (sentinel) and Block B (match check). state root — parent directory of workspace/ . When absent, defaults to the current directory (Block A step 1c/1d). target root — an already prepared tree that OVERRIDES the snapshot root (rarely used by this stage; honored by Block A step 1a). When NONE of these are passed, Block A falls back to active snapshot in workspace/.mantis state.json ; if that is absent too, the stage runs MODE OFF ( snapshot pinned = false ) and behaves exactly as today (see Backward compat). Input/Output Contract Reads : workspace/findings/ (validated finding JSON files where status is "VALID" , and viability is "VIABLE" , "CONDITIONAL VIABLE" , or "SAMPLE OR TEST" ). workspace/kb/entities/ .md and workspace/kb/vulnerabilities/ .md (knowledge base primitives). workspace/.mantis state.json (to track current loop pass). Writes : Net new exploit chain finding JSON files to workspace/findings/<new uuid .json . Original findings are left unmodified. Preconditions : Validated or viable findings must exist in workspace/findings/ . Idempotency Guarantee : Before writing a new exploit chain finding, the skill must check existing exploit chain findings by comparing the constituent finding sequence. Scan BOTH the current workspace/findings/ directory AND every archived pass under workspace/archive/findings pass / AND legacy workspace/archive/loop findings/ (all STATE RELATIVE — never prefix CODE ROOT ). A chain JSON is any finding whose constituent findings array is present and non empty. If a chain with the EXACT same ordered constituent sequence already exists in EITHER location, skip creating a duplicate. Signature keyed idempotency (preferred) — with a code paths tiebreak: If ALL constituent findings have a signature field, compare the ordered constituent signature sequence (not UUIDs). Treat two chains as the SAME (and skip creating the new one) ONLY IF their ordered signature sequences are equal AND, for each corresponding constituent pair, at least one code paths entry (line inclusive, i.e. compared WITH its trailing :line ) is identical. If the signature sequences match but any corresponding constituent's code paths differ, the chains are DISTINCT — create the new chain. (Over reporting is safe; a signature collision must never suppress a genuinely new exploit chain, because signature strips line numbers and can collide between distinct same file bugs.) UUID fallback (today's behavior): If ANY constituent finding lacks a signature field, fall back to comparing the ordered constituent UUID sequence exactly as before. This preserves today's behavior for legacy / un upgraded findings. This archive scan is now fully effective with stable finding signatures: two chains whose constituents share the same signatures are correctly deduplicated across passes. When signatures are absent (legacy findings), the scan remains HARMLESS — it cannot falsely suppress a legitimate new chain (no silent dropped result) and simply prevents exact UUID re duplication within a resumed / rerun pass. If the workspace/archive/ directory does not exist, treat the archived set as empty and proceed. Instructions Locator Resolution (run first — all stages) [!NOTE] CURRENT PASS CHECK (defensive; the binding guarantee is on the harness per mantis pipeline adapter Scenario 2): if active snapshot is present AND active snapshot.pass != state.pass number , treat the snapshot as STALE for this pass — STOP "stale active snapshot: pass mismatch" or degrade as HALT ( snapshot pinned effectively false: no authoritative verdicts, Block B NOT MATCHED, reproduce not attempted ). This catches a custom harness that preserved active snapshot across the Stage 15 pass increment without re pinning. The reference meta agent re pins every pass, so this check never fires there. Block B itself cannot detect this (it is snapshot id only, not pass aware). Stage specific notes for Block A: mantis chain is NOT a findings only stage (it is not report/calibrate/reflect), so Block A runs steps 1–6 and resolves CODE ROOT , SNAPSHOT ID , and snapshot pinned from snapshot root / snapshot id / state active snapshot . This stage WRITES only new finding JSON to workspace/findings/ (STATE RELATIVE, Block A step 3). It never writes under CODE ROOT , so Block A step 4 is satisfied trivially. If you optionally re inspect a constituent's code paths to sanity check a chain, read them SNAPSHOT RELATIVE under CODE ROOT (Block A step 3) and never cd and write there. A chain finding's code paths are COPIED verbatim from its constituents (they are already SNAPSHOT RELATIVE). Do not re prefix, re resolve, or renumber them. Snapshot Match Check (used to select constituents) You will run Block B once per candidate constituent finding in Step 1 below, using that finding's discovery commit as F.discovery commit . Read the current batch of validated findings and explore whether multiple seemingly low severity or disparate vulnerabilities can be sequentially combined to achieve a higher impact compromise. Execute the chaining stage as follows: 1. Load Primitives & Validated Findings: Read the JSON files in the workspace/findings/ directory. Filter for findings that have passed validation (e.g., status is "VALID" and viability is "VIABLE" , "CONDITIONAL VIABLE" , or "SAMPLE OR TEST" ). Snapshot eligibility gate (NEW — branches on active snapshot presence, 3 state model): MODE OFF (no active snapshot in state — no sync was requested, today's default): SKIP this gate entirely: every finding that passed the validation/viability filter above is an eligible constituent, exactly as today. Build chains normally. HALT ( active snapshot IS present but snapshot pinned == false ): do NOT build any chains this pass. In HALT, findings' locators and pre/post conditions may be stale (the tree raced or could not be pinned), so no authoritative chain verdicts may be produced. Log "no chain: HALT mode (active snapshot present, snapshot pinned=false)" and stop the chaining stage cleanly (produce no chain files). This mirrors the minimum eligibility guard below — a chain requires proven against snapshot constituents, which HALT cannot provide. PINNED ( active snapshot present AND snapshot pinned == true ): run the Snapshot Match Check (Block B) on EACH such finding, using its discovery commit . Keep ONLY findings that return MATCHED as eligible constituents. A finding that returns NOT MATCHED — including any finding whose discovery commit is absent/empty, is the literal "MIXED" , or differs from the current SNAPSHOT ID — was discovered against a DIFFERENT code snapshot; its file:line locators and its pre/post conditions may no longer hold, so it MUST NOT be used as a chain link this pass. Minimum eligibility guard (NEW): If fewer than 2 eligible constituents remain, do NOT construct any chain this pass — a chain requires at least two links proven against the SAME snapshot. Log "no chain: fewer than 2 snapshot matched constituents" and stop the chaining stage cleanly (this is not an error; simply produce no chain files). This mirrors today's behavior whenever there are fewer than two chainable findings. Read the Markdown Knowledge Base ( workspace/kb/entities/ and workspace/kb/vulnerabilities/ ) to identify architectural primitives that might not be bugs on their own, but could serve as stepping stones (e.g., "User controls file upload path", "Service runs as root"). 2. Cross Finding Analysis (The Chaining Matrix): Analyze the preconditions and postconditions of each validated finding. Ask: Can the output or side effect of Finding A satisfy the strict precondition required to trigger Finding B? Example Chains to look for: Path Traversal + Loose Permissions = RCE: A low severity path traversal (Finding A) allows writing to /tmp , but a separate misconfiguration (Finding B) allows a cron job to execute scripts in /tmp . XSS + CSRF = Account Takeover: A stored XSS (Finding A) can be used to harvest an anti CSRF token to execute a state changing action (Finding B). Info Leak (Memory Revelation) + Buffer Overflow = ASLR Bypass: An info leak (Finding A) reveals base pointers, satisfying the precondition to exploit a stack buffer overflow (Finding B). 3. Construct "Super Findings": If a viable exploit chain is discovered, do NOT modify or delete the original isolated findings. They still need to be patched individually. Idempotency check (run BEFORE minting a UUID): Apply the Idempotency Guarantee above — scan current workspace/findings/ AND workspace/archive/findings pass / AND legacy workspace/archive/loop findings/ for a chain whose constituent sequence equals this chain's ordered constituent sequence. If ALL constituents have signature , compare ordered signature sequences AND require the per constituent line inclusive code paths tiebreak described in the Idempotency Guarantee (a signature sequence match ALONE is NOT enough to skip); if ANY constituent lacks signature , fall back to ordered constituent UUID sequences (today's behavior). Only if a match satisfies the tiebreak, SKIP this chain (do not create a file) and move on to the next candidate. Instead, generate a net new UUID and create a new finding JSON file in workspace/findings/<new uuid .json . Constituent Findings : You must record the array of constituent finding UUIDs in the structured "constituent findings" property (e.g., ["UUID A", "UUID B"] ). This clearly documents the links of the exploit chain. Determine Discovery Snapshot ( discovery commit ) : Set the chain finding's discovery commit from its ELIGIBLE constituents (the ones you kept in Step 1): MODE OFF short circuit (3 state rule): if active snapshot is ABSENT in state (MODE OFF — no sync was requested), OMIT discovery commit on the chain finding entirely. In MODE OFF, researcher OMITS discovery commit on every constituent ( researcher:317,340 341 : "OMIT this key entirely if active snapshot is absent or snapshot pinned is false"), so every constituent has a missing/empty discovery commit . The SAME/MIXED logic below would thus write the literal "MIXED" on every chain — a snapshot era artifact that did not exist in Phase 1 and violates MODE OFF's "byte for byte today's behavior" guarantee ( schema.json:4 ). The chain's own schema comment ( chain:307 )