Official agent skill

Constant-Time Analysis

by trailofbits in trailofbits/skills

Compiles cryptographic code and inspects the assembly or bytecode for variable-time instructions, then triages which flagged operations actually touch secrets.

OfficialCC-BY-SA-4.0Auto-check: notesSecurity

Install Constant-Time Analysis

skills CLI
$ npx skills add trailofbits/skills --skill constant-time-analysis -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install trailofbits/skills constant-time-analysis --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/trailofbits/skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/constant-time-analysis/skills/constant-time-analysis .claude/skills/constant-time-analysis && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
constant-time-analysis
GitHub stars
7.4k
Token cost
~3.3k tokens
SKILL.md length
1,585 words
Files
12 (incl. references, assets)
Skills in repo
79
Repo updated
First seen
Licence
CC-BY-SA-4.0

At a glance

Compiles cryptographic code and inspects the assembly or bytecode for variable-time instructions, then triages which flagged operations actually touch secrets.

  • Works in 3 steps: Static only — reads assembly and… → No data flow analysis — see triage above. → Configuration-specific — a different…
  • Reviewing a signature, encryption, KEM or key derivation routine for timing leaks
  • SKILL.md covers When to Use, When NOT to Use, Language Routing and Running the Analyzer, plus 5 more sections
  • Calls go, uv and dotnet

What it does

A bundled analyzer script takes one source file at a time, detects the language from its extension and, run with the warnings flag, lists instructions whose timing can depend on data, such as division or modulo on values derived from keys, plaintext, nonces or tokens. The compilation step is mechanical; the real work is deciding which flagged operations handle secrets.

Before interpreting results, the agent reads the guide for the target language in the references folder. One guide covers C, C++, Go and Rust, and others cover Swift, Java with C#, Kotlin, PHP, JavaScript with TypeScript, Python and Ruby, each listing dangerous instructions and constant-time replacements. The check is static: it never runs the code under test, cannot see cache or other microarchitectural channels, and timing measurement belongs to a different skill.

When your agent uses it

  • Reviewing a signature, encryption, KEM or key derivation routine for timing leaks
  • Checking whether a division or modulo touches a key-derived value
  • Auditing functions named sign, verify, encrypt, decrypt or derive_key
  • Answering constant-time programming questions for a specific language

Example prompts

  • “Run the constant-time analyzer on src/kem.c and tell me which flagged divisions touch secrets.”
  • “Is our Rust decrypt function free of secret-dependent branches?”
  • “Check this Kotlin key derivation helper for timing side channels.”
  • “Could our key-encapsulation code have a KyberSlash-style timing problem?”

Requirements

  • uv, to run the analyzer script
  • A toolchain that can compile the target language
  • Pre-approved tools (allowed-tools): Bash, Read, Grep, Glob

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. Static only — reads assembly and bytecode, never runtime behavior. Cache timing and other microarchitectural channels are invisible.
  2. No data flow analysis — see triage above.
  3. Configuration-specific — a different compiler, optimization level, architecture, or runtime version can emit different instructions from…

What it can do on your machine

Read from SKILL.md and the folder at commit 82fe822. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves these tools, so the agent can use them without asking each time:

    • Bash
    • Read
    • Grep
    • Glob

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • go
    • uv
    • dotnet

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • github.com
    • kyberslash.cr.yp.to
    • bearssl.org

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Constant-Time Analysis loads about 3.3k tokens when it runs, and up to ~16k if it reads all its reference files. Until then it costs about 82 tokens; SKILL.md has 1,585 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~82
When it runs · the whole SKILL.md, loaded when a task matches
~3.3k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~16k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NotePre-approves every shell command (allowed-tools: Bash)SKILL.md
    allowed-tools: Bash, Read, Grep, Glob

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from trailofbits/skills at commit 82fe822, republished under its CC-BY-SA-4.0 licence (© trailofbits). 1,585 words, ~3,285 tokens.

