reviewing-cryptography
Skill11 starsChanged 3 months agoApache-2.0View on GitHub
Review cryptographic implementations and protocol usage for misuse — weak primitives, nonce and IV handling, key management, authentication of ciphertext, randomness, timing side channels, TLS and JWT configuration, and password storage. Use when auditing code that encrypts, signs, hashes, or authenticates, or when assessing TLS and token configurations.
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 3 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
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 52
If you see CBC, find the MAC.
- Distinctive: line 101
Check the work factor against current guidance, not the value that was adequate when the code was written.
- Distinctive: line 187
Canonicalization: if a signature covers a serialized structure, can the same structure serialize two ways?
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Reviewing Cryptography
Almost no real system is broken by cryptanalysis. They are broken by misuse: a reused nonce, unauthenticated ciphertext, a comparison that returns early, a key checked into git. Review for misuse, and leave primitive design to cryptographers.
When to Use
- Auditing code that encrypts, decrypts, signs, verifies, or hashes
- Reviewing key management, rotation, and storage
- Assessing TLS/mTLS configuration and certificate validation
- Reviewing JWT, session token, and API signature schemes
- Checking password and secret storage
- Evaluating randomness quality for security-relevant values
When NOT to Use
- Designing a new primitive or protocol — that needs a cryptographer and formal review, not a code audit
- Breaking cryptography in a CTF — different discipline; use
solving-oriented offensive skills and known-attack tooling - General code review — use
auditing-code-for-vulnerabilities - Password cracking — use
cracking-passwords
The Misuse Checklist
Work through these in order. Each has caught real production breaks.
1. Is the ciphertext authenticated?
Encryption without authentication is the single most common serious finding. CBC or CTR without a MAC means an attacker can modify plaintext — and with a decryption oracle, recover it (padding oracle).
Good: AES-GCM, ChaCha20-Poly1305, AES-CBC + HMAC (encrypt-then-MAC)
Bad: AES-CBC alone, AES-ECB (ever), CTR without a MAC, MAC-then-encryptrg -n 'AES/ECB|AES\.MODE_ECB|CipherMode\.ECB|"AES"\)' -i
rg -n 'AES/CBC/PKCS5Padding|MODE_CBC|createCipheriv\(.*cbc' -iIf you see CBC, find the MAC. If there is no MAC, that is a finding regardless of how the ciphertext is transported.
2. Nonce and IV handling
| Mode | Rule | Failure |
| GCM / ChaCha20-Poly1305 | Never reuse a (key, nonce) pair | Catastrophic: reveals the auth key, forgery becomes trivial |
| CBC | IV must be unpredictable and random per message | Chosen-plaintext attacks (BEAST-class) |
| CTR | Never reuse a counter with the same key | Keystream reuse; XOR of plaintexts |
# The classic bug: a fixed or zero IV
rg -n 'iv\s*=\s*(b?["\x27]0|new byte\[\d+\]|bytes\(\d+\)|\[0\]\s*\*)' -i
rg -n 'IvParameterSpec\(new byte\[16\]\)|createCipheriv\([^,]+,[^,]+,\s*["\x27]'Random 96-bit nonces for GCM are safe up to roughly 2^32 messages per key. A counter-based nonce is safer, but only if the counter state genuinely survives restarts and is not duplicated across instances. Ask where the counter is persisted; "in memory" plus horizontal scaling means reuse.
3. Key management
- Where does the key come from? Hardcoded, env var, KMS/HSM, derived?
- Hardcoded keys, keys in source, keys in config committed to the repo, keys in container images, keys in CI logs — check all of these.
- Is a key used for exactly one purpose? Key reuse across encryption and signing, or across tenants, is a finding.
- Is there a rotation path at all? A system that cannot rotate has no response to compromise.
- Derived keys: is a proper KDF used (HKDF for key material, Argon2id/scrypt/ PBKDF2 for passwords)? A raw SHA-256 of a password is not a KDF.
rg -n 'BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY|-----BEGIN'
rg -n '(secret|api[_-]?key|password|token)\s*[:=]\s*["\x27][A-Za-z0-9/+=]{16,}' -i
gitleaks detect --source . --redact # history matters more than the tree4. Password storage
Correct: Argon2id (preferred), scrypt, bcrypt, PBKDF2-HMAC-SHA256 with a
high iteration count — each with a per-user random salt
Wrong: MD5, SHA-1, SHA-256, SHA-512 (raw or salted), any unsalted hash,
encryption instead of hashing, a "pepper" as the only defenseCheck the work factor against current guidance, not the value that was adequate when the code was written. And check that the verification path uses the library's constant-time verify function rather than comparing strings.
5. Randomness
Security-relevant values — tokens, session IDs, nonces, salts, password reset codes, IVs — must come from a CSPRNG.
rg -n 'math/rand|Math\.random\(\)|random\.random\(|rand\(\)|mt_rand|Random\(\)'
# Correct: crypto/rand, secrets.token_bytes, window.crypto.getRandomValues,
# SecureRandom, os.urandom, RandomNumberGeneratorAlso check: seeding with a timestamp or PID, UUIDv1/v4-from-a-weak-source used as a secret, and predictable sequential IDs used where unguessability is assumed.
6. Timing side channels
Any comparison of a secret must be constant time: MACs, tokens, API signatures, password hashes, OTPs.
rg -n 'hmac.*==|token\s*==|signature\s*==|\.equals\(.*(hmac|token|sig)' -i
# Correct: hmac.compare_digest, crypto.timingSafeEqual, subtle.ConstantTimeCompare,
# MessageDigest.isEqual, hash_equalsEarly-return string comparison of an HMAC is a practical remote attack, not a theoretical one.
7. Signature verification
- Is the signature actually verified, or merely parsed?
- Is the algorithm taken from the message? (JWT
algconfusion:none, and RS256→HS256 where the public key becomes the HMAC key.) - Is the key selected by an identifier the attacker controls (
kid,jku,x5u)? Those fields are attacker input; treat them as such. - Are claims validated after signature verification:
exp,nbf,iss,aud, and — critically — the subject's current authorization?
rg -n 'jwt\.decode\(|verify\s*[:=]\s*(False|false)|algorithms\s*=\s*\[?["\x27]?none' -i
rg -n 'InsecureSkipVerify|verify\s*=\s*False|CURLOPT_SSL_VERIFYPEER.*0|rejectUnauthorized:\s*false'8. TLS configuration
# Server side
testssl.sh --severity MEDIUM https://target
sslyze --regular target:443
nmap --script ssl-enum-ciphers -p 443 target
# Look for: TLS < 1.2, RC4/3DES/NULL/EXPORT ciphers, no forward secrecy,
# weak DH params, expired or misissued certs, missing HSTSClient side is more often wrong than server side. Check that certificate
verification is enabled, that hostname verification is on (it is separate
from chain verification in several libraries), and that custom trust stores
are not silently accepting everything. A custom TrustManager that returns
without throwing is the Java idiom for "no TLS at all."
9. Post-quantum posture
For anything with a long confidentiality lifetime, note harvest-now-decrypt later exposure and whether a hybrid key exchange (e.g. X25519 + ML-KEM) is available in the stack. This is a roadmap finding, not usually an urgent one — but say so explicitly rather than omitting it.
Protocol-Level Questions
Beyond primitives, ask:
- Replay: is there a nonce, timestamp, or sequence number, and is it actually checked and stored?
- Binding: is the signature bound to the whole message, including the recipient and context? Signature-stripping and cross-protocol reuse come from under-scoped signing.
- Downgrade: can a client or server be negotiated to a weaker mode?
- Oracles: does the error handling distinguish "bad padding" from "bad MAC", or decryption failure from authorization failure? Any observable difference — including timing and response size — is an oracle.
- Canonicalization: if a signature covers a serialized structure, can the same structure serialize two ways? JSON and XML signature schemes break here routinely.
Rationalizations to Reject
- "It's encrypted." Encrypted is not authenticated, and not authorized.
- "We use AES-256, so it's strong." Key size is almost never the weak link.
- "The IV is random enough." Show where it is generated and from what.
- "Timing attacks aren't practical over a network." They are, and have been demonstrated repeatedly across the internet.
- "We rolled our own because the library was awkward." Custom crypto is a finding on its own. Name the library that should be used instead.
- "The key is in an environment variable, not the code." Better, but check where the env var is set, who can read the process environment, and whether it appears in logs, crash dumps, or the container image.
- "Certificate pinning is too much hassle." Fine — but then say so as an accepted risk, do not disable verification instead.
- "It's internal traffic." Internal networks are where lateral movement happens.
Deliverable
For each finding: the primitive or protocol involved, the specific misuse, the concrete attack it enables (not "weak crypto"), the affected data and its confidentiality lifetime, and the specific correct construction — named library, named mode, named parameters. Cryptography findings that recommend "use strong encryption" do not get fixed.
Reading External Sources
Fetch public advisories, specifications, and vendor reports as Markdown:
curl -sL "https://defuddle.md/<url>" # scheme in the path is optionalThis strips page boilerplate — roughly 78% fewer tokens on a prose page — and returns the full text rather than a summary, so you can grep it and trust a negative result.
Three things it is not for. Fetch JSON and API responses raw, because readability extraction mangles structured data. Fetch authenticated or JavaScript-rendered pages directly, because it retrieves them anonymously. And never route adversary infrastructure (phishing links, C2, malware hosting), client-owned hosts, or engagement URLs through it — the request leaves your machine to a third party, and for live adversary infrastructure it also tips off the operator.
Some sites block the extractor and return an error blob rather than the page —
{"error":"Failed to fetch: 418 I'm a teapot"} from freedesktop.org, for
instance. That is the fetch being refused, not the source saying the thing
does not exist. Re-fetch the URL directly before drawing any conclusion from
it.
References
auditing-code-for-vulnerabilities— the surrounding code reviewcracking-passwords— offensive side of weak password storagetesting-apis— token and signature handling at the API layer- Libraries to recommend: libsodium/NaCl, Google Tink,
age, platform AEAD APIs testssl.sh,sslyze,cryptography(Python) audit APIs,cargo-crev
Other versions1 project uses a version of this.
Word for word · 1
- EvilFreelancer/secs★ 11100% same
Edited · 0
None found.
Wrote their own version · 0
None found.
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 repository50 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- analyzing-binariesSkill
- analyzing-malwareSkill
- analyzing-memory-imagesSkill
- analyzing-network-trafficSkill
- analyzing-phishing-emailsSkill
- attacking-active-directorySkill
- attacking-wireless-networksSkill
- auditing-code-for-vulnerabilitiesSkill
- auditing-mcp-serversSkill
- auditing-supply-chainSkill
- container-securitySkill
- cracking-passwordsSkill
- engineering-detectionsSkill
- enumerating-network-servicesSkill
- escalating-linux-privilegesSkill
- escalating-windows-privilegesSkill
- establishing-persistenceSkill
- exploiting-cloud-platformsSkill
- hardening-cloud-postureSkill
- hunting-threatsSkill
- hunting-web-backdoorsSkill
- iac-securitySkill
- investigating-aws-incidentsSkill
- investigating-azure-incidentsSkill
- investigating-gcp-incidentsSkill
- investigating-m365-entraSkill
- investigating-windows-endpointsSkill
- maintaining-engagement-stateSkill
- managing-vulnerabilitiesSkill
- mapping-attack-techniquesSkill
- orchestrating-vulnerability-researchSkill
- performing-reconnaissanceSkill
- performing-social-engineeringSkill
- producing-threat-intelligenceSkill
- recognizing-deceptionSkill
- reporting-security-findingsSkill
- responding-to-incidentsSkill
- securing-ai-systemsSkill
- testing-apisSkill
- testing-ics-ot-protocolsSkill
- testing-mobile-applicationsSkill
- testing-web-applicationsSkill
- threat-modelingSkill
- transferring-filesSkill
- triaging-security-alertsSkill
- vetting-agent-extensionsSkill
- writing-sigma-rulesSkill
- writing-yara-rulesSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
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.

