Secrets detection beyond HEAD: git history, CI logs, images

Secrets detection that only scans HEAD misses real leaks. Where credentials hide in git history, CI logs and image layers, and how to verify them safely.

Examples in this article are illustrative, not customer case studies. Product availability and coverage are described on the linked capability pages.

A developer commits a warehouse password to a nightly ETL job’s config and removes it within the hour, so the next secrets scan comes back clean while the password sits intact in git history, in the image built from the earlier commit and possibly in the log of a CI run that failed in between. This post maps where secrets actually end up, how detection finds and confirms them, and why the scanner doing that work must itself be treated as untrusted.

Secrets detection is the practice of finding credentials, such as API keys, tokens, passwords and private keys, wherever they have been written down: every commit in git history, every image layer, CI logs and pasted environments, not only the files at HEAD. Verifying each candidate against its provider then separates live secrets from noise.

Secrets detection that stops at HEAD misses the commit that leaked

Git history is the most common blind spot. A follow-up commit cleans the file at HEAD, but the value remains in the commit that introduced it and is recoverable by anyone with a clone. Rewriting shared history is disruptive enough that most teams sensibly avoid it, so that commit is effectively permanent.

A scanner that checks only the current tree will report the ETL repository as clean while a working password is one git log -p away. Effective secrets detection scans every commit reachable from every branch and tag, then scans new commits as they arrive, so the finding points at the exact commit and author that introduced the value.

Build arguments and image layers keep what the Dockerfile deleted

The ETL job’s Dockerfile passes a registry token with --build-arg so one step can pull a private package. It feels temporary, because the token is not in any file in the repository. Build arguments are frequently recorded in the image’s build history, though, and if a step writes the token to disk before a later step deletes it, the earlier layer still holds it.

“Not visible in the final filesystem” and “not in the image” are different claims, and this class of leak lives in the gap between them. Scanning images for secrets means inspecting each layer and the build metadata, not just the flattened result. Build-time secret mounts, which expose a value to a single step without writing it into a layer, avoid persisting the mount itself in a layer; build commands must still avoid copying or logging its contents. The layer model behind this is covered in container image scanning: layers, base images and real fixes.

CI logs and pasted environments sit outside repository scanning

CI logs are the least governed leak path. A test runner that dumps configuration on failure, a deploy script that prints a curl command with an inline token, a debug flag that echoes the environment: each writes a working credential into a log store that usually outlives the credential’s rotation cycle and is readable by anyone with pipeline access. When the ETL job failed between the two commits, its log may well have printed the warehouse connection string.

Environment dumps complete the picture: printenv output attached to a support ticket, a .env file pasted into chat for a teammate, a debugging session captured in a recording. None of this is code, so repository scanning never sees it. Masking known secret values in CI output and scanning retained logs closes part of the gap. Habit and review close the rest.

Pattern matching finds candidates; verification finds live secrets

Pattern matching is the baseline: expressions tuned to known credential shapes such as provider key prefixes, private key headers and connection string formats. It is fast and reliable for well-known formats, but blind to anything that does not match a known shape, and it cannot tell a live credential from a rotated one.

Entropy analysis flags long, random-looking strings even without a recognised prefix, which catches custom tokens that pattern lists miss, at the cost of precision. Successful authorised verification can establish that a credential is live. A scoped, read-only check against the credential’s own provider establishes whether it still works, which separates “this looks like a secret” from “this secret opens something today”. It is the biggest single lever for making detection output worth acting on.

Noise is the fastest way to make a team ignore secrets alerts

Secrets detection tolerates noise poorly. Missing a true positive is costly, and a steady stream of false ones teaches people to skim alerts instead of investigating them. Test fixtures with placeholder values, example tokens in documentation and hashes that resemble keys all look alike to patterns and entropy.

Verification lets you triage by consequence. A confirmed-live warehouse password needs action today. An unsuccessful check can also mean a network failure, restricted endpoint or unsupported verification method. Treat that result as unverified until an authorised owner establishes whether the credential remains valid. When a live one does need a response, the next steps are in leaked secret response: rotate, trace, then prevent repeats.

The secrets scanner itself belongs in an untrusted band

A secrets scanner handles strings that may be real, working credentials by design. It should never be a process that also holds database credentials, platform tokens or broad network reach it could combine with what it just found. The safer design treats the scanner as hostile by default: ephemeral, stateless, free of platform credentials, and with network reach limited to what a verification check needs.

This matches the control to what the tool touches. Scanners pull in third-party dependencies of their own and parse attacker-influenced input, including the very repositories and images they inspect. Placing them in the untrusted part of your architecture means a compromised or misbehaving scanner cannot turn a finding into a foothold.

Key takeaways

  • Scan full git history, every image layer and retained CI logs, not only the files at HEAD.
  • Verify candidates against their provider so live credentials are separated from placeholders and rotated values.
  • Use build-time secret mounts instead of build arguments for tokens an image build needs.
  • Run secrets scanners in isolated jobs without platform credentials, restrict outbound access and protect any discovered values.

How SecurityVault approaches this

SecurityVault runs supported secrets scanners in isolated scan jobs and reports candidates with available source or image context. History, image and verification coverage depend on the selected scanner and accessible inputs. Provider verification is not available for every secret type; a failed check must not automatically be treated as an invalid credential.

Use an authorised test repository with a credential fixture in a historical commit and another in an image layer. Confirm which inputs the selected scan actually inspects and whether the evidence identifies the relevant location. Include an unsupported verification case and a provider timeout so reviewers can distinguish unknown from invalid. The evaluation should also inspect masking and access to results. A useful finding explains where to investigate without unnecessarily redistributing the sensitive value through tickets, screenshots or broadly accessible reports.

Explore Secrets detection or talk to our team about an evaluation with your engineering, security and compliance stakeholders.

Further reading

See it on your stack

Bring Secrets detection into one finding graph.

SecurityVault is the enterprise security operating system: one graph of findings, policy and evidence from code to cloud. Explore the Secrets detection workflow with your engineering, security and compliance teams. No repository access is needed for the initial demonstration.