I Committed AWS Credentials to GitHub (Accidentally) — Complete Case Study

I Committed AWS Credentials to GitHub (Accidentally) — Complete Case Study & Industry Analysis

I Committed AWS Credentials to GitHub (Accidentally) — Complete Case Study & Industry Analysis

I Committed AWS Credentials to GitHub

At 15:23 on a Tuesday afternoon, I made what every developer fears: I pushed AWS credentials to GitHub. Not in a private repository — in a public one. For 2 weeks, anyone on the internet could access those credentials. What happened next is a real-time case study in how quickly attackers move and why credential exposure is more critical than most developers realize.

This is the complete timeline, technical analysis, and industry research on what happens when AWS credentials are exposed on GitHub. This includes: real attack data, financial impact analysis, industry statistics on credential exposure, and a complete prevention framework used by security-first companies.

GitHub repository showing source code and commit history

Looking back, the GitHub part was the mistake that made everything possible. It is easy to think that a credential is safe because you are going to remove it later, but once it reaches a public repository you have to assume someone may already have copied it.

📑 Complete Analysis Navigation:
  1. How credentials end up on GitHub — root causes and prevalence
  2. My exact timeline — the 24-hour breach in real-time detail
  3. How attackers find and exploit exposed credentials
  4. Industry data — scale and cost of credential exposure
  5. Real case studies from other organizations
  6. Complete recovery and hardening process
  7. Prevention framework every developer must implement
Industry Context: GitHub's secret scanning detected 2.5 million secrets on the platform in 2025 alone. AWS credential exposure is the #1 category. Average time from exposure to exploitation: 47 minutes. Average financial impact: ₹60 lakh per incident. This is not a rare edge case — it is a systemic problem affecting thousands of companies monthly.

Part 1: How Credentials End Up on GitHub — Root Cause Analysis

Credential exposure doesn't happen randomly. It happens through predictable mistakes that are now well-documented in security research.

1

Root Cause: Incomplete .gitignore Files

The most common cause (72% of cases per GitHub research): developers create .gitignore files but don't include environment variable file patterns.

# Typical incomplete .gitignore: node_modules/ venv/ .DS_Store # Missing: .env .env.local *.pem *.key .aws/credentials

When developers then run `git add .` or `git add -A`, the .env file with AWS credentials gets included.

VS Code development environment

This is one of those mistakes that can happen very easily while developing. You add a credential temporarily to test something, get the code working, and then forget that the value is still sitting in the file. The dangerous part is that the code can look completely normal during development.

2

Root Cause: Temporary Credential Hardcoding for Debugging

Second most common (18% of cases): developer hardcodes credentials temporarily while debugging, forgets to remove them before committing.

# What developers do (temporarily): AWS_KEY = "AKIA3XQX123456789ABC" AWS_SECRET = "abcdef123456..." # Commit without removing # Now credentials are in git history forever
3

Root Cause: Accidental Public Repository

Developer creates private repository, develops locally, then makes it public for open-source or sharing — forgetting to check what's in git history.

4

Root Cause: No Code Review Process

Code is pushed directly without review. Someone who knew better might have caught it, but it went straight to production.

Part 2: My Exact Timeline — The 2-Week Breach in Detail

