mmo.vn
Lập trình AI15 phút đọc

Lộ API key, mật khẩu qua AI coding agent: vụ 2.539 bí mật trên GitHub và cách cấu hình Claude Code, Cursor, Copilot an toàn

Nghiên cứu của Apiiro tìm thấy hàng nghìn khoá API, mật khẩu cơ sở dữ liệu và thông tin đăng nhập SSH bị lộ qua tệp cấu hình quyền của AI coding agent trên GitHub. Bài viết giải thích cơ chế, cách kiểm tra repo của bạn và bộ cấu hình an toàn cho Claude Code, Cursor, Copilot.

Thumbnail cảnh báo lộ API key qua AI coding agent với tệp settings.local.json

Trong bài này

  • 15 phút đọc
  • 11 phần
  • 13 mẫu sao chép được
  • 2 bảng tra cứu
Mục lục
  1. Tóm tắt nhanh
  2. Chuyện gì đã xảy ra
  3. Cơ chế lộ bí mật: từ "đừng hỏi lại" đến GitHub
  4. Bối cảnh: lập trình viên dùng AI đang là mục tiêu
  5. Kiểm tra repo của bạn trong 10 phút
  6. Nếu đã lộ: đổi khoá trước, dọn lịch sử sau
  7. Bộ cấu hình an toàn hơn
  8. Danh sách kiểm tra theo giai đoạn
  9. Câu hỏi thường gặp
  10. Kết luận
  11. Nguồn tham khảo

Cách bài viết này được thực hiện: bài tổng hợp từ báo cáo nghiên cứu của Apiiro được Cybernews đưa tin, các bản tổng hợp an ninh mạng tuần 2 đến 8/11/2026 và tài liệu công khai của các công cụ, kiểm tra ngày 10/11/2026. Các đoạn lệnh và cấu hình trong bài là ví dụ để bạn điều chỉnh theo dự án, hãy thử trên một repo thử nghiệm trước. Bài không có link affiliate.

Nếu bạn đang dùng Claude Code, Cursor, GitHub Copilot hay bất kỳ AI coding agent nào, có lẽ bạn đã quen với hộp thoại hỏi quyền: agent muốn chạy một lệnh, bạn bấm đồng ý. Sau vài chục lần, phần lớn chúng ta chọn “đồng ý và đừng hỏi lại” cho đỡ phiền. Tiện thật. Nhưng một nghiên cứu công bố đầu tháng 11/2026 cho thấy chính lựa chọn đó đã khiến hàng nghìn mật khẩu, khoá API thật bị đẩy lên GitHub công khai.

Bài này đi qua chuyện gì đã xảy ra, vì sao các công cụ quét bí mật quen thuộc bỏ sót, cách kiểm tra repo của bạn trong 10 phút, và một bộ cấu hình an toàn hơn cho các agent phổ biến. Mục tiêu không phải để bạn ngừng dùng AI coding agent, mà để dùng chúng mà không phải trả giá bằng một hoá đơn đám mây bất ngờ hay một cơ sở dữ liệu bị xoá.

Tóm tắt nhanh#

MụcNội dung
Nghiên cứuApiiro, công ty bảo mật ứng dụng, công bố đầu tháng 11/2026
Quy mô quét104.185 tệp quyền của agent trong 103.617 repo công khai trên GitHub
Bí mật nhạy cảm tìm thấy2.539 bí mật trong 1.994 repo; 1.105 repo chứa bí mật thật còn dùng được
Loại bí mậtToken dịch vụ (nhiều nhất), mật khẩu cơ sở dữ liệu, khoá API mô hình AI, hàng chục thông tin đăng nhập root SSH, khoá đám mây quyền quản trị
Tệp chính.claude/settings.local.json của Claude Code, ngoài ra có tệp tương tự của Cursor, Copilot, Gemini
Nguyên nhânLệnh được duyệt “đừng hỏi lại” được lưu nguyên văn, kể cả bí mật gõ trong lệnh
Việc cần làm ngayĐổi (rotate) mọi bí mật bị lộ, loại thư mục agent khỏi git, không gõ bí mật trực tiếp vào lệnh

