- Các phiên bản PyPI
lightning 2.6.2 và 2.6.3 sau khi được đăng vào ngày 30 tháng 4 năm 2026 đã bị lợi dụng trong một cuộc tấn công chuỗi cung ứng; chỉ với pip install lightning, thư mục _runtime ẩn và payload JavaScript bị làm rối có thể được thực thi
- Payload độc hại tự động chạy khi import module, đánh cắp thông tin xác thực, token xác thực, biến môi trường, bí mật đám mây, đồng thời còn cố gắng làm ô nhiễm các kho GitHub
- Điểm xâm nhập của cuộc tấn công lần này là PyPI, nhưng việc phát tán dạng sâu lại diễn ra qua npm; nếu tìm thấy thông tin xác thực để publish npm, nó sẽ chèn dropper
setup.mjs và router_runtime.js vào các gói có thể publish rồi phát hành lại phiên bản vá
- Việc rò rỉ dữ liệu sử dụng 4 kênh song song gồm HTTPS POST, dead drop qua tìm kiếm commit GitHub, kho GitHub công khai do kẻ tấn công kiểm soát và push trực tiếp vào kho của nạn nhân; các dấu hiệu nhận biết gồm tiền tố commit
EveryBoiWeBuildIsAWormyBoi và mô tả kho "A Mini Shai-Hulud has Appeared"
- Mã độc cài hook
SessionStart trong .claude/settings.json của Claude Code và tác vụ runOn: folderOpen trong .vscode/tasks.json của VS Code để chạy dropper mỗi khi mở kho; mọi máy đã import gói độc hại trong khoảng thời gian bị ảnh hưởng phải được xem là đã bị xâm phạm hoàn toàn
Các gói bị ảnh hưởng và quy trình kiểm tra
lightning là framework deep learning thường xuất hiện trong cây phụ thuộc của các nhóm xây dựng bộ phân loại ảnh, fine-tune LLM, chạy mô hình khuếch tán và phát triển bộ dự báo chuỗi thời gian
-
Các gói bị ảnh hưởng
lightning phiên bản 2.6.2
lightning phiên bản 2.6.3
-
Quy trình kiểm tra cho khách hàng Semgrep
- Nếu gần đây chưa quét dự án, cần chạy một lần quét mới
- Có thể kiểm tra trên trang advisories xem dự án có cài các phiên bản gói này gần đây hay không
- Có thể kiểm tra mục khớp tại dependency filter; nếu hiển thị “No matching dependencies” thì nghĩa là dự án không đang chủ động sử dụng phụ thuộc độc hại
- Nếu có mục khớp, cần kiểm tra trong kho các tệp bất thường trong thư mục
.claude/ và .vscode/ được nêu trong các chỉ dấu xâm nhập bên dưới
- Cần thay thế token GitHub, thông tin xác thực đám mây và khóa API có thể đã hiện diện trong môi trường bị ảnh hưởng
- Lời khuyên chung về ứng phó với tấn công chuỗi cung ứng và thời gian chờ được đề cập trong $foo compromised in $packagemanager và Attackers are Still Coming for Security Companies
Cơ chế lây lan từ PyPI sang npm
- Khác với mini Shai-Hulud nhắm trực tiếp vào npm, điểm xâm nhập của cuộc tấn công lần này là PyPI
- Payload độc hại vẫn là JavaScript, và việc phát tán dạng sâu diễn ra qua npm
- Nếu mã độc đã chạy tìm thấy thông tin xác thực publish npm, nó sẽ chèn dropper
setup.mjs và router_runtime.js vào mọi gói có thể publish bằng token đó
- Sau đó nó đặt
scripts.preinstall để thực thi dropper, tăng phiên bản vá rồi publish lại
- Các nhà phát triển cấp dưới cài những gói đó sẽ thực thi toàn bộ mã độc trên máy của mình, kéo theo việc đánh cắp token và lây nhiễm sâu qua gói
Cách thức rò rỉ dữ liệu
- Chức năng đánh cắp dữ liệu dùng chung cơ chế và thiết kế với chiến dịch Mini Shai-Hulud trước đó, sử dụng 4 kênh song song để dữ liệu vẫn thoát ra được ngay cả khi từng đường riêng lẻ bị chặn
- Cuộc tấn công mang chủ đề Shai-Hulud, bao gồm cả việc tạo kho công khai có tên
EveryBoiWeBuildIsaWormBoi
- Cấu trúc chỉ dấu tấn công khớp với chiến dịch mini Shai-Hulud trước đó, nhưng thông điệp commit độc hại dùng tiền tố
EveryBoiWeBuildIsAWormyBoi để phân biệt với cuộc tấn công Mini Shai-Hulud gốc
-
Truyền C2 qua HTTPS POST
- Dữ liệu bị đánh cắp được POST ngay tới máy chủ do kẻ tấn công kiểm soát qua cổng 443
- Tên miền và đường dẫn được lưu thành chuỗi mã hóa trong payload để gây khó cho phân tích tĩnh
-
Dead drop qua tìm kiếm commit GitHub
- Mã độc polling GitHub commit search API để tìm các thông điệp commit có tiền tố
EveryBoiWeBuildIsAWormyBoi
- Thông điệp commit mang token mã hóa Base64 kép theo định dạng
EveryBoiWeBuildIsAWormyBoi:<base64(base64(token))>
- Token sau khi giải mã được dùng để xác thực client Octokit cho các bước tiếp theo
-
Kho GitHub công khai do kẻ tấn công kiểm soát
- Một kho công khai mới được tạo với tên là từ Dune được chọn ngẫu nhiên và mô tả
"A Mini Shai-Hulud has Appeared"
- Mô tả này có thể được tìm trực tiếp trên GitHub
- Thông tin xác thực bị đánh cắp được commit dưới dạng
results/results-<timestamp>-<n>.json; tuy được mã hóa Base64 khi đi qua API nhưng bên trong là JSON thuần
- Các tệp vượt quá 30MB sẽ được chia thành các chunk được đánh số
- Thông điệp commit ngụy trang bằng
chore: update dependencies
-
Push trực tiếp vào kho của nạn nhân
- Nếu mã độc lấy được token máy chủ GitHub
ghs_, nó sẽ push trực tiếp dữ liệu bị đánh cắp vào mọi nhánh của GITHUB_REPOSITORY của nạn nhân
Mục tiêu đánh cắp
- Mã độc nhắm vào thông tin xác thực trên tệp cục bộ, môi trường, pipeline CI/CD và trên các nhà cung cấp đám mây
-
Hệ thống tệp
- Quét hơn 80 đường dẫn tệp chứa thông tin xác thực để tìm token
ghp_, gho_, npm_
- Xử lý tối đa 5MB cho mỗi tệp
-
Shell và biến môi trường
- Chạy
gh auth token
- Dump toàn bộ biến môi trường trong
process.env
-
GitHub Actions
- Trên runner Linux, dùng Python tích hợp sẵn để dump bộ nhớ tiến trình
Runner.Worker
- Trích xuất mọi bí mật được đánh dấu
"isSecret":true cùng với GITHUB_REPOSITORY, GITHUB_WORKFLOW
-
Tổ chức GitHub
- Kiểm tra các scope token là
repo, workflow
- Duyệt qua các bí mật cấp tổ chức của GitHub Actions
-
AWS
- Thử biến môi trường, profile
~/.aws/credentials, IMDSv2 169.254.169.254, ECS 169.254.170.2 để gọi sts:GetCallerIdentity
- Liệt kê và lấy mọi giá trị trong Secrets Manager cùng các tham số SSM
-
Azure
- Dùng
DefaultAzureCredential để liệt kê subscription và truy cập bí mật trong Key Vault
-
GCP
- Xác thực bằng
GoogleAuth
- Liệt kê và lấy mọi bí mật trong Secret Manager
- Phạm vi mục tiêu bao trùm môi trường phát triển cục bộ, CI runner và cả 3 nhà cung cấp đám mây lớn
- Mọi máy đã import gói độc hại trong thời gian bị ảnh hưởng phải được xem là đã bị xâm phạm hoàn toàn
Thiết lập cơ chế bám trụ qua công cụ phát triển
- Sau khi xâm nhập vào bên trong kho, mã độc nhắm vào các công cụ phát triển phổ biến là Claude Code và VS Code để cài hook bám trụ
-
Claude Code
- Mã độc ghi hook
SessionStart với matcher: "*" vào tệp cấu hình Claude Code của kho là .claude/settings.json
- Hook này trỏ tới
node .vscode/setup.mjs
- Mỗi khi nhà phát triển mở Claude Code trong kho đã nhiễm, nó sẽ chạy mà không cần sử dụng công cụ khác hay thao tác người dùng ngoài việc bắt đầu phiên
-
VS Code
- Nhắm tới người dùng VS Code, nó cài một tác vụ
runOn: folderOpen trong .vscode/tasks.json
- Mỗi khi thư mục dự án được mở,
node .claude/setup.mjs sẽ chạy
-
Dropper setup.mjs
- Cả hai hook đều gọi
setup.mjs, một bootstrapper Bun runtime tự chứa
- Nếu Bun chưa được cài, nó sẽ âm thầm tải
bun-v1.3.13 từ GitHub releases
- Hỗ trợ Linux x64, Linux arm64, Linux musl, macOS x64, macOS arm64, Windows x64, Windows arm64
- Sau đó chạy toàn bộ payload 14.8MB là
.claude/router_runtime.js và dọn dẹp trong /tmp
-
Workflow GitHub Actions độc hại
- Nếu mã độc có token GitHub với quyền ghi, nó sẽ push một workflow tên
Formatter vào kho của nạn nhân
- Trên mọi sự kiện push, workflow này dump toàn bộ bí mật của kho thông qua
${{ toJSON(secrets) }}
- Kết quả được upload thành artifact Actions có thể tải xuống với tên
format-results
- Actions được pin vào một commit SHA cụ thể để trông có vẻ hợp lệ
- Các kho nhận gói
lightning đã nhiễm trong CI và có token quyền ghi cần kiểm tra các tệp này
Chỉ dấu xâm nhập
-
Chỉ dấu có thể tìm kiếm
- Các thông điệp commit có tiền tố
EveryBoiWeBuildIsAWormyBoi được dùng làm vật mang token dead drop và có thể tìm bằng GitHub commit search
- Các kho GitHub có mô tả
"A Mini Shai-Hulud has Appeared" là kho rò rỉ do kẻ tấn công kiểm soát và có thể tìm trực tiếp
-
Gói
lightning@2.6.2
lightning@2.6.3
-
Tệp và artifact hệ thống
_runtime/start.py: loader Python khởi tạo payload khi import
_runtime/router_runtime.js: payload JavaScript bị làm rối và là Bun runtime 14.8MB
_runtime/: thư mục được thêm vào các phiên bản gói độc hại
.claude/router_runtime.js: bản sao mã độc được chèn vào kho của nạn nhân
.claude/settings.json: cấu hình hook Claude Code được chèn vào kho của nạn nhân
.claude/setup.mjs: dropper được chèn vào kho của nạn nhân
.vscode/tasks.json: tác vụ tự chạy của VS Code được chèn vào kho của nạn nhân
.vscode/setup.mjs: dropper được chèn vào kho của nạn nhân
1 bình luận
Ý kiến Hacker News
Có thể chỉ là ảo giác về tần suất, nhưng dạo gần đây có vẻ xuất hiện khá nhiều cuộc tấn công chuỗi cung ứng đình đám trong các gói quan trọng
Ngay ở vài trang đầu của HN lúc này cũng có nhiều bài nói về các trường hợp khác nhau
Nhìn lại
left-padcủa 10 năm trước, tôi tự hỏi liệu bây giờ số vụ tấn công thành công có nhiều hơn trước không, và có lẽ là cóGiá trị của các vụ tấn công thành công chắc chắn cũng đã tăng lên, nhưng tôi tự hỏi liệu khả năng phát hiện trước khi phát hành gói có thực sự đang cải thiện trên bình diện toàn cộng đồng hay không
Các công ty phần mềm thương mại tất nhiên phải làm tốt hơn, nhưng có vẻ vẫn còn thiếu những công cụ phổ quát và dễ dùng cho các trường hợp bắt đầu từ mã hobby/nghiệp dư rồi trở thành phụ thuộc của rất nhiều dự án
Tôi cũng đã đăng bình luận này trong thread về vụ tấn công chuỗi cung ứng SAP hiện tại: https://news.ycombinator.com/item?id=47964003
Trước đây, người ta thường chạy
npm installthủ công hơn, có lẽ chỉ khi build bị hỏng hoặc rất thỉnh thoảng mới chạyTấn công chuỗi cung ứng dựa vào việc con người, hay chính xác hơn là pipeline, tự động cập nhật gói ngay khi có bản phát hành mới mà không cần suy nghĩ
Tôi không biết đó có phải mô hình kinh doanh tốt không, và có lẽ là không
left-padkhông phải là một cuộc tấn công mà là lỗi của NPMKhông đáng lẽ phải có chuyện xóa được phiên bản gói mà các gói công khai khác đã phụ thuộc vào, và ngược lại thì phải cho phép xóa một phiên bản gói mới mà chưa ai phụ thuộc vào
Khi tác giả
left-padmuốn xóa toàn bộ dữ liệu với ý định rời bỏ dịch vụ, NPM đáng lẽ phải trả về mã lỗiTheo Wikipedia, khi Koçulu thất vọng với quyết định của npm, Inc. và nói rằng không muốn tiếp tục là một phần của nền tảng, Schlueter, tác giả NPM, đã cung cấp lệnh để xóa 273 module mà ông ấy đã đăng ký
Điều kỳ lạ là đã có 4 issue bảo mật được mở lên nhưng tất cả đều bị bot
pl-ghosttự động bình luận rồi đóng lại [1][2][3][4]Cuối cùng chỉ có [4] được xử lý đúng cách và toàn bộ bình luận của bot đều bị xóa
Ở báo cáo khác [5] vẫn có thể thấy bình luận của bot, và nó còn cung cấp nhiều thông tin hơn cả bài gốc
[1] https://github.com/Lightning-AI/pytorch-lightning/issues/216...
[2] https://github.com/Lightning-AI/pytorch-lightning/issues/216...
[3] https://github.com/Lightning-AI/pytorch-lightning/issues/216...
[4] https://github.com/Lightning-AI/pytorch-lightning/issues/216...
[5] https://socket.dev/blog/lightning-pypi-package-compromised
Kẻ tấn công đã dùng tài khoản này để tạo workflow Actions mới, rồi từ workflow đó parse và lấy trộm secret PyPI
Sau khi phát hành gói, hắn còn dùng tài khoản đó để bình luận, kiểu như chế nhạo chúng tôi một chút
Tôi thật sự mong ngày không còn phụ thuộc nào sẽ sớm đến
Lấy ví dụ cực đoan, gần đây khi làm ứng dụng giáo dục tương tác cho con gái, tôi bảo Opus chỉ dùng JavaScript và HTML thuần
Từ con lắc kép đến mô phỏng chất lưu đều chạy tốt trong một lần, trong khi trước đây sẽ kéo theo hàng trăm phụ thuộc
Nếu là mã giấy phép MIT, tôi còn có thể bảo Opus trích đúng phần cần thiết, sửa cho phù hợp với mục đích của tôi rồi nhúng luôn vào
Với các dự án hobby thì đến giờ cách này hoạt động tốt, và tôi hy vọng sau này cả phần mềm production cũng có thể bớt phụ thuộc
Nếu Chrome thay đổi hình dạng của một API nào đó thì bạn phải tự đi tìm và sửa, còn nếu Morocco đổi thời điểm bắt đầu giờ mùa hè thì bạn cũng phải tự cập nhật mã xử lý ngày/giờ
Đó là những việc mà thư viện vẫn âm thầm xử lý giúp ta nên ta coi là hiển nhiên
Với một trình mô phỏng con lắc kép mà tuần sau con gái bạn có thể chẳng còn hứng thú thì không sao, nhưng với một công ty làm thứ phải chạy vô thời hạn về sau thì đó là vấn đề
Chắc tôi phải tung ra một đoạn mã truy cập từ xa giấy phép MIT để nó chui vào tập dữ liệu huấn luyện của Opus mới được
Khi học khóa deep learning của Fast.AI, tôi đã rất ngạc nhiên trước số lượng phụ thuộc Python mà các dự án machine learning kéo theo
Các dự án web frontend vốn luôn bị xem là có nhiều phụ thuộc bên thứ ba, nhưng với tôi hệ sinh thái machine learning còn rối rắm hơn nhiều
Thêm nữa, phát triển web vốn được xem là nhạy cảm về bảo mật nên đã tích lũy được nhiều kinh nghiệm và thông lệ bảo mật từ lâu, còn phát triển machine learning thì có vẻ chắp vá hơn nhiều và cũng không áp dụng nhiều thực hành kỹ nghệ phần mềm thông thường
Ví dụ, một trong những cách triển khai model ML thời đó là dùng Python pickle, mà về cơ bản nó là một đối tượng thực thi được không có giới hạn mặc định
Model ở định dạng đó có thể làm bất cứ thứ gì trên máy tính tải nó về, và kiểu hệ sinh thái vô luật pháp ban đầu như vậy khiến vi phạm bảo mật và tấn công chuỗi cung ứng dễ xảy ra hơn
Có người trong lúc làm mới học viết code một chút, có người là nhà toán học, có người lại giống các lập trình viên say men AI
Cũng có kiểu tư duy “giờ code không còn quan trọng, chạy được là được”
Với nhiều người, quản lý phụ thuộc cho đàng hoàng chỉ là việc lặt vặt mà họ không muốn bận tâm
Nhiều dự án machine learning kết hợp tất cả những yếu tố này lại, trong khi thật ra đây lại là một trong những lĩnh vực đáng lẽ phải tập trung nhất vào tính tái lập
Tìm kiếm trong kho lưu trữ thì thấy có tới 2,2 nghìn repo được tạo trong vòng một ngày qua chứa chuỗi
"A Mini Shai-Hulud has Appeared": https://github.com/search?q=A%20Mini%20Shai-Hulud%20has%20Ap...Điều này có vẻ là dấu hiệu cho thấy tài khoản, có lẽ là token GitHub auth/Actions, đã bị xâm nhập rồi bị dùng để tạo repo
Chuyện kiểu này đã từng xảy ra rồi, nên tôi tưởng họ đã rút được bài học
Malware này chẳng tốn mấy công sức, và Microsoft dường như cũng chẳng cố gắng mấy
Nói trước là tôi chưa từng dùng pytorch và cũng không rành các thực hành bảo mật phần mềm
Nhưng tôi không nghĩ ra được mấy kịch bản mà pytorch cần truy cập mạng
Có vẻ sai khi ở bất kỳ đâu trong codebase cũng có thể import bất kỳ module nào rồi dùng API đó
Có lẽ cần thêm các hạn chế import hoặc phân tích tĩnh
Ngôn ngữ có vẻ không có abstraction phù hợp để xử lý vấn đề kiểu này
Để so sánh thì ở Rust, tôi thích việc chỉ nhìn chữ ký hàm thôi cũng có thể thấy tính biến đổi và vòng đời mà không cần hiểu mã bên trong
Tôi cảm giác phụ thuộc cũng cần một thứ tương tự
Nhà phát triển đáng lẽ phải có thể audit dễ dàng toàn bộ phụ thuộc mà không cần đào xuống mã cấp dưới để thấy kiểu “à, phụ thuộc này dùng
eval()này” hoặc “nó có truy cập mạng này”Ứng dụng di động thì bị ép quyền hạn, nên có lẽ nhà phát triển cũng phải có khả năng chỉ cho phép một số tính năng nhất định thay vì nhận nguyên cả đống khả năng
Tôi không muốn khái quát hóa, nhưng có vẻ đặc biệt là cộng đồng phát triển AI ưu tiên sự tiện lợi hơn mọi cân nhắc khác
Ví dụ, việc dự án tự động tải model lớn ở lần chạy đầu tiên gần như đã thành chuẩn
Thường thì có thể tắt được, nhưng vì có các lớp code ăn sâu qua nhiều thư viện nên việc tìm đúng tham số thật sự rất đau đầu
Việc có thể bắt đầu quá dễ với những thứ phức tạp, mà phần lớn vẫn giống đồ chơi, là điều hay, nhưng bầu không khí dễ dãi này khá khó chịu
Bước giải quyết vấn đề đầu tiên dường như lúc nào cũng là “
pip install …”, và một số môi trường, chẳng hạn MacOS, còn không virtualize tốt quyền truy cập GPUTuần này tôi đang tự hỏi liệu dùng uv để quản lý phiên bản Python có phải ý hay không
Trên website [1] có ghi “Python không cung cấp binary chính thức để phân phối, vì vậy uv sử dụng các bản phân phối từ dự án Astral python-build-standalone”
Nó trỏ đến repo GitHub này https://github.com/astral-sh/python-build-standalone, và ở đó lại nhắc tới https://gregoryszorc.com/docs/python-build-standalone/main/r...
Nếu tôi hiểu đúng thì có vẻ mã nguồn để build Python không được lấy trực tiếp từ python.org, và tôi không chắc mức độ an toàn của điều này
Tôi cũng có cùng lo ngại với asdf [2], nhưng asdf dùng pyenv [3], và bên đó có cảm giác gần chính thống hơn
Có ai giải thích được công cụ nào giữa uv và asdf tốt hơn và an toàn hơn cho việc cài Python không?
[1] https://docs.astral.sh/uv/guides/install-python/
[2] https://github.com/asdf-community/asdf-python
[3] https://github.com/pyenv/pyenv/tree/master/plugins/python-bu...
Ngay từ đầu thì còn lấy từ đâu khác được nữa
[1]: https://github.com/astral-sh/python-build-standalone/blob/a2...
uvvàcpython. Quy trình của họ vững, phản ứng nhanh, và giờ cũng có kha khá tài trợĐiều khiến tôi lo là những thứ như
mdformat, tức formatter được dùng rộng rãi nhưng chủ yếu do một người duy trì lúc rảnh, hoặc một phụ thuộc cực kỳ đặc thù đã nhiều năm không cập nhật và nằm sâu 3 tầng trong cây phụ thuộcTôi không muốn khóa mọi bản cập nhật rồi duyệt thủ công trên các ứng dụng đang phát triển tích cực, nhưng với ứng dụng nghiêm túc thì giờ điều đó bắt đầu trông như bắt buộc
Trong lúc đó tôi đi lấy các API key khỏi file
.envkhông mã hóa vậyNếu bị dính ở một webapp tiêu dùng quy mô lớn thì đáng xấu hổ nhưng còn hiểu được, chứ mất hàng trăm tới hàng nghìn đô chỉ vì một phụ thuộc gián tiếp của repo demo đồ chơi tình cờ nằm trên cùng host và cùng hệ thống thì đau quá
Có ai biết nếu key bị đánh cắp theo cách này thì OAI hay Anthropic có hoàn tiền không? Hay đó được xem là lỗi của người dùng?
Tôi không rõ mức độ rủi ro khác nhau bao nhiêu giữa việc họ tự build Python binary hay ai khác build
Dạo này phần lớn
pip installcủa tôi là do Claude Code gợi ý rồi tôi chỉ việc nhấn EnterModel được huấn luyện bằng dữ liệu từ vài tháng trước nên nó không thể biết tuần này cái gì vừa bị xâm nhập
Thành ra tôi đã tạo ra bộ lọc tệ nhất có thể để đánh giá xem “gói này hiện giờ có an toàn không”
Ý bạn là để Claude Code đề xuất phần mềm để cài từ internet rồi cứ thế cài theo
Tôi chưa từng nghe ai nói Claude Code hay bất kỳ LLM nào là bộ lọc để đánh giá “gói này hiện giờ có an toàn không”, và xét theo chính lý do bạn nêu ra thì đó có vẻ là một heuristic cực kỳ tệ
setup.pysẽ chạy gì trên máy của tôiVì không có thứ gì thật sự kiểm tra gói trước khi thực thi
Điều cần là công cụ lấy metadata trước khi chạy để xem có hook nào trong đó
Claude Code được cập nhật gần như mỗi ngày, đôi khi còn nhiều lần một ngày
Nếu một ngày nào đó Anthropic bị xâm nhập thì tất cả chúng ta sẽ lãnh đủ
Nhưng dạo này mọi thứ đều theo kiểu YOLO
Tôi thấy tin nhắn này trên GitHub được đăng ngày 20 tháng 4 và hơi bối rối
"deependujha hi @thebaptiste, thanks for inquiring. Release of 2.6.2 is blocked due to some internal reasons. Will notify once release is made."Nếu nghĩa là từ lúc đó họ đã biết vấn đề mà đến giờ vẫn không cảnh báo thì tôi sẽ thấy rất khó chịu
Mong ai biết rõ hơn có thể giải thích cho minh bạch
https://github.com/Lightning-AI/pytorch-lightning/issues/216...
Trước đó không có bản phân phối bị ảnh hưởng, và chúng tôi cũng không biết việc rò rỉ
Bản phát hành gốc trên GitHub không có vấn đề gì, nhưng đã được gỡ xuống để tránh gây nhầm lẫn