15:23 (Tuesday, May 21) I push commit to GitHub Created .env file with AWS credentials for local testing. Committed to public CloudSecScanner repository without reviewing .gitignore. File included: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION.
15:27 (4 minutes later) GitHub begins indexing commit GitHub's search indexing system automatically indexes public repositories. My commit is now in GitHub's search index. The .env file is publicly visible through GitHub's web interface.
15:45 (22 minutes later) Attacker bot discovers credentials Attacker runs automated secret scanning against GitHub (tools like GitRob, TruffleHog, gitrob scan public repos hourly). Bot finds my commit containing AWS_ACCESS_KEY_ID pattern. Bot stores the credential: AKIA3XQX...
15:47 (24 minutes later) Attacker verifies credential validity Attacker runs: aws sts get-caller-identity --access-key AKIA... --region us-east-1 Result confirms: valid credentials for AWS account 123456789, user: Amardeep-local-dev Attacker knows exactly whose account they've compromised and what region it's in.
15:50 (27 minutes later) Attacker enumerates account resources Attacker runs series of discovery commands: - aws ec2 describe-instances (finds 2 running t3.medium instances) - aws s3 ls (finds 3 S3 buckets) - aws rds describe-db-instances (finds production RDS instance) - aws iam list-users (finds 4 IAM users) - aws kms list-keys (finds encryption keys) Attacker now has complete picture of infrastructure.
15:55 (32 minutes later) Attacker launches cryptocurrency miner Attacker provisions 8 GPU-heavy p3.8xlarge EC2 instances. Each instance costs ₹200/hour. Attacker configures with monero mining software. Total daily cost: ₹38,400. Attacker's return: approximately ₹15,000/day in mined cryptocurrency. Profit margin: ₹8,000/day for attacker (40% ROI).
16:15 (1 hour 52 minutes later) AWS CloudWatch alerts trigger CloudWatch detected: unusual EC2 instance creation (8 instances created in 20 minutes), unusual instance type (p3.8xlarge not in normal pattern), unusual region activity. Alert sent to my email: "Unusual Activity Detected in Your AWS Account" I was not checking email actively at this time.
16:30 Attacker modifies infrastructure to hide tracks Attacker disables CloudTrail logging (if possible with permissions), clears recent history from CloudWatch, creates new IAM user "backup-admin" with full permissions to maintain access. This ensures that even if original credentials are revoked, attacker keeps access through backdoor account.
18:15 (about 3 hours later) I check AWS bill notification AWS sent automated bill alert: "Your estimated monthly bill has increased by ₹45,000 (from baseline ₹5,000 to ₹50,000)." I log into console. See the 8 mining instances running. Immediately understand the situation.
18:20 Immediate response: Revoke credentials Deactivate the exposed access key immediately. Create new access key for legitimate use. But attacker already has backdoor IAM user "backup-admin" which I don't know about yet.
18:25 Terminate mining instances Terminate all 8 p3.8xlarge instances. Check for other unusual instances. All instances terminated.
18:35 Delete .env from GitHub history Run: git filter-branch to rewrite history, remove .env file from all commits. Force push to remove from public history. However, GitHub keeps deleted content in their cache for some time, and attacker already has the credentials.
19:00 Enable MFA on AWS root account Set up TOTP MFA on root account (should have been done months ago). Also enable MFA on all IAM users.
20:00 AWS cost notification: attack continues New alert: ₹15,000 in additional charges for a completely different instance type (c5.4xlarge running for 1 hour). This was attacker using backdoor account "backup-admin" that I hadn't discovered yet.
20:30 Deep audit: discover backdoor account Run: aws iam list-users Discovered "backup-admin" user I never created. Check access keys: two access keys created for this user at 15:52 and 16:00. Attacker created this account as persistence mechanism. Delete "backup-admin" account and its access keys.
Next day (7:00 AM) AWS sends final billing summary Total attack cost: ₹45,000 in compute charges (mining instances 3 hours, backdoor instance 1 hour, plus data transfer). AWS later refunded 100% after investigation, but damage was done.
Terminal showing security and cloud commands

The part that surprised me most was how little manual work an attacker needs. Public repositories can be monitored automatically, so an exposed key doesn't have to sit there for days waiting for someone to notice it. That is why the first response should always be to revoke the credential rather than trying to clean up the repository first.

Part 3: How Attackers Find and Exploit Exposed Credentials

The Automated Attack Infrastructure

How do attackers find credentials so quickly? They run continuous automated scanning:

Tools attackers use:

  • TruffleHog: Open-source tool that scans git repositories for secrets. Can be configured to continuously scan GitHub's public data.
  • GitRob: Specifically searches GitHub for repository names with keywords like "backup", "prod", "secret", "key" and scans their content.
  • Custom AWS key scanners: Regex patterns that specifically look for AWS key IDs (start with AKIA, ASIA) in commit history.
  • Shodan: Searches for AWS credentials mentioned in public commits or code.

The timeline is critical: From detection to exploitation takes ~30 minutes. Most developers check email maybe once an hour. Most AWS alerts are checked once a day. This 30-minute window is all attackers need.

Part 4: Industry Data — Scale and Cost of Credential Exposure

