Bundled with Unleash skills pack. Source: C:\Users\Admin.agents\skills\patch-diff-variant-hunting\SKILL.md
Patch-Diff Variant Hunting
Objective
Use known fixes as maps to unreviewed code. The deliverable is not “old PoC still works” unless the fix genuinely regressed; it is a new latest-stable instance of the same broken security invariant, an incomplete fix, or a fix bypass in a distinct reachable path.
Candidate Selection
Prefer historical bugs with:
- complex trust-boundary logic rather than one obvious bounds check;
- multiple parsers, protocol versions, platform ports, or service modes;
- duplicated helpers or generated code;
- fixes added only at callers or only after one normalization step;
- emergency patches, defense-in-depth language, or sparse root-cause detail;
- later refactors, rollbacks, vendor forks, or component rewrites;
- high-value products matching the current-version and deployment gate.
Record CVE/advisory, fixed versions, public PoCs, researcher writeups, patch commits, and exact latest stable version before analysis.
Phase 1: Reconstruct the Original Invariant
Do not begin with the old payload. State:
Untrusted actor controls <field/object/state>.
Trusted component assumes <invariant>.
Missing/late/incorrect check permits <primitive>.
Primitive reaches <sink> under <authority>.
Separate:
- trigger syntax;
- vulnerable semantic condition;
- exploit primitive;
- final impact.
Completion criterion: the root cause can generate searches beyond the original function name.
Phase 2: Diff the Fix
For source patches, inspect full function, callers, tests, and adjacent commits—not only changed lines.
For binary-only patches:
- obtain same-channel pre/post binaries and symbols where available;
- hash and record package provenance;
- match functions using symbols, strings, CFG, constants, and call neighborhoods;
- classify changed basic blocks and data structures;
- recover the new predicate, ordering, or ownership rule;
- identify unchanged callers and parallel implementations;
- verify the apparent change dynamically with the old trigger.
Produce a fix model:
| Check |
Location |
Data representation |
Effective token/state |
Before/after side effect |
Failure action |
Completion criterion: explain what security property the patch attempts to enforce and where enforcement begins/ends.
Phase 3: Generate Variant Axes
Search systematically:
- sibling callers omitted from the patch;
- alternate protocol/file-format versions;
- fast path, fallback, retry, recovery, offline, import/export, and compatibility modes;
- default stream versus ADS; local versus remote; live versus snapshot;
- Unicode/ANSI, normalized/raw, absolute/relative, object-name/path-name representations;
- client/server, desktop/Server, x86/x64/ARM, kernel/user, host/guest implementations;
- pre-auth/post-auth and impersonated/reverted token paths;
- parser size/count/offset relationships transformed in a different order;
- object lifecycle changes between the new check and final use;
- integer widths, signedness, truncation, alignment, and unit conversion;
- duplicated vendor forks and statically linked copies;
- cleanup/error paths that skip the new invariant.
Build a matrix; do not free-associate variants.
Phase 4: Search by Predicate
Translate the fix into queries:
- CodeQL/Semgrep/Coccinelle for source patterns;
- compiler-aware grep for helper call sequences;
- IDA/Ghidra scripts for call-before-check or missing-callee patterns;
- binary feature matching for old/new basic-block shapes;
- runtime tracing for consumers that reach the sink without the new validation event.
Example abstractions:
open(path) -> validate(path) -> reopen(path) # identity not preserved
size = count * width without checked multiplication
authorize(token A) -> revert -> act(token B)
normalize(name) in one branch, raw name in sibling branch
validate leaf reparse tag but reopen through mutable parent
Completion criterion: every hit is tied to the root-cause predicate, not merely a shared API.
Phase 5: Latest-Stable and Novelty Validation
For each candidate:
- reproduce on exact latest stable bytes;
- prove the old public issue is fixed in its original path;
- prove the new path remains vulnerable;
- compare root cause, trigger, component, and impact with public descriptions;
- search whether the variant path has already been disclosed;
- record why this is a distinct instance, incomplete fix, or regression.
If the original old PoC simply works unchanged, investigate regression provenance; do not assume novelty.
Completion criterion: zero-day-target-eligibility passes with a written distinction from the known issue.
Phase 6: Minimize and Bisect
- minimize the trigger around the variant-specific condition;
- build a negative control exercising the fixed original path;
- bisect packages/commits to find introduction or regression;
- determine whether the variant predates, survives, or reappears after the original fix;
- quantify affected stable releases without losing latest-version proof;
- derive a regression test that covers all sibling paths.
High-Value Fix Smells
- validation added after partial parsing;
- denylist of one path/name/tag rather than object identity validation;
- check performed before queueing asynchronous work;
- check under caller impersonation, side effect after revert;
- count capped but secondary count/stream/metadata unbounded;
- only one protocol opcode or content-type patched;
- security check copied rather than centralized;
- exception converted to generic error while state remains mutated;
- defense-in-depth patch with no corresponding tests;
- fix in UI/client while server endpoint remains reachable;
- recovery/offline implementation not updated with online component.
Common Pitfalls
- Running public PoCs without reconstructing root cause.
- Calling a byte-level patch difference a security difference.
- Ignoring servicing branches and independently updated components.
- Searching only renamed functions rather than semantic predicates.
- Treating an incomplete fix already discussed publicly as a new zero-day.
- Failing to prove the original path is fixed and the sibling path is distinct.
- Overfitting to compiler noise in binary diffs.
- Skipping error, fallback, and recovery paths.
Verification Checklist
1---2name: patch-diff-variant-hunting3description: Use when mining historical CVEs, vendor patches, silent fixes, regressions, or incomplete mitigations for new vulnerability variants that still affect the latest stable release. Converts binary/source diffs into root-cause predicates, searches sibling implementations and exceptional paths, and applies a strict novelty gate so known bugs are not misreported as zero-days.4license: MIT5---67> Bundled with Unleash skills pack. Source: C:\Users\Admin\.agents\skills\patch-diff-variant-hunting\SKILL.md89# Patch-Diff Variant Hunting1011## Objective1213Use known fixes as maps to unreviewed code. The deliverable is not “old PoC still works” unless the fix genuinely regressed; it is a new latest-stable instance of the same broken security invariant, an incomplete fix, or a fix bypass in a distinct reachable path.1415## Candidate Selection1617Prefer historical bugs with:1819- complex trust-boundary logic rather than one obvious bounds check;20- multiple parsers, protocol versions, platform ports, or service modes;21- duplicated helpers or generated code;22- fixes added only at callers or only after one normalization step;23- emergency patches, defense-in-depth language, or sparse root-cause detail;24- later refactors, rollbacks, vendor forks, or component rewrites;25- high-value products matching the current-version and deployment gate.2627Record CVE/advisory, fixed versions, public PoCs, researcher writeups, patch commits, and exact latest stable version before analysis.2829## Phase 1: Reconstruct the Original Invariant3031Do not begin with the old payload. State:3233```text34Untrusted actor controls <field/object/state>.35Trusted component assumes <invariant>.36Missing/late/incorrect check permits <primitive>.37Primitive reaches <sink> under <authority>.38```3940Separate:4142- trigger syntax;43- vulnerable semantic condition;44- exploit primitive;45- final impact.4647Completion criterion: the root cause can generate searches beyond the original function name.4849## Phase 2: Diff the Fix5051For source patches, inspect full function, callers, tests, and adjacent commits—not only changed lines.5253For binary-only patches:54551. obtain same-channel pre/post binaries and symbols where available;562. hash and record package provenance;573. match functions using symbols, strings, CFG, constants, and call neighborhoods;584. classify changed basic blocks and data structures;595. recover the new predicate, ordering, or ownership rule;606. identify unchanged callers and parallel implementations;617. verify the apparent change dynamically with the old trigger.6263Produce a fix model:6465| Check | Location | Data representation | Effective token/state | Before/after side effect | Failure action |66|---|---|---|---|---|---|6768Completion criterion: explain what security property the patch attempts to enforce and where enforcement begins/ends.6970## Phase 3: Generate Variant Axes7172Search systematically:7374- sibling callers omitted from the patch;75- alternate protocol/file-format versions;76- fast path, fallback, retry, recovery, offline, import/export, and compatibility modes;77- default stream versus ADS; local versus remote; live versus snapshot;78- Unicode/ANSI, normalized/raw, absolute/relative, object-name/path-name representations;79- client/server, desktop/Server, x86/x64/ARM, kernel/user, host/guest implementations;80- pre-auth/post-auth and impersonated/reverted token paths;81- parser size/count/offset relationships transformed in a different order;82- object lifecycle changes between the new check and final use;83- integer widths, signedness, truncation, alignment, and unit conversion;84- duplicated vendor forks and statically linked copies;85- cleanup/error paths that skip the new invariant.8687Build a matrix; do not free-associate variants.8889## Phase 4: Search by Predicate9091Translate the fix into queries:9293- CodeQL/Semgrep/Coccinelle for source patterns;94- compiler-aware grep for helper call sequences;95- IDA/Ghidra scripts for call-before-check or missing-callee patterns;96- binary feature matching for old/new basic-block shapes;97- runtime tracing for consumers that reach the sink without the new validation event.9899Example abstractions:100101```text102open(path) -> validate(path) -> reopen(path) # identity not preserved103size = count * width without checked multiplication104authorize(token A) -> revert -> act(token B)105normalize(name) in one branch, raw name in sibling branch106validate leaf reparse tag but reopen through mutable parent107```108109Completion criterion: every hit is tied to the root-cause predicate, not merely a shared API.110111## Phase 5: Latest-Stable and Novelty Validation112113For each candidate:1141151. reproduce on exact latest stable bytes;1162. prove the old public issue is fixed in its original path;1173. prove the new path remains vulnerable;1184. compare root cause, trigger, component, and impact with public descriptions;1195. search whether the variant path has already been disclosed;1206. record why this is a distinct instance, incomplete fix, or regression.121122If the original old PoC simply works unchanged, investigate regression provenance; do not assume novelty.123124Completion criterion: `zero-day-target-eligibility` passes with a written distinction from the known issue.125126## Phase 6: Minimize and Bisect127128- minimize the trigger around the variant-specific condition;129- build a negative control exercising the fixed original path;130- bisect packages/commits to find introduction or regression;131- determine whether the variant predates, survives, or reappears after the original fix;132- quantify affected stable releases without losing latest-version proof;133- derive a regression test that covers all sibling paths.134135## High-Value Fix Smells136137- validation added after partial parsing;138- denylist of one path/name/tag rather than object identity validation;139- check performed before queueing asynchronous work;140- check under caller impersonation, side effect after revert;141- count capped but secondary count/stream/metadata unbounded;142- only one protocol opcode or content-type patched;143- security check copied rather than centralized;144- exception converted to generic error while state remains mutated;145- defense-in-depth patch with no corresponding tests;146- fix in UI/client while server endpoint remains reachable;147- recovery/offline implementation not updated with online component.148149## Common Pitfalls1501511. Running public PoCs without reconstructing root cause.1522. Calling a byte-level patch difference a security difference.1533. Ignoring servicing branches and independently updated components.1544. Searching only renamed functions rather than semantic predicates.1555. Treating an incomplete fix already discussed publicly as a new zero-day.1566. Failing to prove the original path is fixed and the sibling path is distinct.1577. Overfitting to compiler noise in binary diffs.1588. Skipping error, fallback, and recovery paths.159160## Verification Checklist161162- [ ] Original invariant and primitive reconstructed163- [ ] Pre/post artifacts provenance and hashes recorded164- [ ] Fix predicate and enforcement boundary recovered165- [ ] Variant matrix covers sibling and exceptional paths166- [ ] Semantic searches implemented167- [ ] Original public path shown fixed168- [ ] Candidate shown vulnerable on latest stable169- [ ] Novelty distinction documented170- [ ] Trigger minimized and negative control included171- [ ] Introduction/regression range established where possible172- [ ] Generalized regression test proposed173