FIPS Finding Triage
Structured diagnostic reasoning for classifying individual FIPS crypto audit findings. Determines whether a crypto/ package usage is actual cryptography or non-cryptographic use of a crypto primitive.
This skill follows the abductive triage methodology: resolve coordinate mismatches first (majority of findings are non-crypto), then investigate deeper only when the usage is genuinely ambiguous.
When to Use
- Audit found a CRITICAL or WARNING finding and you need to classify it
- A finding's context is ambiguous — could be crypto or non-crypto
- Vendor dependency uses crypto and you need to determine if it ships in the binary
- Generating evidence for a compliance review
Tier 1 — Fast Path (resolves ~80% of findings)
Most FIPS audit findings are coordinate mismatches: code using a crypto primitive for a non-cryptographic purpose. Check these discriminating signals first, in order:
Check 1: Is it in vendor/ or test code?
| Status |
Action |
In vendor/ and a build-time tool (linter, codegen, analysis) |
FALSE POSITIVE — not compiled into binary. Close. |
In vendor/ and a runtime dependency |
Continue to Check 2, but note: fix owner is upstream. |
In *_test.go or test/ directory |
LOW PRIORITY — fix during test refactor. Close unless specifically asked. |
| In production code (non-test, non-vendor) |
Continue to Check 2. |
Check 2: What does the surrounding code do?
Read 10-15 lines of context around the crypto call. Look for these discriminating patterns:
| Pattern |
Verdict |
Confidence |
| Hash result used as map key, annotation, label, or file name |
NON-CRYPTO |
High |
| Hash result compared for equality (dedup, cache hit) |
NON-CRYPTO |
High |
Hash result stored as sha256:... prefix string |
NON-CRYPTO (content-addressable) |
High |
Hash result used in fmt.Sprintf("%x", ...) for display/logging |
NON-CRYPTO |
High |
Hash used with hmac.New() for request signing or MAC verification |
CRYPTO |
High |
Key generated with rsa.GenerateKey() or ecdsa.GenerateKey() |
CRYPTO |
High |
Used inside tls.Config{} or x509.CreateCertificate() |
CRYPTO |
High |
| Password hashing (bcrypt, scrypt, argon2, or MD5/SHA-1 for passwords) |
CRYPTO |
High |
Result feeds into cipher.NewGCM(), cipher.NewCBCEncrypter() |
CRYPTO |
High |
Check 3: Variable and function naming
Names reveal intent. Check the function name, variable names, and comments:
| Name pattern |
Verdict |
computeHash, configHash, specHash, contentHash |
NON-CRYPTO |
fingerprint, checksum, digest (without "verify") |
NON-CRYPTO |
cacheKey, dedup, etag, annotationHash |
NON-CRYPTO |
sign, verify, encrypt, decrypt, authenticate |
CRYPTO |
seal, open, mac, hmac (as operation, not just import) |
CRYPTO |
password, credential, token (with hash operation) |
CRYPTO |
Tier 2 — Deep Investigation (only if Tier 1 is inconclusive)
If the fast path doesn't resolve the finding, investigate deeper:
Step 1: Trace the data flow
# Find where the hash result is used
rg -n --type go -A 10 '<hash_variable>' <file>
Follow the hash output. Where does it go?
- Into a comparison → NON-CRYPTO
- Into a network write or crypto operation → CRYPTO
- Into a struct field or map key → NON-CRYPTO
- Into a signature or MAC → CRYPTO
Step 2: Check if the algorithm matters
For non-crypto uses, the specific hash algorithm is irrelevant — any hash would work. Ask: "Would replacing MD5 with FNV-1a or CRC32 break the functionality?"
| Answer |
Verdict |
| No, any hash works |
NON-CRYPTO — swap to hash/fnv or crypto/sha256 |
| Yes, must be MD5 specifically |
Check why — protocol compat? Then PROTOCOL-MANDATED |
| Yes, must be cryptographically secure |
CRYPTO — needs FIPS-approved algorithm |
Step 3: Check protocol requirements
If the code implements a protocol (SSH, PGP, WebSocket, AWS S3, UUID):
# Check for RFC references or protocol constants
rg -n -i 'rfc|protocol|spec|standard|compat' <file>
| Status |
Verdict |
| RFC mandates this algorithm (e.g., UUID v3 requires MD5) |
PROTOCOL-MANDATED — needs upstream fix or build-tag gate |
| Protocol supports this as legacy option (e.g., SSH 3DES) |
PROTOCOL-LEGACY — needs upstream decision |
| No protocol requirement found |
Continue investigation |
Output
For each finding, produce a classification record:
### <file>:<line> — <package>.<function>()
- **Classification**: ACTUAL CRYPTO | NON-CRYPTO | PROTOCOL-MANDATED | TEST-ONLY | FALSE-POSITIVE
- **Confidence**: High | Medium | Low
- **Evidence**: <what you observed that led to this classification>
- **Remediation**:
- ACTUAL CRYPTO → replace with FIPS-approved algorithm
- NON-CRYPTO → swap to `hash/fnv`, `hash/crc32`, or `crypto/sha256`
- PROTOCOL-MANDATED → swap or gate behind build tag; document the RFC requirement
- TEST-ONLY → swap algorithm in test code
- FALSE-POSITIVE → no action, exclude from scanner
- **Effort**: XS (<15 min) | S (<1 hour) | M (<4 hours) | L (>4 hours)
Evidence Hierarchy
When classifying findings, trust evidence in this order:
| Label |
Source |
Trust |
| DEFINITIVE |
Code context: actual function calls and data flow |
Highest |
| CONFIG |
Variable/function naming, comments, struct tags |
High |
| HEURISTIC |
Automated pattern matching (non-crypto patterns) |
Medium |
| SOCIAL |
"Someone said this is fine" |
Do not trust — verify |
Follow-up Skills
- Use
@fips-remediation-plan/SKILL.md after classifying all findings to generate TODO lists
- Use
@fips-crypto-audit/SKILL.md to re-audit after fixes to confirm resolution
1---2name: fips-finding-triage3description: Classifies an individual FIPS crypto audit finding as real cryptography or a non-cryptographic use of a crypto primitive, using structured diagnostic reasoning. Follows the abductive triage methodology of resolving coordinate mismatches first, since most findings are non-crypto, then tracing data flow and protocol requirements only when a usage is genuinely ambiguous. Use when an audit surfaces a CRITICAL or WARNING finding that needs classification, when a vendored dependency's crypto usage may not ship in the binary, or when producing evidence for a compliance review.4license: MIT5---67# FIPS Finding Triage89Structured diagnostic reasoning for classifying individual FIPS crypto audit findings. Determines whether a `crypto/` package usage is actual cryptography or non-cryptographic use of a crypto primitive.1011This skill follows the **abductive triage** methodology: resolve coordinate mismatches first (majority of findings are non-crypto), then investigate deeper only when the usage is genuinely ambiguous.1213## When to Use1415- Audit found a CRITICAL or WARNING finding and you need to classify it16- A finding's context is ambiguous — could be crypto or non-crypto17- Vendor dependency uses crypto and you need to determine if it ships in the binary18- Generating evidence for a compliance review1920## Tier 1 — Fast Path (resolves ~80% of findings)2122Most FIPS audit findings are coordinate mismatches: code using a crypto primitive for a non-cryptographic purpose. Check these discriminating signals first, in order:2324### Check 1: Is it in vendor/ or test code?2526| Status | Action |27|--------|--------|28| In `vendor/` and a build-time tool (linter, codegen, analysis) | **FALSE POSITIVE** — not compiled into binary. Close. |29| In `vendor/` and a runtime dependency | Continue to Check 2, but note: fix owner is upstream. |30| In `*_test.go` or `test/` directory | **LOW PRIORITY** — fix during test refactor. Close unless specifically asked. |31| In production code (non-test, non-vendor) | Continue to Check 2. |3233### Check 2: What does the surrounding code do?3435Read 10-15 lines of context around the crypto call. Look for these discriminating patterns:3637| Pattern | Verdict | Confidence |38|---------|---------|-----------|39| Hash result used as map key, annotation, label, or file name | NON-CRYPTO | High |40| Hash result compared for equality (dedup, cache hit) | NON-CRYPTO | High |41| Hash result stored as `sha256:...` prefix string | NON-CRYPTO (content-addressable) | High |42| Hash result used in `fmt.Sprintf("%x", ...)` for display/logging | NON-CRYPTO | High |43| Hash used with `hmac.New()` for request signing or MAC verification | CRYPTO | High |44| Key generated with `rsa.GenerateKey()` or `ecdsa.GenerateKey()` | CRYPTO | High |45| Used inside `tls.Config{}` or `x509.CreateCertificate()` | CRYPTO | High |46| Password hashing (bcrypt, scrypt, argon2, or MD5/SHA-1 for passwords) | CRYPTO | High |47| Result feeds into `cipher.NewGCM()`, `cipher.NewCBCEncrypter()` | CRYPTO | High |4849### Check 3: Variable and function naming5051Names reveal intent. Check the function name, variable names, and comments:5253| Name pattern | Verdict |54|-------------|---------|55| `computeHash`, `configHash`, `specHash`, `contentHash` | NON-CRYPTO |56| `fingerprint`, `checksum`, `digest` (without "verify") | NON-CRYPTO |57| `cacheKey`, `dedup`, `etag`, `annotationHash` | NON-CRYPTO |58| `sign`, `verify`, `encrypt`, `decrypt`, `authenticate` | CRYPTO |59| `seal`, `open`, `mac`, `hmac` (as operation, not just import) | CRYPTO |60| `password`, `credential`, `token` (with hash operation) | CRYPTO |6162## Tier 2 — Deep Investigation (only if Tier 1 is inconclusive)6364If the fast path doesn't resolve the finding, investigate deeper:6566### Step 1: Trace the data flow6768```bash69# Find where the hash result is used70rg -n --type go -A 10 '<hash_variable>' <file>71```7273Follow the hash output. Where does it go?74- Into a comparison → NON-CRYPTO75- Into a network write or crypto operation → CRYPTO76- Into a struct field or map key → NON-CRYPTO77- Into a signature or MAC → CRYPTO7879### Step 2: Check if the algorithm matters8081For non-crypto uses, the specific hash algorithm is irrelevant — any hash would work. Ask: "Would replacing MD5 with FNV-1a or CRC32 break the functionality?"8283| Answer | Verdict |84|--------|---------|85| No, any hash works | NON-CRYPTO — swap to `hash/fnv` or `crypto/sha256` |86| Yes, must be MD5 specifically | Check why — protocol compat? Then PROTOCOL-MANDATED |87| Yes, must be cryptographically secure | CRYPTO — needs FIPS-approved algorithm |8889### Step 3: Check protocol requirements9091If the code implements a protocol (SSH, PGP, WebSocket, AWS S3, UUID):9293```bash94# Check for RFC references or protocol constants95rg -n -i 'rfc|protocol|spec|standard|compat' <file>96```9798| Status | Verdict |99|--------|---------|100| RFC mandates this algorithm (e.g., UUID v3 requires MD5) | PROTOCOL-MANDATED — needs upstream fix or build-tag gate |101| Protocol supports this as legacy option (e.g., SSH 3DES) | PROTOCOL-LEGACY — needs upstream decision |102| No protocol requirement found | Continue investigation |103104## Output105106For each finding, produce a classification record:107108```markdown109### <file>:<line> — <package>.<function>()110111- **Classification**: ACTUAL CRYPTO | NON-CRYPTO | PROTOCOL-MANDATED | TEST-ONLY | FALSE-POSITIVE112- **Confidence**: High | Medium | Low113- **Evidence**: <what you observed that led to this classification>114- **Remediation**:115 - ACTUAL CRYPTO → replace with FIPS-approved algorithm116 - NON-CRYPTO → swap to `hash/fnv`, `hash/crc32`, or `crypto/sha256`117 - PROTOCOL-MANDATED → swap or gate behind build tag; document the RFC requirement118 - TEST-ONLY → swap algorithm in test code119 - FALSE-POSITIVE → no action, exclude from scanner120- **Effort**: XS (<15 min) | S (<1 hour) | M (<4 hours) | L (>4 hours)121```122123## Evidence Hierarchy124125When classifying findings, trust evidence in this order:126127| Label | Source | Trust |128|-------|--------|-------|129| DEFINITIVE | Code context: actual function calls and data flow | Highest |130| CONFIG | Variable/function naming, comments, struct tags | High |131| HEURISTIC | Automated pattern matching (non-crypto patterns) | Medium |132| SOCIAL | "Someone said this is fine" | Do not trust — verify |133134## Follow-up Skills135136- Use `@fips-remediation-plan/SKILL.md` after classifying all findings to generate TODO lists137- Use `@fips-crypto-audit/SKILL.md` to re-audit after fixes to confirm resolution