Back to Skills

genotoxic

Graph-informed mutation testing triage. Parses codebases with Trailmark, runs mutation testing and necessist, then uses survived mutants, unnecessary test statements, and call graph data to identify false positives, missing test coverage, and fuzzing targets. Use when triaging survived mutants, analyzing mutation testing results, identifying test gaps, finding fuzzing targets from weak tests, running mutation frameworks (including circomvent and cairo-mutants), or using necessist.

5,841stars513forksUpdated 6/24/2026

Security Assessment

Medium Risk(60/100)

Detected risks:

Privilege Escalation([references/mutation-frameworks.md] sudo)
Security Score60/100

About genotoxic

Graph-informed mutation testing triage that combines mutation testing and necessist (test statement removal) with code graph analysis to sort findings into actionable categories: corroborated findings, false positives, missing unit tests, and fuzzing targets. It parses a codebase with Trailmark, runs a mutation testing framework and optionally necessist, then uses survived mutants, unnecessary test statements, and call graph data to identify false positives, missing coverage, and fuzzing targets. It is intended for triaging survived mutants and analyzing mutation results, and not for codebases with no existing test suite, pure documentation or configuration changes, or single-file scripts with trivial logic.

The workflow has three main phases plus an optional parallel phase. Phase 1 builds the code graph with `trailmark analyze` and runs pre-analysis via the QueryEngine API, which is mandatory before triage and computes blast radius, entry points, privilege boundaries, and taint propagation. Phase 2 runs the appropriate mutation framework and captures survived mutants with their file path, line number, mutation type, and status, filtering to survived mutants only. Phase 2b optionally runs necessist on supported languages (Go, Rust, Solidity/Foundry, TypeScript/Hardhat, TypeScript/Vitest, and Rust/Anchor) to find unnecessary test statements, keeping findings where the test still passed after removal. Phase 3 triages each survived mutant and each necessist removal into a bucket using graph data, mapping necessist removals to a production function first.

Prerequisites include trailmark (installed via `uv pip install trailmark`), a mutation testing framework for the target language, optionally necessist (installed with `cargo install necessist`), and an existing passing test suite; on macOS the skill notes running `ulimit -n 1024` before any mull-runner invocation because newer macOS defaults can crash Mull's subprocess spawning. A recurring principle is to install and run the real tools rather than falling back to manual analysis. Quick classification heuristics mark mutants with no callers, only test callers, logging or display strings, or equivalent behavior as false positives, while findings flagged by both mutation testing and necessist on the same function are corroborated and treated as the highest-value results.

FAQ

What output categories does the triage produce?

Corroborated findings (both tools flag the same function, highest value), false positives (harmless, skip), missing tests (write unit tests), and fuzzing targets (set up fuzz harnesses).

Is necessist required?

No, it is optional but recommended. It runs only on supported languages: Go, Rust, Solidity/Foundry, TypeScript/Hardhat, TypeScript/Vitest, and Rust/Anchor, and you keep findings where the test still passed after the statement was removed.

Why is pre-analysis described as mandatory?

Because pre-analysis computes blast radius, entry points, privilege boundaries, and taint propagation, which Phase 3 triage depends on. It is run via `engine.preanalysis()` before triage.

How are false-positive mutants identified?

Via graph signals: a mutant with no callers (dead code), only test callers (test infrastructure), in a logging or display string (cosmetic), or that is an equivalent mutant (behavior unchanged) is classified as a false positive.

Is there a special setup step on macOS?

Yes. Run `ulimit -n 1024` before any `mull-runner` invocation, because newer macOS versions set unlimited file descriptors by default, which crashes Mull's subprocess spawning.

All Files

6 files
agents/openai.yaml0.1 KB
View
assets/trail-of-bits-mark.svg3.0 KB
View
references/triage-methodology.md11.7 KB
View
references/mutation-frameworks.md28.0 KB
View
references/graph-analysis.md12.8 KB
View
SKILL.md12.5 KB
View

Install genotoxic

Download and extract the skill files to your .claude/skills/ directory.

Quick Setup:

  1. Copy the skill folder to .claude/skills/
  2. Claude will automatically detect and use the skill