Imagine accidentally committing an API key to a Git repository.
You notice the mistake, delete the key, commit the change, and push again.
Problem solved?
Not necessarily.
Git stores the history of your project. Removing a secret from the latest version of a file doesn't automatically remove it from previous commits.
Here's a simple example.
- Create a test repository
mkdir git-history-demo
cd git-history-demo
git init
Create a file containing a fake credential:
echo "API_KEY=example-not-a-real-key" > config.env
git add config.env
git commit -m "Add configuration"
Now remove it:
git rm config.env
git commit -m "Remove configuration"
The file no longer exists in your working directory.
But the original commit still exists.
- Check the Git history
Run:
git log -p --all -- config.env
You'll see the earlier commit containing the fake credential.
This is normal Git behavior, but it becomes a security problem when developers accidentally commit real API keys, authentication tokens, or passwords.
Deleting a secret does not mean it was never exposed.
- What happens if a real secret is committed?
The first priority should be to revoke or rotate that credential.
Rewriting Git history may help remove sensitive data from the repository, but it cannot guarantee that nobody has already copied it.
GitHub provides official guidance:
Removing sensitive data from a repository
- Why I started building JetScan
While working on developer tools, I wanted a straightforward way to identify security problems without uploading source code to a third-party scanning service.
So I started building JetScan, a source-available security scanner written in Rust.
It can check:
Exposed secrets in project files and Git history
Known vulnerabilities in supported dependency ecosystems
Potentially risky GitHub Actions workflows
Certain local credential and machine security issues
For example:
jetscan secrets .
Or run a broader scan:
jetscan scan .
JetScan supports local scanning and offline operation. Dependency vulnerability checks can query OSV using package names and versions unless offline mode is used.
The project is still young. It doesn't detect every possible secret, and I don't want to pretend it does.
The fake credential in the example above is for demonstrating Git history; it isn't a verified JetScan detection example.
- Why Git history scanning matters
Many developers already use .gitignore to avoid accidentally committing local configuration files.
That's useful, but .gitignore does not remove secrets that were committed previously.
Even when a repository looks clean today, its history may contain sensitive information.
That's why checking the current files alone isn't always enough.
- Try JetScan
I've released JetScan for Windows, Linux, and macOS.
You can explore the source code, releases, and technical documentation here:
GitHub: https://github.com/y6861977-ui/jetscan
I'm looking for feedback from developers who use security scanning tools in their projects or CI pipelines.
What matters most to you in a security scanner: detection accuracy, performance, privacy, integrations, or something else?
I'd be interested to hear your experience.
Top comments (1)
Good reminder — I learned this the hard way early on, when I assumed deleting a file and pushing fixed the mistake. It didn't, and the key was still right there in the history. Rotating the credential first, before worrying about cleaning up the repo, is the part I wish someone had drilled into me sooner. I also keep a pre-commit hook now that scans for secrets, since catching it before the commit is so much less painful than cleaning up afterwards. Thanks for the clear example.