Không nên còn gì để thu hoạch
Một phiên bản Bitwarden CLI bị xâm phạm đã thu thập khóa SSH, thông tin xác thực đám mây và mã thông báo npm từ 334 máy của lập trình viên. Vấn đề thực sự không phải là phần mềm độc hại lọt vào bằng cách nào. Mà là mọi bí mật đều nằm đó dưới dạng tệp văn bản thuần, chờ bị đọc.
Hôm qua, một phiên bản Bitwarden CLI bị xâm phạm đã thu thập khóa SSH, thông tin xác thực AWS, mã thông báo npm, biến môi trường, lịch sử shell và bí mật Git từ 334 máy của lập trình viên.
Hôm nay là Bitwarden. Tháng trước là Axios. Trước đó là Checkmarx. Ngày mai sẽ là một tiện ích VS Code, hoặc Acrobat, hoặc một công thức Homebrew, hoặc một image Docker. Vector thay đổi mỗi tuần. Kết quả luôn như nhau.
Phần mềm độc hại đáp xuống máy. Nó đọc ~/.ssh/. Nó đọc ~/.aws/credentials. Nó đọc ~/.npmrc. Nó đọc ~/.git-credentials. Nó đọc lịch sử shell, biến môi trường, kho mật khẩu của trình duyệt. Nó gom tất cả lại và gửi tới một máy chủ C2.
Và nó hoạt động. Lần nào cũng vậy.
Đợt thu hoạch
Phần tải của Bitwarden — một tệp 10 MB được làm rối tên là bw1.js — không cố phá bất kỳ lớp mã hóa nào. Nó không cần làm vậy. Đây là những gì nó thu thập, theo tài liệu của Socket và Aikido:
- Khóa SSH và vân tay máy chủ
- Thông tin xác thực đám mây AWS, GCP và Azure
- Mã thông báo xác thực npm
- Thông tin xác thực Git và URL từ xa
- Biến môi trường
- Lịch sử shell
- Thông tin xác thực Claude Code và cấu hình MCP
Sau đó nó dùng các mã thông báo npm đã đánh cắp để xuất bản lại các gói khác mà nạn nhân duy trì, từ đó lan rộng hơn nữa. Nạn nhân trở thành vector lây lan.
Không có bước nào trong số này cần phá mã hóa. Mỗi bí mật trong số đó đều là một tệp trên hệ thống tệp, bất kỳ tiến trình nào chạy dưới quyền người dùng đều đọc được.
Đây không phải là câu chuyện về Bitwarden
Lớp mã hóa két của Bitwarden không bị phá. Kiến trúc zero-knowledge của họ vẫn đứng vững. Phần mềm độc hại không bao giờ chạm tới két.
Nó không cần phải làm vậy.
Két bảo vệ những gì ở bên trong nó. Nhưng khóa SSH không bao giờ nằm trong két. Thông tin xác thực AWS không bao giờ nằm trong két. Mã thông báo npm, thông tin xác thực Git, khóa API trong các tệp .env — không có cái nào trong số này nằm trong trình quản lý mật khẩu. Chúng nằm trong các dotfile, ở dạng văn bản thuần, trên máy của mọi lập trình viên.
Kẻ tấn công hiểu điều này. Két là một két sắt khóa kín trong một căn nhà mà mọi ngăn kéo đều mở toang.
Bề mặt tấn công thực sự
Mở một terminal ngay bây giờ. Nhìn xem trên máy bạn có gì.
~/.ssh/id_ed25519 — khóa riêng của bạn. Tệp văn bản thuần.
~/.aws/credentials — quyền truy cập đám mây của bạn. Tệp văn bản thuần.
~/.npmrc — mã thông báo xuất bản của bạn. Tệp văn bản thuần.
~/.git-credentials — quyền truy cập kho mã của bạn. Tệp văn bản thuần.
~/.env trong hàng tá thư mục dự án — khóa API, mật khẩu cơ sở dữ liệu, bí mật ký. Tất cả đều là tệp văn bản thuần.
Bất kỳ tiến trình nào chạy dưới quyền người dùng của bạn đều đọc được tất cả những thứ này. Không cần leo thang đặc quyền. Không cần khai thác lỗ hổng. Chỉ cần cat.
Đây là thiết lập mặc định của lập trình viên trong năm 2026. Chúng ta để mật khẩu trong một két được mã hóa rồi bỏ mặc mọi thứ khác ở ngoài trời.
Câu hỏi sai
Sau mỗi cuộc tấn công chuỗi cung ứng, ngành lại đặt ra cùng một câu hỏi: làm sao ngăn phần mềm độc hại lọt vào?
Bảo mật CI/CD tốt hơn. Ký mã. Quét phụ thuộc. Runtime được cách ly. Tất cả những điều này đều tốt. Không cái nào là đủ. Bề mặt tấn công quá rộng. Có quá nhiều vector — trình quản lý gói, tiện ích trình duyệt, plugin IDE, ứng dụng OAuth, công cụ build bị xâm phạm. Bạn không thể bịt kín mọi điểm vào.
Câu hỏi đúng là: khi phần mềm độc hại chắc chắn giành được quyền thực thi trên máy của một lập trình viên, nó tìm thấy gì?
Nếu câu trả lời là "hàng trăm thông tin xác thực dạng văn bản thuần ở những vị trí hệ thống tệp có thể đoán trước", thì dù gia cố chuỗi cung ứng đến đâu cũng vô nghĩa. Bạn đang phòng thủ trên một sân mà khung thành bỏ ngỏ ngay phía sau lưng.
Không nên còn gì để thu hoạch
Cách sửa không phải là phát hiện phần mềm độc hại tốt hơn. Cách sửa không phải là cách ly npm install. Cách sửa không phải là rút ngắn thời gian phản ứng sự cố.
Cách sửa là: bí mật không nên tồn tại dưới dạng tệp trên đĩa.
Khóa SSH được dẫn xuất từ phần cứng ngay tại thời điểm xác thực — chứ không lưu trong ~/.ssh/. Thông tin xác thực đám mây được cấp theo từng phiên từ một danh tính gắn với phần cứng — chứ không ghi ra ~/.aws/. Mã thông báo API được thu hẹp phạm vi, tạm thời và chặn bằng phần cứng — chứ không nằm trong các tệp .env.
Khi một thông tin xác thực chỉ tồn tại bên trong mô-đun bảo mật phần cứng và trong bộ nhớ tiến trình tạm thời trong lúc dùng, phần mềm độc hại không có gì để đọc. Không có tệp nào để đánh cắp. Không có dotfile nào để cào. Tiến trình chạy, nó không tìm thấy gì, nó đi tiếp.
Đây không phải lý thuyết suông. Thông tin xác thực gắn với phần cứng đã tồn tại ngay hôm nay. WebAuthn PRF có thể dẫn xuất khóa mã hóa từ một lần chạm xác thực vật lý — những khóa không bao giờ chạm vào hệ thống tệp. Công nghệ đã sẵn sàng. Ngành chỉ chưa áp dụng nó làm mặc định.
Cần làm gì ngay bây giờ
Nếu bạn bị ảnh hưởng bởi sự cố Bitwarden CLI bị xâm phạm:
- Đổi toàn bộ thông tin xác thực trên máy — khóa SSH, mã thông báo đám mây, mã thông báo npm, khóa API, mọi thứ trong các dotfile và biến môi trường
- Kiểm tra xem có gói npm nào bạn duy trì bị xuất bản lại không
- Rà soát hoạt động GitHub và các workflow CI/CD để tìm thay đổi trái phép
Nếu bạn không bị ảnh hưởng, hành động vẫn vậy. Nhìn vào máy của bạn. Đếm xem có bao nhiêu bí mật ở dạng văn bản thuần. Tự hỏi điều gì sẽ xảy ra khi — chứ không phải nếu — một thứ gì đó độc hại chạy dưới quyền người dùng của bạn.
Câu trả lời nên là: không có gì. Không nên còn gì để thu hoạch.