Chuyện gì đã xảy ra#

Apiiro quét các repo công khai trên GitHub để tìm tệp lưu quyền của AI coding agent. Kết quả: hơn 104 nghìn tệp như vậy đã được commit công khai. Trong đó, nhóm nghiên cứu tìm thấy 2.539 bí mật nhạy cảm trong 1.994 repo, và 1.105 repo chứa bí mật thật, tức khoá hoặc mật khẩu đang hoạt động chứ không phải giá trị mẫu.

Một số ví dụ được nêu trong báo cáo cho thấy mức độ nghiêm trọng: khoá đám mây quyền quản trị của một nhà cung cấp cơ sở dữ liệu, mật khẩu Postgres trên Azure của môi trường production, token production của Square (dịch vụ thanh toán), mật khẩu chủ sở hữu của một cơ sở dữ liệu hồ sơ y tế, và hàng chục thông tin đăng nhập root SSH.

Phần lớn repo bị ảnh hưởng thuộc về lập trình viên cá nhân, nhưng có 63 tổ chức trong danh sách, từ startup, agency phần mềm đến các nhà cung cấp đã có tên tuổi. Trong 539 trên 1.105 repo có bí mật thật, chính Claude là đồng tác giả (co-author) của commit thay đổi tệp đó.

Cùng tuần, Microsoft cảnh báo kẻ tấn công đang dùng AI dạng tác tử để quét thông tin đăng nhập bị lộ trên GitHub rồi đi tiếp vào môi trường đám mây. Nghĩa là khoảng cách giữa “lỡ đẩy khoá lên GitHub” và “bị khai thác” ngày càng ngắn.

Cơ chế lộ bí mật: từ “đừng hỏi lại” đến GitHub#

Lấy Claude Code làm ví dụ, vì đây là công cụ được báo cáo tập trung phân tích. Khi agent đề xuất chạy một lệnh shell, bạn có ba lựa chọn: từ chối, đồng ý lần này, hoặc đồng ý và đừng hỏi lại với lệnh tương tự. Lựa chọn thứ ba tạo một “allow rule” và lưu vào tệp .claude/settings.local.json trong thư mục dự án.

Vấn đề là quy tắc được lưu nguyên văn lệnh. Nếu lệnh bạn duyệt có dạng:

psql "postgresql://admin:MatKhauThat123@db.example.com:5432/prod" -c "select count(*) from orders"

thì nguyên chuỗi kết nối kèm mật khẩu sẽ nằm trong tệp cấu hình. Tương tự với curl -H "Authorization: Bearer sk-...", sshpass -p ..., mysql -p... hay bất kỳ lệnh nào có bí mật gõ thẳng vào.

“Nhưng Claude Code đã tự gitignore tệp đó rồi mà?”

Đúng, và đây là lý do nhiều người chủ quan. Theo phản hồi của Boris Cherny, người phụ trách Claude Code tại Anthropic, công cụ tự động thêm tệp này vào gitignore, nên các tệp bị lộ đã được thêm thủ công. Tuy nhiên báo cáo chỉ ra cơ chế bảo vệ này có những lỗ hổng thực tế:

  • Repo được clone về: quy tắc gitignore toàn cục không áp dụng giống nhau cho mọi repo bạn clone.
  • Thư mục trở thành repo sau: bạn làm việc với agent trong một thư mục thường, sau đó mới git init. Lúc đó tệp đã nằm sẵn và dễ bị git add . cuốn vào.
  • Tệp đã commit trước đó: một khi tệp đã vào lịch sử git, thêm vào gitignore sau không gỡ được nó.
  • Thói quen git add -A: đặc biệt khi chính agent được nhờ “commit hết thay đổi”.

Vì sao gitleaks, TruffleHog bỏ sót

