MEHDI.
RETURN_TO_INDEX

Fixing SSH Private Key Permissions on Windows

5 min read
#DevOps#SSH#Windows#PowerShell#Linux#Oracle Cloud

If you have ever tried to SSH into a Linux server from Windows and seen this error:

WARNING: UNPROTECTED PRIVATE KEY FILE!
Permissions for the private key are too open.
This private key will be ignored.
Permission denied (publickey).

you are not alone. The fix is straightforward once you understand why it happens, but the error message does not explain what to do.

Why OpenSSH Refuses the Key

OpenSSH enforces strict permission checks on private key files. On Linux, this means the file must be readable only by the owner (chmod 600 or 400). On Windows, the equivalent concept is the Access Control List (ACL).

The problem is that Windows file permissions work differently from Unix permissions. A freshly downloaded or copied private key file on Windows often inherits permissions from its parent directory, which means other users or groups (like Authenticated Users, SYSTEM, or your Microsoft account group) have read access. OpenSSH sees this as "too open" and refuses to use the key.

This is not a bug in OpenSSH. It is a security measure. A private key that anyone on the system can read is not truly private.

Inspecting Current Permissions

Open PowerShell and check the current permissions on your key file:

icacls "C:\Users\YourName\.ssh\my-key.pem"

You will likely see something like:

BUILTIN\Users:(F)
NT AUTHORITY\SYSTEM:(I)(F)
BUILTIN\Administrators:(I)(F)
DOMAIN\YourName:(I)(F)

The (I) means the permission is inherited from the parent directory. BUILTIN\Users:(F) means all users on the machine have full control over the file. This is exactly what OpenSSH does not want.

Removing Inheritance

The first step is to disable inheritance and remove the inherited rules:

$path = "C:\Users\YourName\.ssh\my-key.pem"

# Disable inheritance (converts inherited rules to explicit)
icacls $path /inheritance:r

# Grant full control only to the current user
icacls $path /grant:r "$($env:USERNAME):(F)"

# Remove all other users
icacls $path /remove "BUILTIN\Users"
icacls $path /remove "NT AUTHORITY\SYSTEM"
icacls $path /remove "BUILTIN\Administrators"

After these commands, only your user account should have access to the file. Verify:

icacls $path

The output should show only your username with (F) and no inherited rules.

The Correct Final State

The ideal permissions for a private key file on Windows:

YourName:(F)

That is it. One user, full control, no inheritance. If you need the key accessible to a service account, add that account explicitly, but do not grant access to broad groups like Users or Authenticated Users.

Common Mistakes

Granting permissions to Everyone or Users: This defeats the purpose. The whole point is that only one specific user can read the key.

Not removing inherited permissions: Adding a restrictive rule does not help if the permissive inherited rules still apply. You must disable inheritance first.

Applying the fix to the wrong file: If you have multiple key files or the key is in a non-standard location, make sure you are modifying the correct file. The -i flag in the SSH command tells you which key it is trying to use.

The SSH Command

Once the permissions are fixed, connect with:

ssh -i C:\Users\YourName\.ssh\my-key.pem ubuntu@your-server-ip

Replace ubuntu with the correct remote username. For Oracle Cloud instances, the default is usually ubuntu. For AWS, it might be ec2-user. For other providers, check the documentation.

If the key still does not work after fixing permissions, the problem might be elsewhere:

  • Wrong username: The server expects ubuntu but you are connecting as root
  • Wrong key: The public key on the server does not match this private key
  • Firewall or port: Port 22 is blocked, or the server uses a non-standard port
  • Key format: The key is in an unsupported format (OpenSSH requires PEM or the newer OpenSSH format)

Distinguishing Key Problems from Other Issues

If you get Permission denied (publickey), the SSH connection reached the server but authentication failed. This could be a key problem or a username problem. Try adding -v for verbose output:

ssh -v -i my-key.pem ubuntu@your-server-ip

The verbose output shows which key was offered, whether the server accepted it, and what authentication methods are available. If you see Offering public key followed by Server refused public key, the key was rejected. If you see No more authentication methods to try, the server does not accept any of the methods you offered.

If the connection times out instead of being refused, the problem is network-level (firewall, security group, port). That is a different issue entirely.

Precautions

A private key is a credential. Treat it like a password:

  • Do not share it via email, chat, or cloud storage
  • Do not commit it to a git repository
  • Do not leave it on a shared machine without proper permissions
  • Do not store it unencrypted on a USB drive
  • Generate a new key pair if you suspect the private key has been compromised

The permission fix is a one-time operation per key file. Once the ACLs are set correctly, OpenSSH will use the key without complaint.