Sửa lỗi SSH 'Permissions for private key are too open' trên Windows

beginner🪟 Windows2026-03-17| Windows 10/11, OpenSSH (tích hợp sẵn hoặc Git for Windows), PowerShell / CMD

Error Message

Permissions for 'id_rsa' are too open. It is required that your private key files are NOT accessible by others.
#windows#ssh#permission#private-key

Lỗi Xảy Ra

Bạn chạy lệnh SSH — kết nối đến server từ xa, clone repo Git, hoặc deploy code — và nhận được thông báo này:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions for 'id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/c/Users/YourName/.ssh/id_rsa": bad permissions
Permission denied (publickey).

SSH từ chối đọc key. Kết nối chết ngay lập tức.

OpenSSH kiểm tra quyền file trước khi nạp bất kỳ private key nào. Nếu một tài khoản khác có thể đọc được file đó, SSH coi key đã bị lộ và từ chối tiếp tục. Trên Linux, một lệnh là xong: chmod 600 ~/.ssh/id_rsa. Windows dùng NTFS ACL thay vì Unix permission bits, nên cách sửa có khác đôi chút.

Nguyên Nhân Trên Windows

Việc sao chép private key vào Windows thường là lúc mọi thứ đi sai hướng. Dù file đến từ download, USB hay máy khác, nó thường kế thừa quyền từ thư mục cha. Điều đó có nghĩa là nhóm Users, SYSTEMAdministrators đều có thể đọc file. OpenSSH nhìn thấy điều đó và từ chối nạp key.

Sửa Bằng icacls Trong PowerShell

icacls là công cụ phù hợp cho việc này. Mở PowerShell (không cần quyền admin) và chạy:

# Điều chỉnh đường dẫn nếu key của bạn ở nơi khác
$key = "$env:USERPROFILE\.ssh\id_rsa"

# Bước 1: Xóa tất cả quyền được kế thừa
icacls $key /inheritance:r

# Bước 2: Xóa quyền của các nhóm rộng
icacls $key /remove "NT AUTHORITY\SYSTEM"
icacls $key /remove "BUILTIN\Administrators"
icacls $key /remove "BUILTIN\Users"

# Bước 3: Cấp quyền đọc chỉ cho tài khoản của bạn
icacls $key /grant:r "${env:USERNAME}:R"

Chạy theo thứ tự. Mỗi lệnh loại bỏ một lớp quyền — lệnh cuối thêm lại quyền của bạn, chỉ đọc.

Phiên bản một dòng

Muốn gộp lại một dòng? Nối tất cả lại với nhau:

icacls "$env:USERPROFILE\.ssh\id_rsa" /inheritance:r /remove "NT AUTHORITY\SYSTEM" /remove "BUILTIN\Administrators" /remove "BUILTIN\Users" /grant:r "${env:USERNAME}:R"

Cách Thay Thế: Dùng PowerShell ACL Objects

icacls đủ dùng cho hầu hết trường hợp. Nếu bạn đang viết script thiết lập máy hoặc cần kiểm soát chi tiết hơn, bạn có thể dùng trực tiếp các lớp System.Security.AccessControl của .NET:

$key = "$env:USERPROFILE\.ssh\id_rsa"

# Nạp ACL hiện tại
$acl = Get-Acl $key

# Vô hiệu hóa kế thừa và xóa các mục được kế thừa
$acl.SetAccessRuleProtection($true, $false)

# Xóa tất cả quy tắc truy cập hiện có
$acl.Access | ForEach-Object { $acl.RemoveAccessRule($_) }

# Thêm quy tắc: người dùng hiện tại chỉ được đọc
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
    $env:USERNAME, "Read", "Allow"
)
$acl.AddAccessRule($rule)

# Áp dụng ACL đã cập nhật lại cho file
Set-Acl -Path $key -AclObject $acl

Write-Host "Đã cập nhật quyền cho $key"

Sửa Qua Giao Diện Đồ Họa (File Explorer)

Không muốn dùng dòng lệnh? File Explorer cũng làm được:

  • Chuột phải vào id_rsa trong File Explorer → Properties
  • Chuyển sang tab Security → nhấp Advanced
  • Nhấp Disable inheritance → chọn Remove all inherited permissions
  • Nhấp AddSelect a principal → nhập tên tài khoản Windows của bạn → OK
  • Chỉ chọn ReadOKApply

Sau khi xong, chỉ tài khoản của bạn mới xuất hiện trong danh sách quyền.

Kiểm Tra Kết Quả

Trước khi thử SSH, xác nhận ACL trông đúng chưa:

icacls "$env:USERPROFILE\.ssh\id_rsa"

Bạn muốn chỉ thấy tên người dùng của mình:

C:\Users\YourName\.ssh\id_rsa YourName:(R)

Successfully processed 1 files; Failed processing 0 files

Giờ thử kết nối:

ssh -T git@github.com

Hoặc kết nối trực tiếp đến server của bạn:

ssh -i ~/.ssh/id_rsa user@your-server.com

Không còn cảnh báo nữa. Nếu SSH vẫn thất bại lúc này, đó sẽ là lỗi xác thực — không phải lỗi quyền — có nghĩa là key đã được nạp thành công.

Sửa Cho Người Dùng Git Bash / WSL

Bên trong WSL hoặc Git Bash, nếu key nằm trong filesystem WSL, chmod hoạt động bình thường:

# Bên trong WSL hoặc Git Bash
chmod 600 ~/.ssh/id_rsa
chmod 700 ~/.ssh

Truy cập key theo đường dẫn Windows từ WSL (như /mnt/c/Users/YourName/.ssh/id_rsa)? chmod sẽ không ảnh hưởng đến NTFS ACL. Dùng icacls từ cửa sổ PowerShell cho những trường hợp đó.

Áp Dụng Cho Tất Cả Key Cùng Lúc

Có nhiều private key trong thư mục .ssh? Sửa tất cả trong một lần:

Get-ChildItem "$env:USERPROFILE\.ssh" -File | Where-Object { $_.Name -notmatch '\.pub$|config|known_hosts' } | ForEach-Object {
    $path = $_.FullName
    icacls $path /inheritance:r /remove "NT AUTHORITY\SYSTEM" /remove "BUILTIN\Administrators" /remove "BUILTIN\Users" /grant:r "${env:USERNAME}:R"
    Write-Host "Đã sửa: $path"
}

Lưu Ý

  • Đặt quyền ngay khi tạo key. Chạy ssh-keygen trên Windows sẽ tự động đặt ACL đúng. Vấn đề hầu như luôn xuất phát từ việc sao chép key giữa các máy.
  • Giữ key trong thư mục profile của bạn. Các thư mục dùng chung hoặc thư mục hệ thống liên tục kéo theo quyền rộng. Hãy dùng C:\Users\YourName\.ssh\.
  • Chuyển đổi quyền giữa các nền tảng. Nếu bạn làm việc cả trên Windows lẫn Linux và cần hiểu chmod 600 tương ứng với ACL như thế nào, Unix Permissions Calculator trên ToolCraft trực quan hóa điều đó — chạy hoàn toàn trên trình duyệt, không gửi dữ liệu đi đâu.
  • Public key không cần quyền chặt. id_rsa.pub để đọc được là ổn. Nhưng nhân thể, hãy xác nhận toàn bộ thư mục .ssh chỉ thuộc về tài khoản của bạn.

Related Error Notes