Các công cụ quét bí mật hoạt động tốt nhất với khoá có định dạng nhận dạng được, ví dụ khoá bắt đầu bằng tiền tố đặc trưng của từng nhà cung cấp. Mật khẩu do người tự đặt, gõ thẳng trong chuỗi lệnh, thường không có mẫu nào để nhận diện. Báo cáo cho biết đây chính là loại bí mật mà công cụ quét hay bỏ sót.

Không chỉ Claude Code

Báo cáo ghi nhận tệp tương tự trên Hugging Face, GitLab, và với các công cụ khác: thiết lập tự động phê duyệt lệnh (auto-approve) của Copilot trong VS Code, bản ghi hội thoại với agent, tệp “bộ nhớ” của agent đều từng chứa bí mật. Các thư mục cần chú ý gồm .claude/, .cursor/, .gemini/, .specstory/ và các tệp ghi nhớ như CLAUDE.md hay AGENTS.md nếu bạn từng dán thông tin nhạy cảm vào đó.

Bối cảnh: lập trình viên dùng AI đang là mục tiêu#

Vụ lộ bí mật không đứng riêng. Trong cùng hai tuần đầu tháng 11/2026:

  • Mã độc đánh cắp thông tin như WardenStealer và Aoki nhắm vào token phiên ChatGPT, Claude, token OAuth và khoá API trên máy lập trình viên.
  • LLMjacking: theo Mandiant và Google, kẻ tấn công chiếm quyền truy cập dịch vụ mô hình ngôn ngữ của doanh nghiệp, để lại hoá đơn có thể lên tới 1 triệu USD.
  • Tiện ích trình duyệt độc hại được chứng minh có thể lạm dụng tính năng Claude Dispatch để phê duyệt prompt và chạy mã qua Claude Desktop.
  • Vụ Binance: báo cáo sơ bộ cho biết chuỗi tấn công bắt đầu từ việc một kỹ sư tải bản cài Homebrew bị chỉnh sửa trong lúc tìm một công cụ lập trình AI phổ biến, và sau đó kẻ tấn công còn dùng một công cụ AI nội bộ để chiếm thêm máy của đồng nghiệp.
  • Langflow, công cụ dựng ứng dụng AI phổ biến, được công bố 7 lỗ hổng, trong đó có lỗi vượt xác thực và thực thi mã từ xa.

Điểm chung: máy của lập trình viên dùng AI tập trung rất nhiều quyền (khoá API mô hình, quyền repo, quyền đám mây, SSH), và agent làm việc thay bạn nên mọi thứ bạn cho agent thấy đều có thể bị lưu lại ở đâu đó.

Kiểm tra repo của bạn trong 10 phút#

Bước 1: Tìm tệp của agent đang được git theo dõi

Chạy trong thư mục gốc của từng repo:

git ls-files | grep -E '(^|/)\.(claude|cursor|gemini|specstory)/'

Nếu lệnh in ra bất kỳ tệp nào, hãy mở ra xem nội dung. Tiếp theo, kiểm tra cả lịch sử, vì tệp có thể đã bị xoá khỏi nhánh hiện tại nhưng vẫn nằm trong commit cũ:

git log --all --oneline -- '**/.claude/settings.local.json' '.claude/settings.local.json'

Bước 2: Tìm chuỗi đáng ngờ trong tệp quyền

grep -rEn "(password|passwd|token|secret|apikey|api_key|Bearer |://[^ ]+:[^ ]+@|sshpass|-p[^ ]{4,})" .claude/ .cursor/ 2>/dev/null

Mẫu ://người-dùng:mật-khẩu@ đặc biệt quan trọng vì đó là định dạng chuỗi kết nối cơ sở dữ liệu có nhúng mật khẩu.

Bước 3: Quét toàn bộ lịch sử bằng công cụ chuyên dụng

Dù không bắt được mọi mật khẩu tự đặt, gitleaks hay TruffleHog vẫn bắt được phần lớn khoá có định dạng chuẩn. Ví dụ với gitleaks:

