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