Download SKILL.mdSave it as .claude/skills/constant-time-analysis/SKILL.md (or your agent's skills folder). This skill also uses 11 other files; get the full folder from GitHub.
name
constant-time-analysis
description
Detects timing side-channel vulnerabilities in cryptographic code. Use when implementing or reviewing crypto code, encountering division on secrets, secret-dependent branches, or constant-time programming questions in C, C++, Go, Rust, Swift, Java, Kotlin, C#, PHP, JavaScript, TypeScript, Python, or Ruby.
allowed-tools
Bash, Read, Grep, Glob
effort
medium

Constant-Time Analysis

Compile the code, inspect the emitted assembly or bytecode for variable-time instructions, then decide which of the flagged operations actually touch secrets. The compilation step is mechanical; the triage step is the work.

When to Use

  • Implementing or reviewing a signature, encryption, KEM, or key derivation routine
  • Code applies / or % to a value derived from a key, plaintext, nonce, or token
  • The user mentions "constant-time", "timing attack", "side-channel", or "KyberSlash"
  • Reviewing functions named sign, verify, encrypt, decrypt, derive_key

When NOT to Use

  • Measuring timing variance on a running binary — use the constant-time-testing skill from the testing-handbook-skills plugin, which covers dudect and statistical approaches and may not be installed. This skill inspects compiler output statically and never executes the code under test.
  • Non-cryptographic code, or crypto code where every input is public
  • High-level API usage where a vetted library owns the constant-time guarantees
  • Cache and other microarchitectural side channels — the assembly view cannot see them

Language Routing

Read the guide for the target language before interpreting any findings; each one lists that language's dangerous instructions and the idiomatic constant-time replacements.

Running the Analyzer

The analyzer takes one file and detects the language from its extension. Always pass --warnings:

bash
uv run {baseDir}/ct_analyzer/analyzer.py --warnings <source_file>

Without it the analyzer reports only error-severity findings, which means division, modulo and weak RNG. Four detector families are warning severity and stay silent: secret-dependent branches, early-exit comparison (memcmp, strcmp, .equals, ==), table lookups indexed by a secret, and variable-time encoding. Early-exit comparison of an authentication tag is the most common timing bug in real code — Lucky Thirteen was exactly that — so a default run is quiet about the finding you are most likely to have.

FlagEffect
--warningsAdd the four warning-severity families above. Pass it every time
--func <regex>Restrict output to function names matching the regex
--jsonMachine-readable output
--githubGitHub Actions annotations
--arch <target>Target architecture (x86_64, arm64, riscv64, ...) — native languages only
--opt-level <level>Optimization level (O0 through O3, Os, Oz) — native languages only
--compiler <name>Override compiler choice (gcc, clang, go, rustc, swiftc)

Narrow a large file to the routines that handle secrets with a regex, for example --func 'sign|verify'.

Run natively compiled code (C, C++, Go, Rust, Swift) at more than one --arch and --opt-level. Division timing and branch lowering are architecture- and optimization-dependent: x86_64 IDIV and arm64 SDIV differ, and a cmov at -O2 can become a branch at -O0. A single clean run proves one configuration safe, not the code.

How --arch crosses depends on the toolchain. clang crosses with --target and needs no second compiler, but any source that includes libc headers also needs that target's C library headers — libc6-dev-riscv64-cross and friends — or it fails with bits/libc-header-start.h file not found. Go cross-builds through GOARCH, though go tool objdump has no riscv64 disassembler. A GNU cross toolchain is a separate binary, so gcc needs it named explicitly — --compiler x86_64-linux-gnu-gcc, --compiler riscv64-linux-gnu-gcc — and nothing is substituted for you, so the report always names the binary that ran. rustc needs the target's standard library (rustup target add), and Swift on Linux targets only the host. Compare against the toolchain that builds your product, not whichever cross build a distribution packages.

Re-run the whole sweep on the fix, across compilers, targets and every level including Os and Oz. Any fix that works by handing the compiler a constant divisor to strength-reduce is a fix only where the compiler chooses to cooperate, and that choice varies more than it looks. Replacing key_coef / (2 * gamma2) with a #defined divisor still emits a real divide here:

ToolchainLevels that emit a division
gcc riscv64O0 through Oz — every level
gcc arm64, gcc x86_64Os, Oz
clang arm64O0, Oz

Strength reduction is an optimizer courtesy, not a language guarantee. Prefer an explicit multiply-shift, and verify it against the original expression over the full input range rather than on sampled values — an off-by-a-power-of-two reciprocal matches for millions of inputs before it diverges.

Java, Kotlin, and C# compile to JVM/CIL bytecode. The analyzer reads that bytecode, so --arch and --opt-level do not apply and the JIT may still introduce variable-time native code the analyzer cannot see.

Per-language coverage limits

Coverage is not uniform, and the gaps change what a clean report means:

LanguageWhat the report does not cover
GoOnly symbols from the analyzed file. go build links the runtime in, and its divisions — all on public data — would otherwise dominate the findings
JavaScript, TypeScriptBytecode findings are restricted to functions the file declares by name, because V8 dumps node's internals the same way it dumps yours. Anonymous callbacks fall to the source scan. For TypeScript, bytecode findings name the function but carry no line, since V8's positions index the transpiled output
Python, Ruby, PHPBytecode reflects the interpreter that ran, not a JIT'd or alternative runtime
RustAnalyzed as a library unless the file declares fn main; private functions with no caller may be optimized away before analysis
SwiftTargets the host platform on Linux; iOS and macOS triples need an Apple toolchain

Since findings and silence both depend on the configuration, say which compiler, architecture, and optimization level produced a result when reporting it.

To sweep a directory, loop in the shell — the analyzer is a deterministic script, one invocation per file:

bash
for f in src/crypto/*.c; do uv run {baseDir}/ct_analyzer/analyzer.py --warnings --json "$f"; done
Prerequisites
LanguageRequirement
C, C++, Go, Rustgcc/clang, go, rustc in PATH
SwiftXcode or Swift toolchain (swiftc)
Java / KotlinJDK (javac, javap); Kotlin also needs kotlinc
C#.NET SDK plus ilspycmd (dotnet tool install -g ilspycmd)
PHPPHP with the VLD extension or OPcache
JavaScript / TypeScriptNode.js
PythonPython 3.x
RubyRuby with --dump=insns support

On a "toolchain not found" error, see references/vm-compiled.md for JVM and .NET installation, macOS keg-only PATH configuration, and troubleshooting.

Show full SKILL.md (614 more words)Show less

Interpreting Results

PASSED — no error-severity finding for the configuration you ran. Warnings do not affect it, so Result: PASSED alongside Warnings: 6 is normal and is not a clean result. Read the warning list before concluding anything.

FAILED — dangerous instructions found, reported per function:

text
[ERROR] SDIV
  Function: decompose_vulnerable
  Reason: SDIV has early termination optimization; execution time depends on operand values

Triaging Findings

The analyzer has no data flow analysis. It flags every dangerous instruction regardless of whether a secret reaches it, so a FAILED report is a worklist, not a verdict. Reporting the raw output as a set of vulnerabilities is the primary failure mode of this skill.

For each flagged instruction, read the source and answer one question: does an operand depend on secret data? Trace from the instruction's function back to the caller's inputs, then classify:

c
// FALSE POSITIVE: operands are a buffer length, already public from the ciphertext size
int num_blocks = data_len / 16;

// TRUE POSITIVE: dividend is a private-key coefficient; IDIV/SDIV leaks its magnitude
int32_t q = secret_coef / GAMMA2;
QuestionIf yes
Is the operand a compile-time constant?Likely false positive
Is the operand a public parameter — length, count, index bound?Likely false positive
Is the operand derived from a key, plaintext, nonce, or token?True positive
Can an attacker influence the operand's value?True positive

State the verdict and the data flow that justifies it for every flagged item. A finding you cannot trace to a secret is not a finding; say so explicitly rather than dropping it silently.

{baseDir}/ct_analyzer/tests/triage_samples/ holds a known-answer case per language: each fixture pairs a true positive with a false positive that the analyzer reports identically, and expectations.json records which is which and why. triage_c.c is the shortest example — the analyzer flags the division in both ct_high_bits and ct_block_count, and correct triage confirms the first and clears the second.

Weak-RNG and encoding findings ask a different question. For Math.random, mt_rand, random.randint, System.Random and base64_encode, no operand is secret, so "does an operand depend on a secret?" does not resolve them. Ask instead what the result is used for: seeding a nonce or key is a true positive, jittering a retry delay is not. These are reported by a regex scan over the source rather than from bytecode, so they are attributed to <source> with a line number instead of to the enclosing function — except in PHP, where they carry the function.

Comparison and lookup findings have their own question, and their own fix. For an early-exit comparison, ask whether either side is secret: comparing an authentication tag, MAC, or password hash is a true positive, comparing a public protocol header is not. For a table lookup, ask whether the index is secret — the array's contents do not matter, only what selects the element. Both are exploitable as written, so a confirmed one needs the language's constant-time primitive rather than a rewrite of the loop:

LanguageConstant-time comparison
C, C++CRYPTO_memcmp (OpenSSL) or sodium_memcmp
Gocrypto/subtle.ConstantTimeCompare
Rustthe subtle crate's ConstantTimeEq
Java, KotlinMessageDigest.isEqual
C#CryptographicOperations.FixedTimeEquals
PHPhash_equals
Pythonhmac.compare_digest
RubyOpenSSL.secure_compare
JavaScript, TypeScriptcrypto.timingSafeEqual

A secret-indexed lookup has no drop-in replacement: it needs a bit-sliced or arithmetic formulation that touches every element, which is why AES S-box tables are the classic case. Encoding a secret through a table — base64_encode, bin2hex, chr/ord — is the same problem in a library, and paragonie/constant_time_encoding is the reference fix for PHP.

Limitations

  1. Static only — reads assembly and bytecode, never runtime behavior. Cache timing and other microarchitectural channels are invisible.
  2. No data flow analysis — see triage above.
  3. Configuration-specific — a different compiler, optimization level, architecture, or runtime version can emit different instructions from identical source.

Real-World Impact

  • KyberSlash (2023) — division instructions in ML-KEM implementations allowed key recovery
  • Lucky Thirteen (2013) — timing differences in CBC padding validation enabled plaintext recovery
  • RSA timing attacks — early implementations leaked private key bits through division timing

References

© trailofbits, CC-BY-SA-4.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 11 other files (references, assets) in plugins/constant-time-analysis/skills/constant-time-analysis of trailofbits/skills.

  • SKILL.md
  • README.md
  • agents/openai.yaml
  • assets/trail-of-bits-mark.svg
  • references/compiled.md
  • references/javascript.md
  • references/kotlin.md
  • references/php.md
  • references/python.md
  • references/ruby.md
  • references/swift.md
  • references/vm-compiled.md

Open the folder on GitHubat commit 82fe822

Compare with similar skills

Constant-Time Analysis next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Constant-Time Analysis compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Constant-Time Analysis this skilltrailofbits/skills7.4k—~3.3kAutomated safety check: NotesCC-BY-SA-4.0
Taint Instrumentation AssistantArabelaTso/Skills-4-SE253—~2.9kAutomated safety check: PassApache-2.0
Security Reviewgithub/awesome-copilot40k1 repos~2.3kAutomated safety check: NotesMIT
Constant Time Analysissickn33/agentic-awesome-skills47k2 repos~2.4kAutomated safety check: PassMIT
Fory Version Bumpapache/fory4.6k—~1.1kAutomated safety check: PassApache-2.0
Find Untested Sourcesdotnet/skills5.6k1 repos~3.3kAutomated safety check: PassMIT

Similar skills

  • Taint Instrumentation Assistant

    ArabelaTso/Skills-4-SE

    Instruments code to track the flow of untrusted or sensitive data at runtime, enabling detection of injection vulnerabilities, data leaks, and privilege violations.

    253 GitHub stars~2.9k tokensUpdated 1 mo ago
    SecurityAuto-check passed
  • Security Review

    github/awesome-copilot

    Official

    AI-powered codebase security scanner that reasons about code like a security researcher — tracing data flows, understanding component interactions, and catching vulnerabilities that pattern-matching…

    40k GitHub starsUsed in 1 repo~2.3k tokens
    SecurityAuto-check: notes
  • Constant Time Analysis

    sickn33/agentic-awesome-skills

    Analyze cryptographic code to detect operations that leak secret data through execution timing variations.

    47k GitHub starsUsed in 2 repos~2.4k tokens
    MobileAuto-check passed
  • Bump Apache Fory release or post-release development versions across Java, Kotlin, Scala, Python, Rust, Go, C++, C, Dart, JavaScript, Swift, integration tests, examples, and source docs.

    4.6k GitHub stars~1.1k tokensUpdated today
    MobileAuto-check passed
  • Official

    Statically pairs source files with test files to list code that no test references, using Roslyn for C# or tree-sitter for many languages, with no build.

    5.6k GitHub starsUsed in 1 repo~3.3k tokens
    Testing & QAAuto-check passed
  • Run profile-driven bottleneck optimization across Apache Fory implementations (Java, C++, Python/Cython, Go, Rust, Swift, C, JavaScript/TypeScript, Dart, Kotlin, Scala).

    4.6k GitHub stars~2.2k tokensUpdated today
    MobileAuto-check passed

More from trailofbits/skills

All 79 skills in this repo
  • CodeQL Security Scan

    trailofbits/skills

    Official

    Scans a codebase for vulnerabilities with CodeQL's data flow and taint tracking in run-all or important-only modes, including data extensions for project-specific sources and sinks.

    7.4k GitHub stars~4.6k tokensUpdated 5 days ago
    Auto-check: notes
  • Code Graph Mermaid Diagrams

    trailofbits/skills

    Official

    Generates Mermaid diagrams from Trailmark code graphs, including call graphs, class hierarchies, module dependency maps, complexity heatmaps and attack surface data flows.

    7.4k GitHub stars~1.7k tokensUpdated 5 days ago
    Auto-check passed
  • Trailmark Graph Evolution

    trailofbits/skills

    Official

    Compares Trailmark code graphs at two snapshots, such as commits, tags or directories, to surface attack paths, blast radius and taint changes that text diffs miss.

    7.4k GitHub stars~3.4k tokensUpdated 5 days ago
    Auto-check passed
  • Let Fate Decide

    trailofbits/skills

    Official

    Draws a 12 Houses tarot spread to break ties when a request is vague or casually delegated, then reads the cards to pick the next step.

    7.4k GitHub stars~2.5k tokensUpdated 5 days ago
    Auto-check: notes
  • Semgrep Security Scan

    trailofbits/skills

    Official

    Detects languages, proposes rulesets for approval, then runs the approved Semgrep scan across a codebase and merges the output into one SARIF file.

    7.4k GitHub stars~3.7k tokensUpdated 5 days ago
    Auto-check: notes
  • Burp Suite Project Parser

    trailofbits/skills

    Official

    Searches and extracts data from Burp Suite project files on the command line: regex searches over responses, audit findings, proxy history and site map data.

    7.4k GitHub starsUsed in 3 repos~4.2k tokens
    Auto-check: notes

Categories

Questions about Constant-Time Analysis

What does Constant-Time Analysis do?

Compiles cryptographic code and inspects the assembly or bytecode for variable-time instructions, then triages which flagged operations actually touch secrets. A bundled analyzer script takes one source file at a time, detects the language from its extension and, run with the warnings flag, lists instructions whose timing can depend on data, such as division or modulo on values derived from keys, plaintext, nonces or tokens. The compilation step is mechanical; the real work is deciding which flagged operations handle secrets.

When should I use Constant-Time Analysis?

Constant-Time Analysis fits situations like: reviewing a signature, encryption, KEM or key derivation routine for timing leaks; checking whether a division or modulo touches a key-derived value; auditing functions named sign, verify, encrypt, decrypt or derive_key; answering constant-time programming questions for a specific language.

How do I install Constant-Time Analysis in Claude Code?

Run `npx skills add trailofbits/skills --skill constant-time-analysis -a claude-code`. Or copy the skill folder (plugins/constant-time-analysis/skills/constant-time-analysis in trailofbits/skills) into .claude/skills/constant-time-analysis in your project. Claude Code loads it when a task matches its description.

How do I install Constant-Time Analysis in Codex?

Run `npx skills add trailofbits/skills --skill constant-time-analysis -a codex`. Or copy the skill folder (plugins/constant-time-analysis/skills/constant-time-analysis in trailofbits/skills) into .agents/skills/constant-time-analysis in your project. Codex loads it when a task matches its description.

Can I use Constant-Time Analysis in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add trailofbits/skills --skill constant-time-analysis -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/constant-time-analysis, .gemini/skills/constant-time-analysis, .github/skills/constant-time-analysis and .opencode/skills/constant-time-analysis in your project.

What does Constant-Time Analysis need to run?

Going by SKILL.md and its folder, Constant-Time Analysis needs the command-line tools its instructions call (go, uv and dotnet). Our summary lists: uv, to run the analyzer script; A toolchain that can compile the target language. Its frontmatter pre-approves these tools: Bash, Read, Grep, Glob.

Does Constant-Time Analysis access the network?

SKILL.md names 3 domains. As links in the text: github.com, kyberslash.cr.yp.to and bearssl.org. This is read from the text; nothing was executed.

Is Constant-Time Analysis safe to install?

Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Constant-Time Analysis use?

Constant-Time Analysis is published under the CC-BY-SA-4.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Constant-Time Analysis use?

About 3.3k tokens (SKILL.md is roughly 13k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 13k tokens, read only when the agent opens those files.

What are the alternatives to Constant-Time Analysis?

Skills that share tags, products or a category with Constant-Time Analysis: Taint Instrumentation Assistant (ArabelaTso/Skills-4-SE, 253 stars), Security Review (github/awesome-copilot, 40k stars), Constant Time Analysis (sickn33/agentic-awesome-skills, 47k stars) and Fory Version Bump (apache/fory, 4.6k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Constant-Time Analysis?

trailofbits (a GitHub organization, an official publisher) maintains it in trailofbits/skills, which has 7,400 GitHub stars. The repository holds 79 skills in this directory. The repository was last updated on October 2, 2026.

Source: trailofbits/skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.