Hardcoding API keys, database passwords, or cloud credentials directly into source code is one of the fastest ways to get breached. When those secrets end up in a Git repository — public or private — automated bots find them within minutes. For Indian dev teams, the consequences are immediate: compromised cloud accounts, unexpected bills reaching lakhs of rupees, data exfiltration, and regulatory exposure under the DPDP Act 2023. This guide covers what secrets are, where they leak, how attackers exploit them, and the exact steps to stop it — including a remediation playbook if you suspect a key is already out.
What Counts as a Secret
A "secret" is any credential that grants access to a system, service, or dataset. The category is broader than most developers realize.
| Secret Type | Examples | Risk if Leaked |
|---|---|---|
| Cloud provider keys | AWS Access Key + Secret, GCP Service Account JSON, Azure Client Secret | Full account takeover, resource spin-up, data access |
| Third-party API keys | Razorpay, Stripe, Twilio, SendGrid, OpenAI | Fraudulent charges, spam, data scraping |
| Database credentials | Connection strings with username + password | Direct data exfiltration |
| JWT signing secrets | JWT_SECRET, SESSION_SECRET | Forge valid auth tokens for any user |
| SSH private keys | id_rsa, deploy keys | Server access, repository push access |
| Webhook secrets | Stripe webhook signing secret | Replay attacks, fake payment events |
| CI/CD tokens | GitHub PATs, GitLab tokens, Docker Hub passwords | Supply chain compromise |
| Encryption keys | S3 SSE keys, AES keys stored as env strings | Decrypt protected data at rest |
.env file, commits it "just for testing," and the history lives in the repository forever.
git log -p exposes it. A git rebase or BFG Repo Cleaner run is required to actually purge it, and that only works before someone has cloned the repository.Where Secrets Actually Leak
Understanding the leak surface is the first step to blocking it.
graph TD
A[Developer writes code] --> B[Hardcodes secret in source file or .env]
B --> C{Committed to Git?}
C -- Yes --> D[Pushed to GitHub/GitLab]
C -- No --> E[Still in local file system risk]
D --> F{Repo public?}
F -- Yes --> G[Automated bot scans within minutes]
F -- No --> H[Internal team has access - insider risk]
G --> I[Secret indexed by search engines or GitGuardian scanners]
H --> J[Secret visible in CI/CD logs or PR diffs]
I --> K[Attacker extracts key]
J --> K
K --> L[Credential abuse - cloud bill shock, data breach, supply chain attack]
E --> M[Leaked via client bundle or error log]
M --> K
B --> N[Pre-commit hook blocks commit]
N:::success --> O[Secret never enters Git history]
D --> P[CI pipeline secret scanner]
P:::success --> Q[Alert raised, pipeline fails, key rotated before merge]
classDef success fill:#1e3d2f,stroke:#10B981,color:#e2e8f0
classDef danger fill:#5f1e1e,stroke:#EF4444,color:#e2e8f0
A:::normal
B:::danger
K:::danger
L:::danger
classDef normal fill:#1e3a5f,stroke:#3B82F6,color:#e2e8f0The four primary leak surfaces are:
1. Source code and Git history. The most common vector. A developer adds API_KEY=sk-live-... to a config file, commits, pushes. Even after the key is removed in the next commit, the history preserves it. GitGuardian's 2024 State of Secrets Sprawl report found that exposed secrets in public repositories routinely go undetected for weeks — more than enough time for significant abuse before revocation.
2. CI/CD pipeline logs. Build logs frequently echo environment variables during test runs or debug steps. If a command like printenv or a failing test prints context to stdout, that output is captured in the pipeline log and visible to anyone with repository access. This includes build artifacts stored in S3 or blob storage if log archiving is enabled.
3. Client-side bundles. Next.js, React, and Vue applications bundle any variable prefixed with NEXT_PUBLIC_, REACT_APP_, or similar into the JavaScript downloaded by every browser. Developers sometimes accidentally prefix backend secrets to make them "available everywhere" — then they are available everywhere, including to anyone who opens DevTools.
4. Container images. Secrets baked into a Docker image via RUN export API_KEY=... or ENV API_KEY=... in a Dockerfile are embedded in the image layers. Even if overridden at runtime, the layer cache and any pushed registry image retains the value. Public Docker Hub images have repeatedly been found with hardcoded cloud credentials.
pie title Where Indian Dev Teams Leak Secrets
"Git repos and history" : 42
"CI/CD logs and artifacts" : 23
"Client-side JS bundles" : 18
"Container images" : 11
"Error logs and monitoring tools" : 6The Fix: Secrets Management Architecture
The goal is a zero-secrets-in-code posture. This requires three layers working together.
Layer 1 — Use a Secrets Manager
A secrets manager stores credentials encrypted at rest, provides versioned access, and logs every retrieval. Applications fetch secrets at runtime rather than reading them from files.
AWS Secrets Manager is the right default for teams already on AWS. Store your RDS password, third-party API keys, and JWT secrets here. Access is controlled by IAM roles — the application's EC2 instance or Lambda function has a role that can read only the specific secrets it needs. No hard-coded credentials in application code or environment files.
HashiCorp Vault is the open-source alternative, self-hosted or available as HCP Vault. It supports dynamic secrets — for example, generating a temporary PostgreSQL username and password that expire in one hour. This eliminates the concept of a shared, long-lived database password entirely.
Cloud-native options for teams on GCP or Azure include Google Secret Manager and Azure Key Vault. The pattern is identical: secrets live in the manager, applications authenticate via managed identity, secrets are fetched at startup or on demand.
The key shift: your application reads os.environ["DB_PASSWORD"] which the deployment platform injects at runtime from the secrets manager. The value is never stored in a file that gets committed.
Layer 2 — Least Privilege on Every Secret
A leaked secret is far less damaging if it carries minimal permissions. Apply the principle of least privilege to every credential:
- The API key your payment service uses should be read-only for webhooks, not a full admin key.
- The database user your web app connects with should have
SELECT, INSERT, UPDATEon specific tables — notCREATE, DROP, ALLon the entire database. - AWS IAM roles for your application should be scoped to the exact S3 bucket and exact actions the application actually performs.
Layer 3 — Rotation as a Default, Not an Exception
Secrets should have a defined TTL and be rotated on a schedule, not only after an incident. AWS Secrets Manager supports automated rotation via Lambda functions. For API keys that do not support server-side rotation, build a quarterly rotation task into your engineering calendar and treat it with the same urgency as a dependency update.
Know your vulnerabilities before attackers do
Run a free VAPT scan — takes 5 minutes, no signup required.
Book Your Free ScanBlocking Leaks Before They Happen
Prevention is cheaper than remediation. Two controls stop secrets from ever reaching a repository.
Pre-commit Hooks with detect-secrets or gitleaks
Gitleaks is an open-source tool that scans staged files for high-entropy strings and known secret patterns (AWS keys, GitHub tokens, Stripe keys, and hundreds more). Install it as a pre-commit hook and it blocks the commit if a secret is detected.
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.4
hooks:
- id: gitleaksThis runs locally on every git commit. The secret never reaches the remote. Takes under five minutes to configure for an entire team.
Secret Scanning in CI/CD
Pre-commit hooks protect against accidental commits, but they can be bypassed with --no-verify. A second layer of scanning in your CI pipeline provides a backstop. GitHub Advanced Security includes secret scanning as a native feature. GitLab Ultimate has it built in. For self-hosted runners, run gitleaks detect as an early pipeline job that fails the build if secrets are found.
This catches anything that slipped past the pre-commit hook and ensures no secret reaches a deployed branch.
| Control | When it runs | Who it protects against |
|---|---|---|
| Pre-commit hook | Before git commit | Accidental inclusion |
| CI/CD secret scanner | On push or PR open | Bypassed hooks, forgotten files |
| Repository secret scanning | Continuously on all branches | Historical exposure, forks |
| Runtime secrets manager | At application startup | Config file exposure |
| Least-privilege IAM | Always | Blast radius limitation |
| Rotation schedule | Quarterly or on trigger | Long-term exposure window |
Remediation Playbook: What to Do If a Key Is Already Out
Assume any key that has touched a public repository or a shared CI log is compromised. The timeline matters: speed of revocation directly limits the damage.
Step 1 — Revoke immediately, then investigate. Do not spend time confirming whether the key was actually used before revoking. Revoke first. For AWS, go to IAM → Access Keys → Deactivate. For third-party APIs, go to the provider's dashboard and delete the key. The cost of a false alarm is zero. The cost of waiting is potentially everything.
Step 2 — Audit access logs. After revocation, check CloudTrail (AWS), GCP Audit Logs, or the equivalent for any API calls made with the compromised key. Identify the time window, the actions taken, and any data accessed or exfiltrated. Preserve these logs — they are your evidence trail.
Step 3 — Purge from Git history. Use BFG Repo Cleaner or git filter-repo to rewrite history and remove the secret. Force-push and require all team members to re-clone. Note: if the repository was public at any point, assume the secret has already been indexed. History purge protects against future casual discovery, not against a determined attacker who already scraped it.
Step 4 — Issue a replacement secret and store it in your secrets manager. Never reuse the same value.
Step 5 — Review blast radius. What did the compromised credential have access to? Check for unauthorized resource creation (EC2 instances, S3 buckets, IAM users), data exports, sent emails or SMS, or charges to payment accounts. File an incident report.
Step 6 — Notify if required. If the compromised credentials exposed personal data, the DPDP Act 2023 imposes notification obligations. Organizations handling personal data of Indian citizens must report breaches to the Data Protection Board. For detailed obligations, see the DPDP compliance guide.
Tooling Reference for Indian Dev Teams
Teams working within Indian cloud regions (AWS ap-south-1, GCP asia-south1) should also evaluate:
- AWS Parameter Store — free tier for standard parameters; suitable for non-sensitive config and low-volume secret retrieval.
- Doppler — SaaS secrets manager with a generous free tier; syncs to Vercel, Render, Railway, GitHub Actions. Good starting point for early-stage teams before committing to cloud-native tooling.
- 1Password Secrets Automation — for teams already on 1Password for team credentials; bridges personal vault practice with CI/CD injection.
For more on application security practices, see the Bachao.AI blog.
External references:
- GitGuardian State of Secrets Sprawl 2024: https://www.gitguardian.com/state-of-secrets-sprawl
- OWASP Top 10 A02:2021 — Cryptographic Failures (which covers secrets in code): https://owasp.org/Top10/A02_2021-Cryptographic_Failures/
- NIST SP 800-57 Key Management Guidelines: https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final
Frequently Asked Questions
What is the fastest way to check if our repository already has secrets in it?
gitleaks detect --source . --log-opts="--all" against your local clone. It scans the full Git history, not just the current working tree. For GitHub repositories, enable GitHub Secret Scanning under Settings → Security — it runs retroactively and alerts on known secret patterns across all branches and history.Is a private GitHub repository safe for storing secrets?
What is the difference between environment variables and a secrets manager?
.env file committed to a repository, that is the problem. A secrets manager is the secure source: your deployment platform fetches the value from the manager at runtime and injects it as an environment variable. The code only ever sees an environment variable; the sensitive value never touches a file.How often should we rotate API keys?
Does DPDP Act 2023 apply to secrets management?
Our team uses .env files checked into a private repo. Is that a real risk?
.env files belong in .gitignore, always. Use a secrets manager or a platform like Doppler to sync values to developer machines without committing them.