Committed Secret Files
One missing .gitignore, and your .env ships to the world.
What Is Committed Secret Files?
Hardcoding a secret in source is one problem. Committing a whole file of them is another. A repository with no .gitignore tracks .env files, private keys and service-account JSON from the first commit, and once a file is tracked it belongs to the history, so every clone carries a copy. You'll clone a public repository, read a committed .env, and reach a live staging environment. Then you'll untrack the files with git rm --cached, rotate every exposed key, add a .gitignore, and install a pre-commit hook that blocks secret filenames.
What You'll Learn in Committed Secret Files
- Recognize that a missing or incomplete .gitignore lets a whole secret file, a .env, private key, or service-account JSON, get committed and tracked from the first commit
- Understand why every clone of a public repo carries a copy of a tracked secret file, so the exposure cannot be undone by deleting the file later
- Distinguish committing a secret FILE under version control from hardcoding a secret literal inside source code, and know both must be kept out of the repo
- Apply the cleanup: remove the files from tracking with git rm --cached and rotate the exposed keys, treating any pushed secret as compromised
- Prevent recurrence with a .gitignore that covers secret files plus a pre-commit hook that blocks known secret filenames before they are committed
Committed Secret Files — Training Steps
-
Size up the target
Today Bob is targeting Tavonn, a payments-integrations startup that ships some of its code in the open. He starts on the public repository, sizing up what the company runs before he looks for a way in. A public repo is a gift to someone like Bob: the whole project, every file, downloadable in one command.
-
Clone the repo
Bob clones the repository to his own machine so he can read every file it tracks, offline and at his own pace. Whatever the repo tracks comes down with the clone. If a secret file was ever committed, it is in the copy he just pulled.
-
List the tracked files
Bob lists everything the repository tracks. He is not looking at what is on disk, he is asking git which files are actually under version control, because those are the ones every clone carries.
-
Read the secret file
Bob opens the committed environment file. This is the difference between this leak and a single hardcoded key: it is not one value pasted into a code line, it is an entire file of secrets under version control. Everything the service needs to run is here, in plain text.
-
Reach the staging environment
A leaked key is only a theory until it opens something. Bob already has every piece he needs from the clone: the committed .env gave him the API base URL in PUBLIC_API_URL and a live key, and the routes he cloned in src/routes/payments.js define the payment feed at /v1/transactions . He assembles the request and carries the key in an Authorization header the way a real client would. Endpoints were never the secret; they sit in the public source. The key was, and the committed file handed him one, so the server has no reason to reject the request.
-
The payment data is open
The server trusted the key and answered. Bob is reading Tavonn's staging payment records from outside the company, with no account of his own.
-
Knowledge check
You just watched a public repo hand an outsider the keys to a live environment. Lock in why.
-
The alert lands
You own Tavonn's payments-service repo. Overnight, the security team's secret scanner flagged the public repository and emailed you. The finding is blunt: a committed .env with live keys is sitting in the public repo, and there is no .gitignore keeping files like it out.
-
Tracked, with no .gitignore
Your first move is to see it for yourself. You list what git is tracking in the repo, and there it is: the .env and the service-account key are under version control, and no .gitignore is in the list. A file present on disk is one thing; a file git is tracking is committed, in the history, and in every clone.
-
Untrack the secret files
You stop git from tracking the secret files with git rm --cached , which removes them from the index while leaving them on disk so the service can still run locally. You commit and push that change, and the files disappear from the current repo. It feels like the fix. It is not, and the next step shows why.
Security Framework Coverage
CWE
- CWE-540 Inclusion of Sensitive Information in Source Code
- CWE-522 Insufficiently Protected Credentials
MITRE ATT&CK
- T1552.001 Unsecured Credentials: Credentials In Files
CIS Controls
- CIS 3 Data Protection
- CIS 16 Application Software Security
NIST CSF
- PR.AT-02 Individuals in specialized roles are provided with awareness and training so that they possess the knowledge and skills to perform relevant tasks with cybersecurity risks in mind
- PR.DS Data Security
- PR.PS Platform Security