A repository on GitHub contains things that must never leave the building:
data/customers.csv with real customer rows, and a config.py holding
DB_PASSWORD = "..." in plain text. You find it yourself while adding a
.gitignore, a reviewer spots it in the first pull request, or GitHub's secret
scanning emails an alert minutes after the push. Deleting the files and pushing
again does not help — both are still readable in the old commits.
A notebook-to-repo restructure done in a hurry: the project's first git add .
swept in everything sitting in the folder, including the data file and a config
with a password pasted "for now". Common in first restructures precisely because
the notebook era had no git — no habits existed yet to guard the sensitive files,
and .gitignore was left for "later". A public repo makes it urgent: bots scrape
GitHub for fresh credentials within minutes. A private repo is not safe either.
Linked modules: 4.1 (Notebook to repo), 0.2 (Git & GitHub as an engineer).
Two incidents in one push, and they must be triaged separately. The password is a
live credential in an append-only history: as WR-006 established, a later delete
does not touch earlier commits, and clones or forks keep full copies — so the
password is burned the moment it left, regardless of any cleanup. The customer
data is a privacy breach, not a hygiene issue: under India's DPDP Act, personal
data exposed in a repository is a reportable incident with legal weight. Confirm
the blast radius: git log --all -- data/ config.py shows when each landed, and
the repo's visibility (public vs private) sets the urgency.
Order matters — value first, cosmetics last. (1) Rotate the password now, exactly
per WR-006's discipline: issue a new credential, deploy it, revoke the old one.
The leaked password must die before anything else. (2) Cut exposure: make the
repo private, or take it down if it was public. (3) Purge data/customers.csv
and the secret from history with git filter-repo (or GitHub support for cached
views), force-push, and have every collaborator re-clone. (4) Report the data
exposure to your lead or data-protection officer — for customer data this is not
optional, and silence converts a mistake into misconduct. (5) Re-home the values:
the secret becomes an environment variable with a committed .env.example naming
the key without the value; the csv goes behind the .gitignore with its source
documented in the README.
.gitignore-first: writing data/, models/, .venv/, .env into it is the
FIRST line of any restructure, before the first git add. Secrets never live in
code — environment variables plus a .env.example template are the pattern from
day one. Review the first commit of any restructure file by file (git status
before git add, never a reflex git add .). The 4.1 clone-test doubles as a
leak detector: if a fresh clone trains without you supplying the data file, ask
why — either the README documents regeneration, or the csv is in git and you have
found this incident early.
Q: "A teammate pushed a repo containing customer data and a database password.
What are your first three moves?" Strong answer: rotate the credential first —
deleting files does not un-leak an append-only history — then reduce exposure
(private/down), then purge history and notify the right people, naming the DPDP
Act for the customer-data half. The differentiator interviewers listen for:
treating the data file and the secret as two different incident types, and the
.gitignore-first habit as the reason it never happens again.