mantis-patch

Generates minimal security fixes using transactional isolation (shadow directories or file backups), applies patches, and verifies them. Use when security findings are successfully reproduced and need patches applied and verified. Don't use for initial vulnerability research or reproduction payload

By google · 1,000 installs

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

Source repository · Upstream listing

Patcher (/mantis patch) System Goal Security Patching Expert. Generates minimal, correct code fixes, applies them to source code files, and verifies them inside isolated sandboxes before appending logs to long term memory. Command Definition Command: /mantis patch [ target root=<path ] [ state root=<path ] [ snapshot root=<path ] [ snapshot id=<id ] [ snapshot pinned=<true false ] Description: Generates minimal security fixes using transactional isolation (shadow directories or file backups), applies patches, and verifies them. Parameters (all optional; absent ⇒ today's behavior): target root : Root of the code snapshot to read (CODE ROOT). When the orchestrator pins a snapshot it passes snapshot root ; target root is reserved for a caller that hands you an already prepared tree. snapshot root : Root of the pinned immutable snapshot for this pass. snapshot id : The SNAPSHOT ID string of the pinned snapshot (used by the Snapshot Match Check). snapshot pinned : true when a pinned immutable snapshot exists this pass; false /absent ⇒ degraded/legacy (see Backward compat). state root : Root of the Mantis state directory that contains workspace/ (defaults to the current directory). ALL workspace/... paths in this file are STATE RELATIVE and resolve under <state root /workspace/... . Input/Output Contract Reads : workspace/findings/ (reproduced finding JSON files where patch status is not "VERIFIED SECURE" or "MITIGATION PROPOSED" ). workspace/.mantis state.json (to track current loop pass). workspace/.mantis state.json active snapshot ( root , snapshot id , snapshot pinned ) — resolved via Block A; supplies CODE ROOT and the SNAPSHOT ID used by the Snapshot Match Check when no snapshot flag is passed. Target source code files. Reproducer script path ( repro file path ) and command ( run command ) from findings. Pre existing backup files matching finding ID (if Option B is used). Writes : Source code modifications (applied transactionally and rolled back). Updates finding JSON files in place (sets "patch status" , "patch diff" , re attack details including "reattack status" and "reattack variants" , and history). Appends to workspace/learnings.jsonl . Reusable helper script workspace/helpers/append patch.py . Preconditions : Findings must exist in workspace/findings/ . Idempotency Guarantee : Snapshot aware skip: Skips a finding whose patch status is already "VERIFIED SECURE" or "MITIGATION PROPOSED" ONLY when its recorded patch base snapshot equals the current SNAPSHOT ID (i.e. it was verified against THIS snapshot). If patch base snapshot is absent, empty, or different from the current SNAPSHOT ID, the terminal status is stale — do NOT skip; re open and re verify the finding against the current snapshot. In legacy mode (no active snapshot and no snapshot flags) skip exactly as today (by patch status alone). Transactional isolation: modifies code inside uniquely generated temporary directories or creates temporary file backups ( target.c.bak [id] ), restoring baseline state upon completion (using try...finally rollback mechanisms). Reuses the existing append patch.py script once created. Instructions Fix successfully reproduced security flaws without breaking standard code behavior. Execute the patching and verification stage as follows: 0. Snapshot & Locator Resolution (run once, before touching any code): 0a. Resolve CODE ROOT, SNAPSHOT ID, snapshot pinned, and state root via Block A (Locator Resolution): [!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). For this stage: mantis patch READS target code (it is NOT a findings only stage), so it runs Block A steps 1–6 in full. CODE ROOT is the immutable pinned snapshot; you MUST NOT write, compile, or run reproducers under it (Block A step 4) — do all mutation in a private shadow (step 2 below). 0b. Determine PATCH MODE (mechanical, using the resolved values): active snapshot absent AND no snapshot root / snapshot id / target root passed ⇒ LEGACY mode (today's behavior; the new ceilings in step 3 do NOT fire). snapshot pinned == true ⇒ PINNED mode (full gates below apply). snapshot pinned == false AND SNAPSHOT ID begins with the literal live: ⇒ HALT/DEGRADED mode (a snapshot was attempted but could not be pinned; authoritative verdicts are forbidden this pass — see step 3). 0c. For each finding you process, compute its MATCHED/NOT MATCHED result via Block B (Snapshot Match Check): The MATCHED/NOT MATCHED result is consumed in step 2 (isolation mode choice) and step 3 (verdict). It never on its own downgrades a verdict in PINNED mode: a NOT MATCHED finding is RE verified against the current snapshot via the step 3 gate and, if it passes, is stamped with the current patch base snapshot . 1. Load Findings to Patch: Read the JSON files in the workspace/findings/ directory. Filter for findings that are NOT already terminally verified AGAINST THE CURRENT SNAPSHOT — i.e. treat a finding as still to process unless its patch status is "VERIFIED SECURE" or "MITIGATION PROPOSED" and its patch base snapshot equals the current SNAPSHOT ID (Snapshot & Locator Resolution step 0). A terminal finding whose patch base snapshot is absent/empty/different is STALE — include it for re verification. (In LEGACY mode, where there is no SNAPSHOT ID, fall back to filtering on patch status alone, exactly as before.) Among the included findings, keep those where (either repro status is "reproduced" OR the finding is an exploit chain, e.g., the title starts with "Exploit Chain:" , or history has an entry from the "chainer" stage, or the "constituent findings" property is present and non empty). If none exist, notify the user. 2. Generate and Apply Minimal Patches: For each reproduced security flaw: Target Agnosticism (Binaries vs Source): If the target is source code, proceed with generating and applying a code patch as described below. If the target is a compiled binary or firmware blob without source code available, do not attempt to modify the binary or write binary patching scripts . Instead, skip the branch isolation/modification/diff steps and generate a general, high level recommendation for how this issue could be mitigated in a production environment without requiring deep technical depth. Output this mitigation string in place of the patch diff field, and set "patch status" to "MITIGATION PROPOSED" . Exploit Chains: If the finding is an exploit chain (identified by "Exploit Chain:" in the title, or history details, or if the "constituent findings" property is present and non empty), do not generate a code patch or diff. Instead, identify its sub findings by reading the "constituent findings" array of UUIDs. Monitor the patch status of these constituent findings (listed on disk as workspace/findings/<uuid .json ). Important: Defer evaluating exploit chains until all individual findings in the batch have been processed, so that the latest patch statuses of their constituents are available on disk. Evaluate the exploit chain status using these propagation rules (evaluated in order): 1. Validity Check: Read the validity "status" of each constituent finding. If any constituent's "status" is "FALSE POSITIVE" , update the exploit chain finding's "status" to match it (e.g. "FALSE POSITIVE" ) and immediately skip any further patching/verification for the chain. If any constituent's "status" is "DUPLICATE" , resolve it to its canonical finding by recursively following its "duplicate of" property. Duplicate Resolution Process: 1. Locate the Finding File: The finding file for the duplicate (or any parent in the duplicate chain) may have been moved. Search for <uuid .json in the following locations in order: workspace/findings/<uuid .json (active findings) workspace/findings/.trash/<uuid .json (de duplicated trash) workspace/archive/findings pass /<uuid .json or workspace/archive/loop findings/<uuid .json (archives from previous passes) If the file cannot be found in any of these locations, treat it as a missing file error. 2. Cycle Detection: Maintain a set of visited finding UUIDs during the resolution. If you encounter a UUID that has already been visited in the current resolution chain, raise a validation error (cycle detected). 3. Maximum Depth: Limit the recursion depth to a maximum of 5 steps. If the chain is deeper, abort and report an error. 4. Extract Status: Once you resolve to the canonical finding (one whose "status" is not "DUPLICATE" or does not have "duplicate of" ), use that canonical finding's "status" and "patch status" for all downstream checks and propagation. Do not update the exploit chain finding itself to "DUPLICATE" . 2. Missing Files: If any constituent finding's JSON file is missing from the disk, set the chain's "patch status" to "ERROR" . 3. Constituent Unset or Stale (Pending): A constituent counts as NOT YET VERIFIED if EITHER its "patch status" is unset (null or missing, indicating it has not yet been reproduced/processed) OR its "patch status" is terminal but its patch base snapshot is absent/empty/different from the current SNAPSHOT ID (verified against a stale snapshot — Snapshot & Locator Resolution step 0). If ANY constituent is NOT YET VERIFIED, the chain's "patch status" must remain unset (null or missing) and you must defer/suspend further evaluation of the chain until that constituent is re verified on the current snapshot. (In LEGACY mode, where there is no SNAPSHOT ID, apply only the "unset" half of this rule, exactly as before.) 4. Constituent Errors: If any constituent's "patch status" is "ERROR" , set the chain's "patch status" to "ERROR" . 5. Constituent Failures: If any constituent's "patch status" is "VERIFICATION FAILED" , set the chain's "patch status" to "VERIFICATION FAILED" . 6. Successful Propagation: If all constituents have finished verification AGAINST THE CURRENT SNAPSHOT (each is in {"VERIFIED SECURE", "MITIGATION PROPOSED", "VERIFICATION INCOMPLETE"} AND — except in LEGACY mode — each terminal constituent's patch base snapshot equals the current SNAPSHOT ID): If any constituent is "MITIGATION PROPOSED" , set the chain's "patch status" to "MITIGATION PROPOSED" . I