Secrets exposed on GitHub (2025): 2.5M
AWS credentials specifically: 340K (14%)
Average time to exploitation: 47 min
Average financial impact per incident: ₹60 lakh
Companies affected (monthly): 8,000+

Part 5: Real Case Studies From Other Organizations

Case Study 1: Fintech Startup's ₹4.5 Crore Incident

The exposure: Junior developer committed credentials for production AWS account to a public GitHub repository while working on integration code.

What happened:

  1. Credentials exposed for 3 weeks (undetected)
  2. Attacker gained access to production RDS database containing 500,000 customer financial records
  3. Attacker extracted complete database and attempted to sell it on dark web
  4. Credential exposure was discovered when another security researcher reported it

Financial impact:

  • Data breach notification: ₹50 lakh
  • Regulatory fines: ₹1.5 crore
  • Credit monitoring services: ₹20 lakh
  • Incident response and forensics: ₹30 lakh
  • Lost customer trust (estimated): ₹2 crore+ in reduced valuations

What went wrong: No code review, no pre-commit hooks to detect secrets, no .gitignore, no GitHub secret scanning enabled.

Case Study 2: SaaS Company's Extended Breach

The exposure: AWS credentials committed to private repository, which was later made public during open-source initiative without audit.

Duration of exploitation: 6 months before discovery

Impact:

  • Attacker ran cryptocurrency mining 24/7 for entire 6-month period
  • Created multiple backdoor accounts throughout infrastructure
  • Planted malware in application deployment pipeline
  • By the time discovered, attacker had deep access across entire infrastructure

Cost: ₹2.8 crore in infrastructure damages, plus ₹1.5 crore in incident response.

AWS shared responsibility security model

The recovery process also reminded me that using AWS doesn't remove the security responsibility from the person deploying the application. AWS secures the underlying infrastructure, but things like IAM permissions, credentials, logging and application configuration still need to be handled correctly.

Part 6: Complete Recovery and Hardening Process

12-Step Recovery Checklist (What I Did After Discovery)

  • Step 1 (Immediately): Revoke all AWS access keys derived from exposed credentials. Create new keys.
  • Step 2 (Within 5 minutes): Enable MFA on root account and all IAM users (should already be enabled).
  • Step 3 (Within 10 minutes): List all IAM users and roles. Delete any you didn't create (backdoors).
  • Step 4 (Within 30 minutes): Review CloudTrail logs for past 24-48 hours. Document all attacker actions.
  • Step 5 (Within 1 hour): Terminate all instances not created by you (mining instances, attacker instances).
  • Step 6 (Within 1 hour): Rotate all database credentials. Check if databases were accessed.
  • Step 7 (Within 2 hours): Change S3 bucket policies to explicitly deny access except from your IP ranges.
  • Step 8 (Within 2 hours): Run AWS Config or Security Hub to identify other misconfigurations.
  • Step 9 (Within 4 hours): Remove credentials from git history permanently (git filter-branch, force push).
  • Step 10 (Within 24 hours): Implement pre-commit hooks to prevent future credential commits.
  • Step 11 (Within 48 hours): Enable GitHub secret scanning and AWS Secrets Manager for all applications.
  • Step 12 (Ongoing): Audit all services to ensure no other credentials are exposed.
GitHub repository security and source code

After going through the whole incident, the biggest lesson for me was that one security control is never enough. A good setup needs several layers: developers checking locally, GitHub scanning the repository, limited IAM permissions, proper secrets management and monitoring in AWS.

Part 7: Complete Prevention Framework — How Security-First Companies Do It

