How does a secret scanner decide a string literal in source is a live credential?
answer
- No dataflow to follow here
- Content and surroundings, not paths
- Shape rules are precise but narrow
- Randomness scoring trades precision for reach
- Deleting the line is not remediation
basics
~20 sBy content and context, not dataflow: issuer-specific patterns with embedded checksums, entropy scoring of candidate strings, and name and path heuristics. Some scanners then verify liveness with the issuer, which is a deliberate choice, not a default.
solid answer
~50 sA credential has no path to follow, so the detector guesses from the string and its surroundings. **Issuer-shaped patterns** match a fixed prefix, length and often an embedded checksum - very high precision, but only for issuers someone wrote a rule for. **Entropy scoring** measures information per character over candidate tokens and flags anything above a threshold - high recall for unknown issuers, poor precision, because digests, opaque identifiers and encoded fixtures score just as high. **Context heuristics** adjust the score using the surrounding key name and the file path. Some scanners **verify** a candidate against the issuer, which nearly eliminates false positives but sends candidate credentials to a third party and must be a documented decision. Misses come from concatenated or extra-encoded values, low-entropy human passwords, and anything outside the scanned tree. And a confirmed hit is an incident: rotate first, because the old commit still carries the value.
code
pseudocode · 11 linesfunction scoreCandidate(literal, keyName, filePath):
if matchesIssuerGrammar(literal) and checksumValid(literal):
return 0.98 # shape rule: near-certain
score = 0.0
if shannonEntropyPerChar(literal) > 4.5 and length(literal) >= 24:
score = 0.55 # looks random
if keyName contains any of ["secret", "token", "password", "apikey"]:
score = score + 0.20
if filePath contains any of ["test", "fixture", "sample", "example"]:
score = score - 0.35
return scorego deeper
Be ready to say a credential in code is treated as disclosed the moment it is committed, and that the remediation is rotating it at the issuer rather than editing the file.
Explain the detector families and their opposite error profiles: exact issuer grammars are precise but narrow, randomness scoring reaches further and flags digests, fixtures and identifiers constantly.
Show the incident sequence and the traps in it: rotate first, then read the issuer's usage records carefully, then remove and extend the detector. Be able to say why timestamp evidence across build agents can mislead you.
Decide the policy: which detector tier blocks a change, who owns the periodic history sweep, whether candidate verification against third parties is permitted at all, and how rotation is made cheap enough that people actually do it.
### Why a credential is hard to recognise Every other finding a security analyzer produces is about *structure* - a path, a call, a shape. A hard-coded credential is about *content*: a run of characters that looks like a key. There is no dataflow to follow, so a detector has to guess from the string itself and from its surroundings, and that is why this detector family has such a distinctive error profile. ### The three detector families **1. Provider-shaped patterns.** Many credential issuers emit tokens with a fixed prefix, a fixed length and, increasingly, an embedded checksum over the body. A rule matching that grammar is extremely precise: a match is nearly always a genuine token of that type, and the checksum lets the detector reject look-alikes without contacting anyone. The weakness is coverage - it recognises only the issuers someone wrote a pattern for, and it recognises nothing about a database password chosen by a human. **2. Entropy heuristics.** A generic detector extracts candidate tokens (quoted literals, values after an assignment, long unbroken runs of characters) and scores their **Shannon entropy** - the average information per character over the string's own character distribution. Random-looking material scores near the alphabet's ceiling: roughly 6 bits per character is the maximum for a 64-symbol encoding, about 4 for a hexadecimal one, while ordinary identifiers and prose score far lower because their characters are unevenly distributed. Detectors set a threshold, often somewhere around 4.5 bits per character over a minimum length, and flag what clears it. High recall against unknown issuers; poor precision, because the world is full of high-entropy strings that are not secrets. **3. Contextual heuristics.** The name beside the value carries signal: an assignment target or key containing words for password, token, key or secret raises the score, and a path or filename containing test, sample, fixture or example lowers it. This is usually a multiplier on the other two rather than a detector on its own. **4. Verification (optional, and a judgement call).** Some scanners take a candidate and ask the issuing service whether it is live. That converts a guess into a fact and collapses false positives to near zero for supported issuers - but it sends candidate credentials to a third party, and it must be a deliberate, documented decision rather than a default someone turned on. ### Why real keys are still missed A credential assembled from concatenated fragments has no single high-entropy literal. A credential wrapped in an extra encoding layer looks like data. A weak human-chosen password has low entropy by definition and cannot clear an entropy threshold without drowning the report in prose. Secrets living outside the scanned tree - a build configuration, a container image layer, a deployment manifest, a notebook, a binary asset - are missed simply because they were never fed in. And a scan of the working tree only says nothing is there *now*: a credential removed in a later commit is still present in the history, still readable by anyone with a clone, and still live until it is rotated. ### Why innocent strings are flagged Digests, content hashes, opaque identifiers, lockfile integrity fields, sample keys copied from documentation, deliberately fake fixtures used by tests, minified assets and encoded test payloads all look exactly like credentials to an entropy detector. On the 11-person ride-hailing dispatcher team, a first history-wide scan flagged 213 candidate strings across the repository; 26 were real credentials, 9 of which had already been rotated for unrelated reasons, and the largest single false-positive family was a fixture file of encoded dispatch payloads used by the routing tests. ### Triage differs from every other finding The point worth making in an interview is that a confirmed secret finding is an **incident**, not a backlog item, and the order of operations is fixed: 1. **Rotate first.** Assume disclosure from the moment the value was committed. Deleting the line changes nothing - the old commit still carries it. 2. **Then check use.** Look at the issuer's own logs for use of that credential from unexpected places or at unexpected times, and be careful reading those timestamps: on the dispatcher's estate, a clock-skew artefact between build agents once made a rotation look as if it had happened *after* a suspicious use, which sent the team chasing a compromise that had not occurred. 3. **Then remove and prevent.** Take the literal out of the code, move it behind a runtime-supplied value, and add the pattern to the detector so the family cannot come back silently. And the program-level move: because precision decides whether anyone keeps reading, most teams run the high-precision provider patterns as a blocking check on new changes, and keep the broad entropy sweep as a periodic, human-reviewed pass over the whole history rather than something that stops a change.
- A credential is found in a commit from four months ago and has already been deleted from the current code. Is there anything to do?Yes - treat it as disclosed. Anyone who cloned the repository still has the value, so the only remediation that changes the attacker's position is rotation at the issuer. After rotating, review the issuer's usage records for that credential around the exposure window, then decide separately whether rewriting history is worth the disruption. History rewriting is cleanup; rotation is the control.
- Why is a broad entropy sweep usually not run as a blocking check on every change?Because its precision is too low for an audience with minutes and no context. Digests, opaque identifiers, integrity fields and encoded test fixtures all clear an entropy threshold, so blocking on it teaches people to bypass the check. The common split is to block on the high-precision issuer patterns and run the entropy sweep periodically over the whole history as a reviewed pass with a named owner.
- What kinds of real credentials will an entropy-based detector reliably miss?Anything that does not look random: human-chosen passwords, short shared values, and credentials assembled at run time from concatenated fragments so no single literal carries the whole string. It also misses values wrapped in an extra encoding layer, and anything living outside the scanned tree - build configuration, image layers, deployment manifests, binary assets. Coverage of what was actually scanned matters as much as the threshold.
It is the difference between recognising a passport by its exact layout and holograms, and guessing that any card covered in random-looking numbers must be one - the first is nearly always right but only for passports you have seen, the second catches more and is wrong constantly.
saying these in an interview costs you the question
- Says removing the line from the code fixes it
- Treats every high-entropy string as a credential
- Assumes a clean working tree means clean history
- Enables third-party verification without a decision
- Thinks the scanner tracks dataflow to find secrets
- Rotates but never checks the issuer's usage records