Khi lỡ đẩy khoá bí mật lên git, việc đầu tiên là thu hồi khoá đó và tạo khoá mới, không phải xoá commit. Kể từ lúc khoá rời máy bạn, phải coi như nó đã lộ: xoá khỏi lịch sử chỉ ngăn người đến sau thấy, không lấy lại được bản đã bị sao chép. Sau khi khoá cũ vô hiệu, mới tới việc xem nhật ký sử dụng, dọn lịch sử git và cài lớp chặn để không lặp lại.
Bài này đi theo thứ tự đó, có lệnh git cụ thể cho các tình huống thường gặp: commit còn trên máy, đã đẩy lên nhánh riêng, đã gộp vào nhánh chính. Trợ lý AI giúp được ở vài bước, và có một bước tuyệt đối không giao cho nó.
Mười lăm phút đầu: thu hồi trước mọi việc khác
Thứ tự dưới đây được sắp theo mức độ khẩn. Đừng mất thời gian viết lại lịch sử git khi khoá còn đang hoạt động.
- Xác định chính xác thứ bị lộ: khoá của dịch vụ nào, tài khoản nào, quyền gì. Một tệp .env có thể chứa năm khoá; liệt kê cả năm.
- Vào trang quản trị của từng dịch vụ, thu hồi hoặc vô hiệu khoá cũ và tạo khoá mới. Với mật khẩu cơ sở dữ liệu, đổi mật khẩu tài khoản đó.
- Cập nhật khoá mới vào nơi ứng dụng thật đang đọc: biến môi trường máy chủ, kho bí mật, cấu hình tích hợp liên tục. Khởi động lại dịch vụ nếu cần và kiểm ứng dụng vẫn chạy.
- Báo cho người phụ trách và những người cùng dùng khoá đó để họ không bất ngờ khi khoá cũ ngừng chạy.
- Ghi lại thời điểm khoá được đẩy lên và thời điểm thu hồi. Khoảng thời gian này là cửa sổ cần điều tra.
Nhiều người làm ngược: xoá commit trước vì ngại người khác thấy, rồi mới đi đổi khoá. Trong lúc đó khoá vẫn dùng được. Nếu kho mã công khai, khoảng thời gian từ lúc đẩy tới lúc bị công cụ quét tự động tìm thấy có thể rất ngắn.
Một số nền tảng lưu trữ mã có tính năng quét bí mật và tự báo cho nhà cung cấp dịch vụ khi phát hiện khoá thuộc định dạng đã biết; vài nhà cung cấp tự vô hiệu khoá khi nhận được báo. Đừng trông vào điều đó, tự thu hồi vẫn là việc của bạn.
Xem khoá đã bị dùng chưa
Sau khi thu hồi, mở nhật ký sử dụng hoặc lịch sử hoạt động của dịch vụ trong cửa sổ thời gian đã ghi. Tìm lượt gọi từ địa chỉ lạ, khối lượng bất thường, thao tác bạn không làm: tạo tài nguyên mới, đọc dữ liệu hàng loạt, đổi cấu hình. Với dịch vụ đám mây, xem thêm có tài khoản hay khoá mới nào được tạo từ khoá bị lộ không, vì kẻ xâm nhập thường tạo thêm đường vào trước khi khoá cũ bị thu hồi.
Với cơ sở dữ liệu, xem nhật ký kết nối nếu có bật. Nếu khoá chạm tới dữ liệu cá nhân của khách hàng và có dấu hiệu bị truy cập, việc này vượt khỏi phạm vi kỹ thuật: báo ngay cho lãnh đạo và người phụ trách pháp chế của công ty, vì có thể phát sinh nghĩa vụ thông báo theo quy định về bảo vệ dữ liệu cá nhân hiện hành.
Trợ lý AI giúp được ở bước đọc nhật ký: bạn có thể đưa cho nó cấu trúc nhật ký đã che địa chỉ và mã định danh, nhờ viết câu lọc tìm hoạt động bất thường. Đừng dán nguyên nhật ký có địa chỉ, tên người dùng, mã phiên vào chatbot.
Dọn lịch sử git theo từng tình huống
Chỉ làm sau khi khoá đã bị thu hồi. Viết lại lịch sử ảnh hưởng tới mọi người đang làm trên kho mã, nên báo nhóm trước.
| Tình huống | Cách xử lý | Lưu ý |
|---|---|---|
| Commit còn trên máy, chưa đẩy | Nếu là commit cuối: sửa tệp, gỡ .env khỏi chỉ mục bằng git rm --cached .env, rồi git commit --amend. Nếu nằm sâu hơn: dùng rebase tương tác để sửa commit đó | Kiểm lại bằng git log -p rằng khoá không còn trong commit nào chưa đẩy |
| Đã đẩy lên nhánh riêng, chưa ai kéo về | Sửa như trên rồi đẩy đè bằng git push --force-with-lease | Dùng force-with-lease thay vì force để không đè mất việc người khác lỡ đẩy lên cùng nhánh |
| Đã gộp vào nhánh chính, nhiều người đã kéo | Dùng công cụ viết lại lịch sử chuyên dụng như git filter-repo để xoá tệp hoặc thay chuỗi khoá trong toàn bộ lịch sử, rồi đẩy đè và yêu cầu mọi người sao chép lại kho | Các bản sao cũ trên máy đồng nghiệp vẫn chứa khoá; yêu cầu họ xoá bản cũ |
| Kho mã công khai hoặc đã có bản rẽ nhánh | Như trên, thêm liên hệ bộ phận hỗ trợ của nền tảng nếu cần xoá bộ nhớ đệm của commit cũ | Bản rẽ nhánh và bản sao của người lạ không xoá được; khoá đã thu hồi là lớp bảo vệ thật |
Lệnh git filter-branch cũ vẫn có trong nhiều bài hướng dẫn và AI hay đề xuất nó, nhưng chính tài liệu của git khuyên dùng công cụ khác vì chậm và dễ sai. git filter-repo là công cụ cài riêng; kiểm tài liệu của nó để dùng đúng tuỳ chọn cho phiên bản bạn cài.
Trước khi viết lại lịch sử, sao lưu toàn bộ kho mã ở dạng nguyên vẹn ra một nơi riêng. Viết lại lịch sử là thao tác không quay lại được nếu không có bản sao.
Việc không giao cho AI và việc giao được
Không giao cho tác tử AI tự thực hiện viết lại lịch sử và đẩy đè lên nhánh chính. Đây là thao tác phá huỷ, ảnh hưởng cả nhóm, và một tham số sai có thể xoá nhầm tệp khỏi toàn bộ lịch sử. Nếu tác tử đề xuất chạy lệnh đẩy đè, từ chối và tự làm sau khi đã đọc kỹ từng lệnh.
Việc giao được: nhờ AI giải thích từng tuỳ chọn của lệnh trước khi bạn chạy, nhờ viết danh sách các bước theo đúng tình huống của bạn để bạn đối chiếu, nhờ viết thông báo cho nhóm về việc sao chép lại kho. Câu lệnh mẫu: “Kho mã của nhóm có một tệp .env đã nằm trong lịch sử nhánh chính từ ba tuần trước, năm người đã kéo về. Khoá đã được thu hồi. Liệt kê các bước dọn lịch sử bằng git filter-repo, giải thích từng tuỳ chọn, và những việc mỗi thành viên phải làm sau đó. Không chạy lệnh nào.”
Khi dán bất kỳ đoạn nào từ kho mã vào khung chat trong lúc xử lý sự cố, kiểm lại rằng đoạn đó không còn chứa khoá, kể cả khoá đã thu hồi. Thói quen này đáng giữ ngay cả khi khoá đã vô hiệu, để không ai sao chép nhầm thứ trông giống thật.
Chặn lần sau: ba lớp, đặt ở ba chỗ
Lớp một, trên máy từng người. Cài một móc kiểm tra trước khi commit chạy công cụ quét bí mật trên các thay đổi. Có nhiều công cụ mã nguồn mở làm việc này; chọn một và ghi cách cài vào tài liệu dự án. Móc chạy trên máy nên chặn được trước khi khoá rời máy, nhưng người dùng có thể bỏ qua, nên không đủ một mình.
Lớp hai, trên nền tảng lưu trữ mã. Bật tính năng quét bí mật và chặn đẩy nếu nền tảng có. Lớp này chặn ở phía máy chủ, không phụ thuộc người dùng có cài móc hay không. Kiểm tài liệu nền tảng vì tính năng và gói áp dụng thay đổi theo thời gian.
Lớp ba, trong quy trình tích hợp liên tục. Thêm một bước quét bí mật vào quy trình chạy cho mỗi yêu cầu gộp mã. Lớp này bắt cả trường hợp khoá nằm trong tệp không phải .env, như tệp cấu hình, sổ tay dữ liệu hay tệp kiểm thử.
Thêm quy ước cho trợ lý AI. Ghi vào tệp hướng dẫn dự án: không tạo commit có tệp .env, không đặt giá trị bí mật vào mã hay tệp kiểm thử, dùng biến môi trường giả cho kiểm thử. Với tác tử có quyền commit, bật chế độ duyệt trước khi commit.
Giảm thiệt hại nếu ba lớp đều trượt. Khoá có quyền hẹp, có hạn mức, có hạn dùng, và khoá phát triển tách khỏi khoá thật. Lộ một khoá hẹp là sự cố nhỏ; lộ một khoá quản trị là sự cố lớn.
Rút kinh nghiệm mà không đổ lỗi
Sau khi xong việc, dành mười lăm phút ghi lại: khoá nào, lọt qua đường nào, bao lâu thì phát hiện, mất bao lâu để thu hồi, lớp chặn nào đã thiếu. Mục tiêu là sửa quy trình, không phải tìm người để trách. Người lỡ đẩy khoá mà thấy bị trách sẽ có xu hướng giấu ở lần sau, và giấu là điều nguy hiểm nhất trong sự cố lộ khoá.
Một bản ghi ngắn như vậy cũng là tài liệu tốt cho người mới. Thay vì danh sách luật khô khan, họ đọc một câu chuyện có thật trong chính nhóm mình về việc tại sao móc quét bí mật tồn tại và vì sao không được bỏ qua nó.
Cuối cùng, kiểm lại sau một tuần rằng khoá cũ thật sự không còn dùng được, ứng dụng không còn chỗ nào đọc khoá cũ, và các lớp chặn mới đã hoạt động bằng cách thử commit một chuỗi giả có định dạng giống khoá trên một nhánh nháp.
Những nơi khác cần soát cùng lúc
Khoá lọt lên git thường không đi một mình. Trong lúc xử lý, soát luôn các nơi mà cùng tệp hoặc cùng giá trị có thể đã đi tới, vì thu hồi khoá giải quyết rủi ro dùng khoá nhưng không cho biết khoá đã lan tới đâu.
- Nhật ký của hệ thống tích hợp liên tục: các lần chạy trên commit có khoá có thể đã in nội dung tệp hoặc biến ra nhật ký công khai trong nhóm.
- Ảnh chứa hoặc gói đã dựng từ commit đó và đẩy lên kho ảnh hay kho gói: tệp .env có thể đã bị đóng gói kèm.
- Bản sao lưu tự động của kho mã và của máy chủ chạy mã từ commit đó.
- Nhóm chat, phiếu công việc, yêu cầu gộp mã có dán đoạn diff chứa khoá.
- Các phiên trò chuyện với trợ lý AI trong thời gian đó, nếu bạn hay đồng nghiệp đã dán tệp hoặc diff vào.
- Các nhánh khác được tạo từ commit có khoá: dọn nhánh chính mà quên nhánh tính năng thì khoá vẫn còn trong kho.
Với những nơi không xoá được, như nhật ký đã gửi cho bên thứ ba, ghi lại vào bản tường trình. Khoá đã thu hồi nên rủi ro dùng khoá không còn, nhưng danh sách này cho thấy những đường lọt cần đóng trong quy trình.
Câu hỏi thường gặp
Kho mã là riêng tư thì có cần thu hồi khoá không?
Vẫn nên thu hồi. Kho riêng tư vẫn được nhiều người, nhiều công cụ, nhiều máy truy cập, và có thể chuyển sang công khai hay bị lộ quyền truy cập về sau. Khoá đã vào lịch sử git là khoá khó kiểm soát.
Đã xoá tệp .env ở commit mới nhất thì khoá còn trong git không?
Còn. Commit mới chỉ ghi lại việc xoá tệp, các commit cũ vẫn giữ nguyên nội dung. Ai có bản sao kho đều xem lại được bằng lịch sử. Phải viết lại lịch sử nếu muốn khoá biến mất khỏi kho, và vẫn phải thu hồi khoá.
Có thể nhờ tác tử AI tự chạy git filter-repo không?
Không nên. Đây là thao tác phá huỷ ảnh hưởng cả nhóm. Dùng AI để giải thích lệnh và lập danh sách bước, còn việc chạy và đẩy đè do người có trách nhiệm làm sau khi đã sao lưu.
Khoá chỉ nằm trên nhánh nháp vài phút có cần làm hết các bước?
Thu hồi và tạo khoá mới thì vẫn cần, vì nhanh và chắc. Phần dọn lịch sử có thể đơn giản hơn nếu nhánh chưa ai kéo về. Đừng tự nhủ vài phút thì không sao.
Làm sao biết công cụ quét bí mật đang chạy thật?
Thử commit một chuỗi giả có định dạng giống khoá trên nhánh nháp. Nếu móc trên máy, nền tảng và quy trình tích hợp đều chặn hoặc báo, ba lớp đang hoạt động. Xoá nhánh nháp sau khi thử.
Có cần báo cho khách hàng khi khoá bị lộ không?
Tuỳ khoá đó chạm tới dữ liệu gì và nhật ký có cho thấy bị truy cập hay không. Nếu có khả năng dữ liệu cá nhân của khách bị đọc, quyết định thông báo thuộc về lãnh đạo và pháp chế theo quy định hiện hành, không phải lập trình viên tự quyết.