Skill: Zeroize Audit
by Trail of Bits
Finds secrets left in memory in C, C++ and Rust — including wipes the compiler deleted — and requires IR or assembly evidence before calling one optimized away.
Compiles cryptographic code and reads the emitted assembly for variable-time instructions, then triages which flagged operations actually touch secrets.
Add this skill to your favorite AI agent in a few steps.
Learn how to use this skill with different AI agents.
Check whether this Kyber reference implementation is constant-time — I am most worried about the division in the polynomial compression routine, and we ship on both arm64 and riscv64.
Timing side-channels are the class of bug that source review is worst at catching, because the vulnerability is introduced by the compiler rather than written by the developer. A branch that looks constant-time in C becomes a real branch at -O0 and a cmov at -O2; a division by a constant is strength-reduced on one target and emitted as a genuine IDIV on another. Reading the source tells you nothing about which happened.
This skill from Trail of Bits takes the only approach that answers the question: compile the code, disassemble it, and look at the instructions that actually shipped. A bundled analyzer detects the language from the file extension and reports variable-time operations across C, C++, Go, Rust, Swift, Java, Kotlin, C#, PHP, JavaScript, TypeScript, Python and Ruby, with per-language reference guides covering that language's dangerous instructions and their constant-time replacements.
Four detector families are warning-severity and stay silent unless the analyzer is run with --warnings, which the skill instructs the agent to pass every time: secret-dependent branches, early-exit comparison (memcmp, strcmp, .equals, ==), table lookups indexed by a secret, and variable-time encoding. That default matters — early-exit comparison of an authentication tag is the single most common timing bug in shipped code, and it is exactly what Lucky Thirteen exploited. Error-severity findings (division, modulo, weak RNG) are reported without the flag.
The skill insists on running natively compiled code at more than one --arch and --opt-level, because a single clean run proves one configuration safe rather than the code. Its own documentation carries the measurement that justifies this: replacing a secret-dependent divisor with a #defined constant still emits a real division on gcc riscv64 at every optimization level, on gcc arm64 and x86_64 at Os and Oz, and on clang arm64 at O0 and Oz. Strength reduction is an optimizer courtesy, not a language guarantee, so the fix has to be verified across the toolchain that builds your product.
The skill documents where a clean report means less than it appears — Go findings cover only symbols from the analyzed file, TypeScript bytecode findings carry no line numbers because V8 indexes transpiled output, Python/Ruby/PHP reflect the interpreter that ran rather than a JIT, and JVM/CIL bytecode analysis cannot see native code the JIT introduces later. Cache and other microarchitectural side channels are explicitly out of scope, since the assembly view cannot see them.
It is a static tool and never executes the code under test; measuring timing variance on a running binary is a different skill in the same collection.
by Trail of Bits
Finds secrets left in memory in C, C++ and Rust — including wipes the compiler deleted — and requires IR or assembly evidence before calling one optimized away.
by Trail of Bits
Trail of Bits' CodeQL skill: build databases, run taint-tracking and data-flow queries across eight languages, and model project-specific sources and sinks.
by Trail of Bits
Trail of Bits' skill for writing production-quality Semgrep rules — pattern design, taint mode for data-flow bugs, and mandatory test-driven validation.
Trail of Bits' security review skill for PRs, commits, and diffs: risk-first analysis with git history, blast radius, and honest coverage limits.