🚨 DỪNG LẠI. Làm 3 việc này NGAY BÂY GIỜ:
- Revoke token. npm:
npm token revoke <token-id>/ GitHub: github.com/settings/tokens > Delete / AWS:aws iam deactivate-access-key --access-key-id <key>- Coi như mọi thứ token truy cập được đã bị compromise.
- CHƯA xóa log, force-push, hay post công khai.
Xong rồi? Đọc tiếp.
TL;DR — Attacker thu thập credential bị lộ từ public repo trong 5 phút. Bạn có 1 giờ trước khi thiệt hại tăng lên. Runbook này hướng dẫn revocation, scoping blast radius, rotate downstream, forensics, và hardening, với command chính xác cho npm, GitHub, Vercel, và AWS. Nhảy đến Phút 0-5 →
📊 Khoảng cách chết người:
- Bot scan GitHub tìm key bị lộ trong 5 phút
- Team trung bình mất 94 ngày để phát hiện secret bị lộ
- Breach liên quan credential mất 292 ngày để xử lý
- 53% tổng số data breach liên quan đến credential bị đánh cắp
Bạn vừa nhận notification từ GitHub rằng npm token bị tìm thấy trong public commit. Hoặc chạy git log thấy AWS key nằm plaintext. Hoặc GitHub Secret Scanning vừa gửi email.
Nhịp tim tăng. Bình thường.
Những gì bạn làm trong 60 phút tới quyết định đây là phiền phức 1 giờ hay sự cố 1 tuần. Tôi đã trải qua chuyện này hai lần. Lần đầu tôi hoảng và force-push. Tệ hơn. Lần hai tôi theo runbook này. Xử lý trong 45 phút.
Đây là runbook.
Phút 0-5: Revoke token
Revoke token bị lộ ngay lập tức. Chưa cần scope damage. Chưa cần điều tra nguyên nhân. Chưa cần clean git history. Revoke. Mỗi phút token còn sống, scanner tự động có thể dùng nó. Threat actor thu thập credential từ public repo trong 5 phút (DevActivity/GitHub, 2026).
Một command mỗi platform:
npm
# Liệt kê token để tìm cái bị lộnpm token list
# Revokenpm token revoke <token-id>GitHub PAT
# Qua CLI (nếu có gh)gh auth token # xem token hiện tại# Rồi vào github.com/settings/tokens > Delete token bị lộ
# Hoặc qua API (fine-grained token)gh api -X DELETE /user/tokens/<token-id>GitHub OAuth và App credential dùng Credential Revocation API (GA từ tháng 3/2026).
AWS
# Deactivate trước, rồi deleteaws iam deactivate-access-key --access-key-id AKIA...aws iam delete-access-key --access-key-id AKIA...Vercel
Project Settings > Environment Variables > click biến > Regenerate. Hoặc qua CLI:
vercel env rm <VAR_NAME> productionvercel env add <VAR_NAME> productionGCP
gcloud iam service-accounts keys delete <key-id> \ --iam-account=<service-account-email>Nếu bạn đọc bài này lúc 2 giờ sáng vì GitHub vừa gửi email, bắt đầu từ đây. Copy command. Chạy. Rồi thở.
Key insight: Threat actor thu thập IAM credential từ public repo trong 5 phút, trong khi team trung bình mất 94 ngày để phát hiện secret bị lộ (Verizon DBIR, 2025). Khoảng cách giữa 5 phút và 94 ngày là nơi breach xảy ra. Revoke ở Phút 0 đóng khoảng cách đó.
Phút 5-15: Scope blast radius
Token đã bị revoke. Giờ xác định nó có thể truy cập gì. Blast radius phụ thuộc ba thứ: loại token, scope/permission, và thời gian bị lộ. Classic GitHub PAT có scope repo và không hết hạn là worst-case: full read/write mọi repo, kể cả private.
| Loại token | Blast radius | Worst-case access |
|---|---|---|
| npm publish token | Package của bạn | Attacker publish version độc |
| npm read-only token | Package metadata | Rủi ro thấp, vẫn nên rotate |
| GitHub classic PAT (repo) | Mọi repo, kể cả private | Source code, secret trong code, CI config |
| GitHub fine-grained PAT | Repo được chọn | Giới hạn trong repo đã chọn |
| AWS IAM access key | Phụ thuộc IAM policy | Có thể là toàn bộ AWS account |
| Vercel env var | Secret một project | API key, DB credential, OAuth token |
Cách kiểm tra access
GitHub: Check security log trong exposure window:
# Tài khoản cá nhân# Settings > Security log > filter theo date range
# Org account (nếu có admin)gh api "/orgs/{org}/audit-log?phrase=action:oauth_authorization.create"AWS CloudTrail: Query access event cho key bị lộ:
aws cloudtrail lookup-events \ --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=AKIA... \ --start-time 2026-04-28T00:00:00Z \ --end-time 2026-04-30T23:59:59ZExposure window: Token bị commit khi nào? (git log --all --oneline | head -20 để tìm commit). Revoke khi nào? Khoảng cách đó là compromise window. Mọi thứ bị truy cập trong window đó đều có thể bị compromise.
Key insight: Stolen credential chiếm 22% tổng số security incident và mất trung bình 292 ngày để xử lý, là loại breach tốn thời gian nhất (IBM/Deepstrike, 2025). Scope blast radius ở Phút 5-15 ngăn cái đuôi 292 ngày.
Phút 15-30: Rotate mọi thứ downstream
Token bị lộ đã chết. Nhưng nếu nó truy cập được secret khác, những secret đó cũng bị compromise. Đây là cascade biến sự cố 1 giờ thành sự cố 1 tuần. Rotate mọi credential mà token bị lộ có thể chạm tới.
Checklist cascade
CI/CD secret (kiểm tra trước):
# GitHub Actions secrets - regenerate qua web UI# Settings > Secrets and variables > Actions > Update từng secret
# Vercel env varsvercel env ls production# Regenerate bất cứ cái gì token bị lộ có thể đọcnpm publish token: Nếu credential bị lộ đọc được CI environment (ví dụ GitHub PAT có repo access đến project lưu npm token trong GitHub Actions secrets), publish token đã bị compromise.
npm token revoke <publish-token-id>npm token create --cidr=<your-ci-ip-range>Database credential: Nếu env var chứa DB connection string, rotate ở cấp database. Không chỉ update env var.
OAuth token: Nếu token bị lộ truy cập được Vercel env var chứa Google hoặc Slack OAuth token, coi như compromised. Chạy OAuth permissions audit từ bài Level 3.
SSH key: Nếu environment bị compromise có ~/.ssh/ accessible:
# Tạo key mớissh-keygen -t ed25519 -C "your_email@example.com"
# Thêm vào GitHubgh ssh-key add ~/.ssh/id_ed25519.pub --title "rotated-$(date +%Y%m%d)"Dev solo: tối đa 5-10 secret. Team lead: nhân với số service CI pipeline chạm tới. Mở shared doc và check off từng cái.
Key insight: 53% tổng số data breach liên quan stolen credential, chi phí trung bình $4.44 triệu mỗi vụ (IBM Cost of a Data Breach / Deepstrike, 2025). Cascade từ một token bị lộ đến downstream credential là thứ đẩy chi phí lên. Cắt cascade ở Phút 15 là action có ROI cao nhất trong runbook.
Phút 30-45: Export log trước khi hết hạn
Export audit log NGAY, trước khi platform xóa. GitHub giữ security event 90 ngày. AWS CloudTrail giữ 90 ngày mặc định. npm audit log hạn chế. Nếu không export bây giờ, bạn mất bằng chứng forensic cần cho post-mortem.
Checklist export log
| Platform | Export gì | Cách | Retention |
|---|---|---|---|
| GitHub | Security log | Settings > Security log > Export | 90 ngày |
| AWS | CloudTrail event | aws cloudtrail lookup-events (xem trên) | 90 ngày |
| Vercel | Deployment log | Dashboard > Deployments > filter theo ngày | 30 ngày |
| npm | Token last-used | npmjs.com/settings/~/tokens | Hạn chế |
Tìm gì trong log:
- Access từ IP hoặc location lạ
- Token mới được tạo trong exposure window
- Package được publish (cho npm token)
- Repo clone hoặc API access ngoài pattern bình thường
- SSH key mới được thêm vào account
Nhận tip bảo mật hàng tuần cho AI coder. Hooks, credential hygiene, và phân tích breach thực tế. Một email mỗi tuần. Đăng ký AI Developer Weekly →
Key insight: Team trung bình mất 94 ngày để phát hiện secret bị lộ (Verizon DBIR, 2025). Export log ở Phút 30-45 đảm bảo bạn có bằng chứng forensic ngay cả khi exposure xảy ra từ tuần trước. Platform xóa log theo lịch của họ, không phải của bạn.
Phút 45-60: Hardening cho lần sau
Lửa đã tắt. Giờ ngăn lần tiếp theo. Ba thay đổi mất 15 phút loại bỏ vector credential leak phổ biến nhất. Riêng GitHub Push Protection đã chặn 39 loại token trước khi vào repo (GitHub Docs, 2026), và fine-grained token với expiration 90 ngày đóng cửa sổ classic PAT đã gây ra vụ axios breach.
1. Bật GitHub Push Protection (miễn phí cho public repo):
# Kiểm tra secret scanning đã bật chưagh api /repos/{owner}/{repo} --jq '.security_and_analysis'Push Protection chặn 39 loại token trước khi vào repo. Không bắt custom secret, nhưng bắt npm, AWS, GCP, Stripe, và hầu hết provider lớn (GitHub Docs, 2026).
2. Chuyển sang fine-grained GitHub token với expiration 90 ngày. Classic PAT không hết hạn mặc định. Fine-grained token expire, scope cho repo cụ thể, và hỗ trợ IP restriction.
3. Xây defense nhiều lớp với supply chain series:
| Level | Defense | Bài viết |
|---|---|---|
| 1 | .npmrc hardening | npm Defense 30 Giây |
| 2 | PreToolUse hooks | Chặn npm Attack với Hooks |
| 3 | OAuth audit + scope hygiene | OAuth Supply Chain Defense |
| 4 | Incident response (bài này) | Bạn đang đây |
5 hành động hoảng loạn khiến token leak tệ hơn
Điều tệ nhất sau credential leak là hoảng loạn và làm tệ hơn. Breach liên quan credential đã mất trung bình 292 ngày để xử lý (IBM/Deepstrike, 2025). 5 anti-pattern sau đây thêm hàng tuần lên trên đó bằng cách phá hủy bằng chứng, báo động attacker, hoặc delay thông báo team.
| Anti-pattern | Tại sao tệ hơn | Làm gì thay thế |
|---|---|---|
| Force-push để xóa commit | Token đã trong GitHub event log và bot cache. Force-push phá audit trail. | Revoke token trước. Clean history sau bằng git filter-repo. |
| Xóa repo | Commit đã bị bot scrape. Giờ mất code VÀ log. | Revoke, export log, rồi clean history. |
| Rotate credential trước khi export log | Mất audit trail cho biết gì đã bị truy cập trong exposure window. | Export log trước, rotate sau (trừ khi token còn live thì revoke ngay). |
| Chờ mới thông báo team | Mỗi giờ delay là mỗi giờ team không bảo vệ được downstream system. | Thông báo trong 15 phút sau khi xác nhận leak. |
| Post công khai trước khi revoke | Công bố leak là tín hiệu cho attacker move nhanh hơn. | Revoke trước. Disclose sau khi containment xong. |
Key insight: Force-push để xóa committed secret phá
git reflogaudit trail và không xóa secret khỏi GitHub event log, cached fork, hay database bot đã scrape. Revocation luôn phải trước history cleanup (GitHub Docs).
Kế hoạch 7 ngày sau incident
Runbook 60 phút cầm máu. Kế hoạch 7 ngày ngừa nhiễm trùng. Với 2 tỷ credential bị lộ được tổng hợp từ dark web chỉ trong 2025 (Deepstrike, 2025), câu hỏi không phải bạn có gặp incident nữa không, mà là bạn có chuẩn bị sẵn không.
- Ngày 1-2: Monitor audit log tìm access trong exposure window bạn bỏ sót. Đặt alert cho hoạt động bất thường trên account bị ảnh hưởng.
- Ngày 3: Document incident. Gì bị lộ, exposure window, gì đã rotate, gì đã bị truy cập. Giữ doc này cho reference sau.
- Ngày 4-5: Review secrets management. Đã dùng env var thay hardcoded key chưa?
.envcó trong.gitignorechưa? CI secret scope minimum necessary chưa? - Ngày 6-7: Mini-retro với team (hoặc với chính mình). Không blame. Process nào fail? Automation nào sẽ bắt được? PreToolUse hook có chặn được commit không?
Khi nào nên gọi chuyên gia?
Nếu credential bị lộ có quyền truy cập customer data, hệ thống tài chính, hoặc production database chứa PII, dừng guide này và liên hệ incident response firm chuyên nghiệp. Yêu cầu pháp lý thay đổi hoàn toàn playbook.
Ngưỡng escalation:
- Customer data có thể bị truy cập: nghĩa vụ pháp lý phải disclose ở nhiều quốc gia (GDPR: 72 giờ)
- Production database credential bị lộ: assume data exfiltration cho đến khi chứng minh ngược lại
- Nhiều token bị lộ cùng lúc: có thể là system compromise rộng hơn, không chỉ một credential leak
Thử ngay:
- Chạy
npm token listvà check token nào không có expiration hoặc scope quá rộng- Vào
github.com/settings/tokensvà thay classic PAT bằng fine-grained token (expiry 90 ngày, scope repo cụ thể)- Bật Push Protection: Settings > Code security > Secret scanning > Push protection
- Bookmark trang này. Bạn sẽ cần nó lúc 2 giờ sáng khi notification đến.
Muốn ngăn credential leak tiếp theo? Bắt đầu với .npmrc defense 30 giây, rồi build up. Tham gia AI Developer Weekly → cho tip bảo mật hàng tuần.
FAQ
Bot scan GitHub tìm key bị lộ nhanh cỡ nào?
Trong vòng 5 phút. Scanner tự động liên tục monitor public commit trên GitHub. Researcher đã document credential harvesting trong vài phút sau exposure. Khi bạn phát hiện leak, token có thể đã bị copy. Đây là lý do Phút 0 là revocation, không phải investigation.
Có nên xóa commit chứa key bị lộ không?
Chưa vội. Revoke token trước. Export log thứ hai. Rồi clean git history bằng git filter-repo hoặc BFG Repo-Cleaner. Force-push trước khi revoke phá audit trail mà không xóa exposure, vì commit data đã trong GitHub event log và có thể đã bị cache bởi third-party service.
GitHub Secret Scanning có bắt được tất cả token không?
Không. GitHub hỗ trợ 39 loại token với push protection mặc định, bao gồm AWS, npm, Stripe, và Google Cloud. Nhưng custom API key, database password, self-hosted service token, và internal secret không được detect. Secret scanning là lưới an toàn, không phải bảo đảm. Kết hợp với .gitignore discipline và pre-commit hook.
Rotate token bị lộ là đủ, hay phải rotate hết?
Rotate tất cả những gì token bị lộ có thể truy cập. Nếu npm token đọc được CI secret, secret đó cũng bị compromise. Nếu GitHub PAT có scope repo, mọi secret trong repo đó bị lộ. Nếu Vercel env var chứa database credential, rotate ở cấp database. Theo cascade mô tả trong phần Phút 15-30.
Đọc tiếp
- npm Defense 30 Giây Cho Mọi Vibe Coder — Level 1 của supply chain defense series. Bốn dòng trong
~/.npmrcngăn vector tấn công phổ biến nhất. Bắt đầu đây cho prevention sau khi đã xử lý incident. - OAuth Supply Chain Attack: Khi AI Tool Trở Thành Vector Tấn Công — Level 3. Nếu credential bị lộ truy cập được OAuth token (ví dụ qua Vercel env var), chạy audit 5 phút này để check exposure.
- 3 Lớp Defense Trong Claude Code. Nó Vẫn Xóa File. — Bài học áp dụng ở đây: test threat model thực tế, không phải tưởng tượng. Incident response plan cần test trước khi có incident.