Detectors
Each rule is a format-specific pattern, and every one that has a checksum or a structural check verifies it — a plausible-looking string in a test fixture or a vendor’s own documentation is not a finding.
Test keys are reported, not filtered. A
sk_test_… Stripe key routinely
reads real customer data copied in for debugging, and a repository whose
practices leak the test key will leak the live one. Severity is a triage
decision, not a detection one.
Two files, two leaks. The same credential committed to two files is two
findings with two remediations — each file has to be edited. Renaming a file
that contains an already-leaked credential is tracked as two observations
of one credential today, because rename detection is deliberately disabled
during the history walk (a similarity heuristic is itself attacker-influenced
input). The credential’s own identity (a salted digest of its bytes) is
identical either way, which is what makes rotation trackable by digest rather
than by location — see Remediation below.
Validity checking
Finding a credential and knowing it still works are different facts. For five rules with a safe, read-only “who am I” endpoint, TRUSTIVAN can ask the credential’s own provider:
Every one of those five URLs is a literal string in TRUSTIVAN’s code.
None is built from anything a scan observes — not the host, not the path —
so nothing in a repository can redirect the check anywhere else. The
credential travels in exactly the header or body position its own provider’s
auth scheme documents, is never logged, and is discarded the instant the
provider answers; only the verdict (
live, invalid, or unknown) and a
timestamp are stored. A network failure or a 5xx resolves to unknown,
never to invalid — an outage must never read as “this credential is dead.”
Not covered, and there is no plan to fake it: AWS keys, GCP keys, private
keys, database URLs and the generic high-entropy rule have no validity check.
An AWS access key ID alone cannot authenticate to anything — it needs its
paired secret key, which this scanner does not correlate across a file — and
“validating” a database URL would mean TRUSTIVAN connecting to a host a
customer’s repository named, which is exactly the server-side request
forgery every other outbound path in this product exists to refuse.
Turning it on, and off
Off by default, for every organization. Turning it on makes TRUSTIVAN present your own discovered credentials to their own providers on your behalf — that’s a decision only an owner or admin can make, and only a human, never an API key:GET the same path to read the current setting. Turning it off stops every
future check; verdicts already recorded on existing findings are not erased,
because a credential that was live an hour ago is still evidence.
A confirmed-live credential is raised to critical severity — this is
no longer “a string shaped like a key,” it is one the provider accepted
moments ago.
Push protection
trustivan secrets scan --staged runs the same detector set locally,
against exactly the lines about to be committed, with no network call at
all. It’s the other half of the product: everything above tells you about
a leak that already happened; this stops one from happening.
0 means clean, 1 means a secret was found (the commit should
stop), 2 means the command itself could not run (no git, not a repository).
Only added lines are scanned — a secret already in the file before this
commit is the history engine’s job, not this command’s, and re-flagging it on
every unrelated commit that happens to touch the same file is how a
push-protection hook gets disabled.
Pre-commit hook
CI
git diff origin/main...HEAD) with your
own wrapper, or rely on gate’s repository-target scan, which reads the
full clone rather than the index.
Remediation
POST /api/v1/findings/:id/rotate records that a credential has been
rotated or revoked — who, when, and a required note. This is not a
status change: the finding stays open, because the credential is still
readable in the repository’s history regardless of what you do to it at the
provider, and marking it “resolved” would misrepresent that. What you get is
a durable record — a secret_rotated timeline event and a badge on the
finding — so a rotated credential doesn’t sit in the backlog looking
unaddressed.
Limitations, stated honestly
- AWS, GCP, private keys, database URLs and the generic rule have no validity check — see above.
- A file rename is tracked as two observations, not one continuous finding, because rename detection is disabled during the history walk.
- Shallow clones are refused by default. A credential introduced before a shallow clone’s earliest commit cannot be found in it, and TRUSTIVAN will not report a shallow scan as a clean one.
secrets scan --stagedonly reads the git index. It does not scan history, and it is not a replacement for the git-history engine — it is the complement to it.

