variant-analysis
Skill6 starsChanged 41 days agoMITView on GitHub
Use immediately after any defect is confirmed - a wrong answer, crash, security hole, or bad pattern - and whenever someone asks "are there others like this?" or "is this the same bug?". Names the mechanism rather than the symptom, derives textual, structural (Roslyn, ANTLR, tree-sitter, Semgrep) and semantic queries, checks the other arms of the dispatch and every place the same rule is written, probes each candidate with a minimal repro, and reports the sweep so a zero result is evidence. Not for initial discovery with no bug in hand.
15 other projects use a version of this.
Adopted by
Most recently taken up by
- mahumadad/quarrytheir own version, first seen Nov 8, 2026
- briiirussell/cybersecurity-skillstheir own version, first seen Nov 1, 2026
- lecluse-net/galaristheir own version, first seen Oct 30, 2026
- mtarcure/claude-vibe-squadtheir own version, first seen Oct 28, 2026
- davidanthonyn/claude-skillstheir own version, first seen Oct 20, 2026
- allanninal/claude-code-skillstheir own version, first seen Oct 17, 2026
Used with
Projects with it also use yara-rule-authoring, second-opinion and 1 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
TheWatcher01Skillyara-rule-authoring
Guides authoring of high-quality YARA-X detection rules for malware identification. Use when writing, reviewing, or optimizing YARA rules. Covers naming conventions, string selection, performance optimization, migration from legacy YARA, and false positive reduction. Triggers on: YARA, YARA-X, malware detection, threat hunting, IOC, signature, crx module, dex module.
Also in 3 projects that use this
MicrosoftSkillsecond-opinion
Independent review of current work or a past session. USE WHEN a user wants a second opinion. DO NOT USE WHEN ordinary code review is wanted — use code-review.
Also in 3 projects that use this
SentrySkillsecurity-review
Finds exploitable application security vulnerabilities in code changes. Use for Warden security scans, appsec review, OWASP-style checks, authentication or authorization bugs, injection, XSS, SSRF, path traversal, secrets, unsafe crypto, webhook verification, open redirects, or sensitive data exposure.
Also in 3 projects that use this
Other versions15 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 15
- waybarrios/opencode-power-pack★ 547same name
- briiirussell/cybersecurity-skills★ 489same name
- mtarcure/claude-vibe-squad★ 220same name
- 0x-Shashi/WEB3-AUDIT-SKILLS★ 61same name
- annatchijova/SKILLS★ 9same name
- allanninal/claude-code-skills★ 1same name
- lecluse-net/galaris★ 1same name
- mahumadad/quarry★ 1same name
- romaintoso78/claude-skills★ 1same name
- TaiMaBenJi/taima-skills★ 1same name
5 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository14 other files it gives its agents.
- agent-fleetSkill
- architecture-auditSkill
- automating-agent-guardrailsSkill
- claude-cloud-sessionsSkill
- cross-platformSkill
- devlogSkill
- dotnet-engineeringSkill
- engineering-standardsSkill
- performance-diagnosisSkill
- reviewSkill
- roslyn-analysisSkill
- spec-compliance-auditSkill
- spec-oracleSkill
- test-gateSkill
The file
We split this skill into the rules it gives an agent
10 rules. 0 are common, 10 are distinctive, and 0 are very specific to this project.
0
Common
Most of the 15 edited versions we read keep these.
10
Distinctive
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 24
When someone asks "are there others like this?", "is this the same bug?", "did we fix all of them?"
- Distinctive: line 25
When a look-alike set of candidates needs triage against one known root cause.
- Distinctive: line 39
If you cannot point at the mechanism in this code, you have a story, not a diagnosis.
- Distinctive: line 44
Same operation, other call sites: Every caller of the API or helper that was misused.
- Distinctive: line 55
Start from an exact match that hits only the known instance.
- Distinctive: line 65
Search the whole repository root, never only the module where the bug was found.
- Distinctive: line 83
When a single case fails while its siblings pass, the usual cause is one rule written down in more than one place, with one copy that …
- Distinctive: line 87
If the rule lives in N places, extracting it into one place *is* the fix.
- Distinctive: line 95
Argue against it: Read the surrounding function, its callers and the types involved, and look for what makes it safe: an earlier guard, a …
- Distinctive: line 156
Narrow scope: Only the original module was searched.
“Common” is measured: kept by at least 6 in 10 of the 15 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Attribution. Adapted from trailofbits/skills
plugins/variant-analysis/skills/variant-analysis/(CC-BY-SA 4.0; seeLICENSEin this directory, which covers this skill only). Changes: aimed at all correctness bugs rather than only security bugs; the root-cause step became "name the mechanism"; added the dispatch-arm and one-rule-in-one-place checks; added Roslyn, ANTLR and tree-sitter structural recipes; every candidate needs a minimal-repro probe; the report became a sweep record in which a zero result counts as evidence; the CodeQL/Semgrep resource files and the workflow were dropped. This adapted skill is distributed under CC-BY-SA 4.0.
Variant analysis
Every bug is a pattern. Once a defect is confirmed, it is one instance of a mechanism, and the same mistake usually lives elsewhere: in a copy-pasted neighbor, at another call site of the same API, in the other arm of the same dispatch, or in a second copy of the same rule. The fix is not done until the sweep is done, and the sweep is not done until you can show the queries you ran and what each one found. (Validated 2026-09-28.)
When to use
- Right after a defect is confirmed (reproduced, root-caused), before or with the fix. Sweep in the same change.
- When someone asks "are there others like this?", "is this the same bug?", "did we fix all of them?"
- When a look-alike set of candidates needs triage against one known root cause.
Not for: initial discovery with no bug in hand (use a review or audit), or explaining unfamiliar code.
Step 1: Name the mechanism, not the symptom
The symptom is what the user saw ("a negative amount prints without its sign"). The mechanism is why the code is wrong ("the sign-handling rule is applied in the value-producing path but not in the validating path"). You can only search for a mechanism. Fill in one of these:
Data flow: "[VALUE of kind K] reaches [OPERATION] without [REQUIRED STEP]." Invariant: "[COMPONENT] must [PROPERTY]; it violates that when [CONDITION]." Duplication: "[RULE] is written in N places; place P disagrees with the others."
If you cannot point at the mechanism in this code, you have a story, not a diagnosis. Go back to debugging.
Then list the expansion axes: the independent directions in which a variant could hide. Each must name concrete identifiers or constructs that exist in the code (grep for them before you claim them):
- Same operation, other call sites. Every caller of the API or helper that was misused.
- Same role, other names.
IsSignedalso meansHasSignandSignSeparate;Readalso meansPeek. - Other arms of the same dispatch (Step 3).
- Other copies of the same rule (Step 4).
- Edge values the repro skipped. Null on both sides, empty versus null, zero, the maximum and minimum of the type, negative zero, a collection with one element, the first and last iteration.
- Name/contract mismatch. Functions whose return value contradicts their name or doc comment. Every caller of such a function is a candidate.
Step 2: Search at three levels, one abstraction at a time
Start from an exact match that hits only the known instance. If it misses, you have misread the bug, and everything built on it is calibrated wrong. Then generalize one element per step, run the query, and read every new hit before the next step. Stop climbing when more than half the hits are noise, and back up.
| Level | Tool | Finds | Misses |
| Textual | rg, git grep | copy-paste, same identifiers, comments and docs repeating the rule | renamed variables, different formatting, semantics |
| Structural | Roslyn syntax walker, ANTLR listener, tree-sitter query, Semgrep | same shape under any names; every switch over the enum; every rule alternative | type-driven and cross-procedure flow |
| Semantic | Roslyn SemanticModel, CodeQL, Semgrep taint | every call resolving to the symbol, every read of a field, value flow | code that does not build |
Search the whole repository root, never only the module where the bug was found. Include tests, generated code sources (templates, grammars), and docs, because a wrong rule stated in a doc gets re-implemented. See references/search-recipes.md for ready-to-edit Roslyn, ANTLR, tree-sitter and Semgrep recipes.
Step 3: Which arm did you fix?
Most dispatches have two or more arms: exact versus approximate, validating versus value-producing, read versus write, encode versus decode, fast path versus slow path, debug versus release, signed versus unsigned, the grammar alternative for one edition versus another. A repro exercises one arm. The existing tests usually follow the same arm. The other arm survives a green suite.
For every fix, write down: the dispatch is at ___; its arms are ___; I fixed ___; the others are ___, and here is the probe that shows each one is correct. If a second arm has the same defect, the arms do not share their rule, so restructure them to share it rather than patching both (Step 4).
Step 4: One rule in one place
When a single case fails while its siblings pass, the usual cause is one rule written down in more than one place, with one copy that disagrees. Search for the rule, not the construct: the constant, the table, the condition, the ordering, the error message. Look in code, tests, generated sources and docs alike.
If the rule lives in N places, extracting it into one place is the fix. Patching each copy leaves N places to drift again. Pair the extraction with a drift test that fails if a second copy reappears or if two consumers disagree.
Step 5: Probe every candidate with a minimal repro
A candidate is not a finding until something runs. For each hit:
- Argue against it. Read the surrounding function, its callers and the types involved, and look for what makes it safe: an earlier guard, a type that makes the bad value unreachable, a normalizing step upstream.
- Write the smallest input that would expose it (a unit test, a five-line source file, a one-record fixture) and run it. Assert the correct value, not merely that it ran. Derive the expected value from the contract or spec, not from the current output.
- Classify it: confirmed (the probe fails), cleared (the probe passes, with the reason recorded), or latent (unreachable today but unprotected; report at lower severity and say what would make it reachable).
Code with no callers today is not cleared. It is latent, and the sweep is exactly how you find it before a caller arrives. Keep every probe as a regression test once it is fixed. (Validated 2026-09-28.)
Step 6: Report the sweep
The report is what turns "I swept it" from an assertion into evidence. A zero result is only meaningful if the queries could have found something. Prove that each query hits the original instance before the fix.
## Variant sweep: <mechanism statement>
Origin: <file:line>, fixed by <change>. Dispatch arms: <list, each marked fixed / probed OK / defect>.
Rule copies: <locations, or "one place: <location>">.
| # | Level | Query (verbatim) | Scope | Hits | Confirmed | Cleared | Latent |
|---|-------|------------------|-------|------|-----------|---------|--------|
| 1 | text | rg -n 'IsSigned\b' --type cs | repo root | 14 | 2 | 12 | 0 |
| 2 | struct| SwitchOverEnum(NumericKind) walker | src/ | 6 | 1 | 5 | 0 |
Confirmed: <file:line, quoted code, probe, fix>.
Cleared, grouped by reason: <reason, count, e.g. "normalized upstream by X: 9">.
Calibration: query 1 hit the origin before the fix: yes.
Regression guard: <test or analyzer or CI rule derived from the best query>.File every confirmed and latent variant in the project's work register, one item each, before it turns into a paragraph of prose. (Practice — not yet validated: the lesson held in use, but its original evidence was only partly re-sourced.) Record the queries that failed alongside those that worked.
Examples
.NET / C#. A decimal rounding bug: Math.Round(x, 2) used banker's rounding where the contract says
half-away-from-zero. Mechanism: "a monetary value reaches Math.Round without an explicit MidpointRounding."
Textual: rg -n 'Math\.Round\(' --type cs. Structural: a Roslyn walker listing every Math.Round invocation
with fewer than three arguments, resolved through SemanticModel so using static System.Math calls are caught
too. Arms: the formatting path (ToString("F2")) and the parsing path round too, so probe both. Rule copies:
three helpers each defined their own rounding. Fold them into one Money.Round, and add an analyzer test that
bans bare Math.Round on decimal.
Compiler / grammar. A statement is rejected when an optional phrase comes before a required one. Mechanism:
"the grammar rule fixes the order of clauses that the language says may appear in any order." Textual: grep the
.g4 files for the phrase keyword. Structural: an ANTLR listener, or a pass over the grammar's own parse tree,
listing every rule whose alternatives are fixed sequences of optional clauses. The sibling statements usually
share the defect. Arms: the parser accepted it for one dialect or edition but not for another, and the semantic
checker had a second copy of the ordering rule. Probe each candidate statement with a three-line source file in
both orders.
Generic. An off-by-one in a pagination helper drops the last item when the count is an exact multiple of the
page size. Mechanism: "an exclusive upper bound is computed as count / size instead of ceil." Textual:
rg -n '/ *(pageSize|size|batch)'. Structural: a Semgrep or tree-sitter pattern for $N / $SIZE used as a loop
bound. Arms: forward versus reverse paging, and the server's copy of the calculation. Probe with count = 0, 1,
size, size + 1.
Why hunts fail
- Narrow scope. Only the original module was searched.
- Symptom search. The query matched the error text, not the mechanism.
- One arm. The sibling arm of the dispatch was never probed.
- Patching copies. N copies of a rule were fixed N times instead of once.
- Generalizing too fast. Several abstractions at once, so the noise cannot be attributed to any of them.
- Uncalibrated zero. A query that could not have hit the original was reported as "no variants."
- Happy-path probes. Null, empty, boundary and both-sides-null cases were never tried.
Standards
The bar is the engineering-standards skill. Its "every bug is a pattern", "two-arm dispatch" and "one rule in one place" rules are Steps 1 to 4 here, and its root-cause rule forbids calling a variant "a quirk" or working around it. A sweep shaped to the smallest diff, where the defect class calls for extracting the rule, falls short of that bar. The review skill's sibling-sweep step runs this skill for each confirmed finding.
Project hooks
A repository specializes this skill by adding a section to its CLAUDE.md:
## Variant analysis
- Structural tooling: <Roslyn walker project path / grammar listener harness / semgrep config>
- Probe harness: <how to run a one-file repro>
- File variants to: <work register path or tracker>Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