gitleaks git -v .

(Cú pháp có thể khác tuỳ phiên bản, xem gitleaks --help.)

Bước 4: Kiểm tra trên GitHub

Với repo công khai, vào Security → Secret scanning để xem GitHub đã cảnh báo gì chưa. Nếu repo từng công khai rồi chuyển sang riêng tư, hãy coi như mọi bí mật trong lịch sử đã bị lộ.

Nếu đã lộ: đổi khoá trước, dọn lịch sử sau#

Thứ tự này rất quan trọng. Nhiều người phản xạ đầu tiên là xoá tệp và đẩy commit mới, nhưng như báo cáo nhấn mạnh, xoá tệp không xoá được lịch sử git, các bản fork và các bản clone mà người khác đã tải về. Công cụ quét tự động của kẻ tấn công có thể đã lấy được khoá trong vài phút sau khi bạn đẩy lên.

  1. Thu hồi và tạo lại (rotate) mọi bí mật xuất hiện trong tệp: khoá API, mật khẩu cơ sở dữ liệu, khoá SSH, token dịch vụ. Với mật khẩu cơ sở dữ liệu, đổi cả mật khẩu và kiểm tra danh sách người dùng của cơ sở dữ liệu.
  2. Kiểm tra nhật ký sử dụng của từng dịch vụ trong khoảng thời gian bí mật bị lộ: hoá đơn API mô hình AI, nhật ký đăng nhập SSH (last, /var/log/auth.log), nhật ký truy cập cơ sở dữ liệu, hoạt động bất thường trên tài khoản đám mây.
  3. Xoá các allow rule chứa bí mật khỏi tệp cấu hình của agent.
  4. Dọn lịch sử git bằng git filter-repo hoặc BFG Repo-Cleaner nếu cần, rồi force-push. Bước này giúp giảm phơi nhiễm về sau, không thay thế bước 1.
  5. Bật cảnh báo chi phí cho tài khoản API và đám mây để phát hiện sớm nếu khoá cũ còn sót ở đâu đó.

Bộ cấu hình an toàn hơn#

1. Đưa thư mục agent ra khỏi git, ở mọi cấp

Thêm vào .gitignore của từng repo (không chỉ dựa vào gitignore toàn cục):