The 8-Layer Prevention Architecture

  • Layer 1 — Secrets Management: Never store credentials in code. Use AWS Secrets Manager, HashiCorp Vault, or environment variables. Rotate every 30 days.
  • Layer 2 — .gitignore Enforcement: Standard .gitignore template that explicitly ignores: .env*, *.key, *.pem, *.credentials, terraform.tfstate, .aws/credentials. Committed to every repository as mandatory.
  • Layer 3 — Pre-commit Hooks: Local git hooks (detect-secrets, talisman, gitleaks) run before every commit. Block any commit containing credential patterns.
  • Layer 4 — Code Review: Mandatory peer review before merge. Reviewers trained to spot secrets in code. Tools flag suspicious patterns automatically.
  • Layer 5 — GitHub Secret Scanning: Enable GitHub's native secret scanning. Receives notifications for any exposed AWS keys, API keys, or other patterns. Automatic revocation integration.
  • Layer 6 — Infrastructure as Code Scanning: Terraform, CloudFormation, and Kubernetes manifests scanned for hardcoded secrets before deployment. Tools like tfsec, checkov, and kube-bench run in CI/CD.
  • Layer 7 — AWS IAM Best Practices: Temporary credentials via STS AssumeRole, not long-lived keys. MFA required for all human access. Credentials have minimum necessary permissions (least privilege).
  • Layer 8 — Continuous Monitoring: CloudTrail logs all API access. GuardDuty detects unusual patterns. Alerts on access from unusual locations or anomalous API calls.

Part 8: Tools and Implementation Guide

# Step 1: Install pre-commit framework pip install pre-commit # Step 2: Create .pre-commit-config.yaml in repo root echo 'repos: - repo: https://github.com/Yelp/detect-secrets rev: v1.4.0 hooks: - id: detect-secrets args: [--baseline, .secrets.baseline] - repo: https://github.com/gitleaks/gitleaks rev: v8.18.0 hooks: - id: gitleaks' > .pre-commit-config.yaml # Step 3: Install git hooks pre-commit install # Step 4: Run against existing history pre-commit run --all-files # Now every git commit is scanned before it's allowed to proceed
What I would do differently now: I wouldn't put a long-lived AWS access key directly into a project just to test something. I would use temporary credentials, keep secrets outside the repository, and check the files being staged before every important commit. It takes a few extra minutes, but cleaning up an exposed credential can take much longer.

Credential Exposure FAQs

If I push credentials and immediately delete them, are they still exposed?
Yes. Deleting the file doesn't remove it from git history. It's still accessible through git log and git show commands. Additionally, GitHub's cache, Google's index, and attacker archives may have copies. You must: (1) Revoke the credentials immediately, (2) Use git filter-branch to remove from history, (3) Force push to GitHub. The credentials should be considered compromised and rotated regardless.
Why do GitHub secret scanning notifications take so long?
GitHub's scanning is not real-time. It runs periodically and depends on GitHub's own detection patterns. For critical applications, you should not rely on GitHub's scanning as your only defense. Use local pre-commit hooks (detect-secrets, gitleaks, talisman) which run before code even reaches GitHub.
Can I use the same AWS credentials for development and production?
Absolutely not. Separate credentials for every environment (dev, staging, prod). Each should have only the minimum permissions needed for that environment. This way, if dev credentials are compromised, production remains protected. Additionally, development should use temporary credentials via STS, not long-lived access keys.
What should I do first after discovering an AWS key on GitHub?
Revoke or deactivate the exposed credential first. Don't wait until you have cleaned the repository. Then review CloudTrail and IAM activity to determine whether the credential was used, check for unexpected resources or account changes, and rotate any related secrets.
Is removing the secret from the latest GitHub commit enough?
No. If the credential was committed previously, it may still exist in Git history, forks, caches or copies made by other systems. More importantly, the credential should already be considered compromised. Remove the secret from the repository history, but revoke and rotate it regardless.
How can developers prevent AWS credentials from reaching GitHub?
Keep secrets outside the source code, use appropriate secrets-management tools, configure a strong .gitignore, scan changes before committing, enable repository secret scanning and use least-privilege IAM permissions. Temporary credentials are preferable to long-lived access keys whenever the workflow supports them.

About the Author

Amardeep Maroli

AWS security practitioner who experienced credential exposure firsthand. Currently implementing security best practices at Inhok Technologies. Specializes in secrets management, CI/CD security, and incident response. Has helped 10+ organizations remediate credential exposure incidents.

Tags: AWS credentials, GitHub security, secrets management, credential exposure, incident response, CI/CD security, pre-commit hooks, credential rotation

Have you accidentally exposed credentials? Here's what to do immediately: revoke, rotate, scan git history, implement pre-commit hooks. Let me know if you need help with any step.

Post a Comment

0 Comments