# AI coding agent: cấu hình cục bộ, bản ghi hội thoại, bộ nhớ
.claude/settings.local.json
.claude/*.local.*
.cursor/
.gemini/
.specstory/
*.agent-memory.*
.env
.env.*
!.env.example

Một số nhóm muốn chia sẻ cấu hình chung của agent (ví dụ .claude/settings.json chứa quy tắc dùng chung cho cả đội). Trường hợp đó hãy commit tệp dùng chung nhưng loại tệp .local, và review tệp dùng chung như review mã nguồn.

Thêm cả gitignore toàn cục làm lớp phòng thủ thứ hai:

git config --global core.excludesFile ~/.gitignore_global

rồi đặt các dòng tương tự vào ~/.gitignore_global.

2. Không bao giờ gõ bí mật thẳng vào lệnh

Đây là thay đổi thói quen quan trọng nhất, và nó áp dụng cả khi bạn tự gõ lẫn khi agent đề xuất. Thay vì:

curl -H "Authorization: Bearer sk-abc123..." https://api.example.com/v1/items

hãy dùng biến môi trường:

curl -H "Authorization: Bearer $EXAMPLE_API_KEY" https://api.example.com/v1/items

Khi đó allow rule chỉ lưu tên biến, không lưu giá trị. Nạp biến môi trường từ trình quản lý bí mật thay vì để trong tệp văn bản. Ví dụ với 1Password CLI:

op run --env-file=.env.tpl -- npm run migrate

trong đó .env.tpl chỉ chứa tham chiếu kiểu DATABASE_URL=op://Dev/postgres/url, an toàn để commit. Các lựa chọn khác như Doppler, Infisical, HashiCorp Vault hay trình quản lý bí mật của nhà cung cấp đám mây hoạt động theo cùng nguyên tắc.

Bạn cũng nên ghi rõ quy tắc này vào tệp hướng dẫn của agent (ví dụ CLAUDE.md hoặc AGENTS.md), để agent tự đề xuất lệnh dùng biến môi trường:

## Quy tắc bí mật
- Không bao giờ đưa mật khẩu, token, khoá API trực tiếp vào lệnh shell.
- Luôn tham chiếu biến môi trường ($DATABASE_URL, $OPENAI_API_KEY...).
- Không đọc, in ra hay tóm tắt nội dung tệp .env.
- Nếu thiếu biến môi trường, dừng lại và hỏi, không tự tạo giá trị.

3. Chặn agent đọc tệp bí mật

Claude Code hỗ trợ quy tắc từ chối (deny) trong tệp settings.json. Một cấu hình khởi điểm hợp lý cho dự án:

{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Read(~/.ssh/**)",
      "Read(~/.aws/**)"
    ],
    "allow": [
      "Bash(npm run test:*)",
      "Bash(npm run lint)",
      "Bash(git status)",
      "Bash(git diff:*)"
    ]
  }
}

Nguyên tắc: allow rule nên hẹp và không chứa giá trị, ví dụ cho phép npm run test:* thay vì cho phép mọi lệnh psql. Cursor, Copilot trong VS Code và các agent khác đều có danh sách cho phép hoặc chặn lệnh terminal và thiết lập tự động phê duyệt; hãy rà soát lại danh sách này định kỳ thay vì chỉ thêm vào.

Boris Cherny cũng khuyến nghị dùng chế độ tự động (auto mode) của Claude Code, nơi agent tự đánh giá rủi ro của từng hành động, thay vì tích luỹ hàng trăm allow rule thủ công. Đây là lựa chọn đáng cân nhắc, nhưng không thay thế được thói quen không gõ bí mật vào lệnh.

4. Chặn ở bước commit: pre-commit hook

Thêm một lớp chặn tự động trước khi bí mật kịp rời máy. Với framework pre-commit, tệp .pre-commit-config.yaml:

repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: vX.Y.Z   # điền phiên bản mới nhất
    hooks:
      - id: gitleaks
  - repo: local
    hooks:
      - id: chan-thu-muc-agent
        name: Chặn commit thư mục AI agent
        entry: "Không commit tệp cục bộ của AI agent"
        language: fail
        files: '(^|/)\.(cursor|gemini|specstory)/|settings\.local\.json$'

Hook thứ hai quan trọng vì nó chặn theo đường dẫn tệp, không phụ thuộc vào việc công cụ quét có nhận ra mật khẩu hay không. Đó đúng là lỗ hổng mà báo cáo chỉ ra.

5. Bật secret scanning và push protection trên GitHub

Trong phần cài đặt bảo mật của repo hoặc tổ chức, bật Secret scanning và Push protection. Push protection chặn ngay lúc git push nếu phát hiện khoá có định dạng nhận dạng được. Với repo công khai, tính năng này miễn phí.

6. Tách khoá dev và production, cấp quyền tối thiểu

Agent làm việc trên máy bạn nên chỉ thấy khoá của môi trường phát triển, với quyền tối thiểu và hạn mức chi tiêu thấp. Khoá production không nên tồn tại trên máy cá nhân. Nếu bắt buộc, dùng khoá có thời hạn ngắn và chỉ đọc. Cách này không ngăn lộ khoá, nhưng giới hạn thiệt hại khi lộ.

7. Chạy agent trong môi trường cách ly khi làm việc với repo lạ

Khi cần agent xử lý mã từ nguồn bên ngoài (repo clone về để thử, bài tập kỹ thuật, mã của khách hàng), hãy chạy trong devcontainer, máy ảo hoặc chế độ sandbox của công cụ, nơi không có khoá SSH, không có thông tin đăng nhập đám mây. Vụ Binance cho thấy một “bài kiểm tra tuyển dụng” có mã độc chạy trên máy công việc có thể là điểm khởi đầu cho chuỗi tấn công rất lớn.

8. Cẩn thận với nguồn tải công cụ AI

Chỉ cài agent, plugin, tiện ích mở rộng từ nguồn chính thức, kiểm tra đúng tên nhà phát hành. Không bấm vào quảng cáo khi tìm trang tải. Với marketplace plugin, gõ chính xác tên đầy đủ của plugin thay vì chọn từ kết quả tìm kiếm.

Danh sách kiểm tra theo giai đoạn#

Giai đoạnViệc cần làm
Thiết lập dự án.gitignore có thư mục agent và .env; tệp hướng dẫn agent có quy tắc bí mật; deny rule cho tệp bí mật; pre-commit hook
Khi làm việcKhông gõ bí mật vào lệnh; đọc kỹ lệnh trước khi chọn “đừng hỏi lại”; không nhờ agent git add -A khi chưa xem danh sách tệp
Trước khi đẩy lêngit status và xem danh sách tệp; để pre-commit hook chạy, không dùng --no-verify
Định kỳ hằng thángRà soát và xoá allow rule cũ; xoay vòng khoá API; kiểm tra hoá đơn API và cảnh báo secret scanning
Khi có sự cốĐổi khoá ngay, kiểm tra nhật ký, rồi mới dọn lịch sử git

Câu hỏi thường gặp#

Repo của tôi là private thì có cần lo không?

Rủi ro thấp hơn nhiều, nhưng không bằng không. Repo private vẫn có thể bị chuyển công khai sau này, được chia sẻ cho cộng tác viên, hoặc bị lộ khi tài khoản GitHub của ai đó trong nhóm bị chiếm. Nguyên tắc an toàn là bí mật không nên nằm trong git, dù repo công khai hay riêng tư.

Có nên ngừng dùng chế độ “đừng hỏi lại”?

Không cần ngừng hẳn. Hãy dùng có chọn lọc: đồng ý vĩnh viễn với lệnh an toàn, lặp lại nhiều, không chứa giá trị nhạy cảm như chạy test, lint, xem trạng thái git. Với lệnh có tham số nhạy cảm, chọn “đồng ý lần này”.

Agent có tự đọc tệp .env khi tôi không yêu cầu không?

Có thể, khi agent tìm hiểu cấu hình dự án để giải quyết lỗi. Đó là lý do nên có deny rule cho .env và ghi rõ trong tệp hướng dẫn rằng agent không đọc, không in nội dung tệp này.

Tôi dùng DeepSeek, Qwen hoặc mô hình khác qua Claude Code hay công cụ trung gian thì sao?

Rủi ro về tệp quyền và lịch sử git là như nhau, vì nó nằm ở công cụ agent chứ không ở mô hình. Thêm vào đó, khi lệnh và nội dung tệp được gửi qua dịch vụ trung gian, bạn cần đánh giá thêm chính sách dữ liệu của bên trung gian.

Kết luận#

Vụ 2.539 bí mật trên GitHub không phải lỗi của riêng một công cụ. Nó là hệ quả của việc agent làm việc với quyền của chúng ta, lưu lại những gì chúng ta duyệt, và thói quen “commit hết” vốn đã có từ trước khi AI xuất hiện. Ba thay đổi mang lại hiệu quả lớn nhất: đưa thư mục agent ra khỏi git ở cấp từng repo, không gõ bí mật trực tiếp vào lệnh, và thêm một pre-commit hook chặn theo đường dẫn tệp. Mất khoảng 15 phút cho mỗi dự án, ít hơn rất nhiều so với thời gian xử lý một khoá production bị lộ.

Nếu bạn đang chọn công cụ, có thể đọc thêm review Claude chi tiết và các bài trong chuyên mục Lập trình AI.

Nguồn tham khảo#

Mở kho mẫu sao chép