Join our Newsletter — 33% off our NHI Course
Home› Guides› How to Find ssh authorized keys across a…
Guide Secrets Management

How to Find ssh authorized keys across a server fleet

PDF for newsletter subscribers · free to read online

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 11 November 2026 15 min read
On this page

Every line in an authorized_keys file is a standing access grant, and on most server fleets nobody can say how many there are, who owns them or which ones still get used. Keys are added by hand during an outage, baked into images, pushed by old configuration management roles and, in intrusions, planted for persistence. This runbook shows how to build a complete, read-only inventory of authorised SSH keys across Linux and Unix servers: where sshd actually looks for keys, how to collect and fingerprint them at scale, how to tie each key to last use, and how to remove keys safely with a rollback. It is for infrastructure, platform and identity teams preparing a clean-up, an audit or a move to SSH certificates. For the wider key lifecycle, see the SSH Key Management Guide.

This is an independent guide from NHI Mgmt Group, based on the OpenSSH manual pages (sshd_config(5), sshd(8), ssh-keygen(1)) and NIST IR 7966 as of November 2026. Options differ between OpenSSH versions and vendor builds, so confirm against the manual on your own hosts.

Key takeaways

  • Ask sshd where it looks, do not assume. AuthorizedKeysFile defaults to .ssh/authorized_keys .ssh/authorized_keys2, but it can be changed, set per user in a Match block, or replaced by an AuthorizedKeysCommand. Read the effective configuration with sshd -T.
  • Collect every account, not just humans. Root, service accounts and accounts with nologin shells can still hold keys; the second file, authorized_keys2, is often forgotten.
  • The fingerprint is the join key. Record a SHA256 fingerprint per key line, then match it to sshd login records, which log the same fingerprint, to separate used keys from dead ones.
  • Options matter as much as the key. A key without from=, command= or restrict grants a full shell from anywhere; a cert-authority line trusts every certificate that CA signs.
  • Remove in stages. Comment out or move a key with a recorded backup first, watch for failed logins, then delete. Restrict who can write key files so the sprawl does not return.

When you need this

  • Audit or access review: auditors ask who can log in to production as root or as an application account. Authorised keys bypass directory groups and are invisible to most identity reviews. NIST IR 7966 notes that SSH user keys had received little security attention and treats the inventory as the first step of any key management programme.
  • Leaver or vendor exit: a departed administrator or a terminated contractor may have left keys on dozens of hosts. Deleting their directory account does nothing to a key in /root/.ssh/authorized_keys.
  • Suspected compromise: adding a key is ATT&CK technique T1098.004 SSH Authorized Keys, a simple persistence method. In the Cursor Marketplace Extension Compromise 2026 the tampered update tried to add an attacker key to authorized_keys with an innocuous-looking comment. Use the SSH Key Compromise Response Playbook alongside this runbook.
  • Before moving to certificates: you cannot switch servers to TrustedUserCAKeys safely until you know which automation depends on plain keys. See the SSH Protocol and Certificate Authority Guide.

Before you start

Know every place sshd can take a trusted key from. The table lists the sources and how to read each one without changing anything.

Trust sourceConfigured byDefaultHow to read it
Per-user key filesAuthorizedKeysFile (tokens %h home, %u user, %U UID, %%).ssh/authorized_keys .ssh/authorized_keys2, relative to homeResolve the paths for every account from sshd -T output and getent passwd
Key lookup programAuthorizedKeysCommand and AuthorizedKeysCommandUserNoneFind the program and its backend (directory attribute, API); inventory keys there, not on disk
CA-trusted certificatesTrustedUserCAKeys, optionally AuthorizedPrincipalsFileNone configuredRecord the CA public keys and principal mappings; individual certificates are not on the server
CA lines inside key filescert-authority option on an authorized_keys lineNot presentFlag during parsing: one line trusts every certificate the CA signs for that account
Revocation listRevokedKeys (plain list or KRL)NoneTest collected keys with ssh-keygen -Q -f <krl>

Two behaviours affect what you find. With StrictModes yes (the default), sshd ignores a key file if the file, ~/.ssh or the home directory is writable by other users, so a key can exist on disk and not work; record it anyway, because a later permission fix would activate it. And AuthorizedKeysFile none means sshd reads no key files at all, which is common on hosts that use only certificates or a lookup command.

Prepare a read-only collection identity (an inventory agent, a configuration management fact, or a root-run collector with no write actions) and agree where the output lands. The inventory contains public keys only, but it maps who can reach which host, so store it as sensitive.

Step-by-step

Steps 1 to 5 are read-only. Step 6 changes access and is reversible. Step 7 is destructive.

  1. Read the effective sshd configuration on each host. sshd -T checks the configuration file, prints the effective configuration and exits, with the same extra checks as sshd -t. Because Match blocks can change AuthorizedKeysFile per user, run it once per account class with a connection spec:
    sshd -T | grep -Ei '^(authorizedkeysfile|authorizedkeyscommand|authorizedkeyscommanduser|trustedusercakeys|authorizedprincipalsfile|revokedkeys|strictmodes|permitrootlogin)'
    sshd -T -C user=root,host=localhost,addr=127.0.0.1 | grep -i '^authorizedkeysfile'
    The -C keywords are addr, user, host, laddr, lport and rdomain. Record the output per host; a fleet where most hosts use the default and a few use a custom path is a common source of missed keys.
  2. List every account and its home directory. getent passwd returns local and directory accounts the host can resolve. Keep root, system and service accounts in scope: a nologin shell stops an interactive shell but a key with a forced command, or one used for port forwarding, can still be useful to an attacker. See the Linux Service Accounts and Keytab Management Guide for the account side.
  3. Collect each key line with its context. For every account, expand the configured paths and read each file that exists. Store one record per key line with these fields: host, account, UID, file path, file owner and mode, options, key type, key, comment, and a hash of the whole line. Lines that are empty or start with # are ignored by sshd; keep commented keys in a separate list because they are often re-enabled by mistake. If you run osquery, its authorized_keys table returns uid, algorithm, key, options, comment and key_file, and the project's example query is select * from users join authorized_keys using (uid). Check that it reads any custom AuthorizedKeysFile path you found in step 1 before relying on it alone.
  4. Fingerprint every key. ssh-keygen -l -f <file> shows fingerprints, and -E selects the hash (sha256 is the default, md5 is available for old tooling). Run against an authorized_keys file, it prints one fingerprint per key line. Store the SHA256 value; it is how you will match keys across hosts and against logs.
    ssh-keygen -l -E sha256 -f /home/deploy/.ssh/authorized_keys
    If the host uses RevokedKeys or you keep a central KRL, test the collected files: ssh-keygen -Q -f revoked.krl authorized_keys returns zero only if no key in the file is revoked.
  5. Join keys to last use. At the default LogLevel INFO, sshd records each successful public key login with the account, source address, key type and the key fingerprint, hashed with FingerprintHash (default sha256). Pull these records from your log pipeline (the journal or /var/log/auth.log or /var/log/secure, depending on the distribution) for a window that covers your slowest automation, then mark each inventoried fingerprint with its last login date and sources. Certificate logins log the certificate's key and CA, so keep them separate. The Linux Logging and auditd for Defenders Guide covers getting these logs off the host.
  6. Classify and disable. Use the triage table below. For each key to remove, save the exact line and file metadata to your change record, then comment the line out or move it to a quarantine file outside the configured path. This is reversible in seconds. Watch for Failed publickey and service errors for an agreed period.
  7. Delete and lock down. After the watch period, delete quarantined lines through configuration management, not by hand, so the change is recorded and repeatable. Then decide who may write key files (see Hardening afterwards).

Triage table

FindingRiskDefault action
Key on root or a shared admin account, no optionsFull root shell from anywhere, unattributableReplace with named accounts and logged sudo; remove after owners confirm
Same fingerprint on many hosts and many accountsOne stolen private key opens the fleetFind the holder; split into per-purpose keys with from= and command=
No login seen in the log windowStanding access nobody needsDisable (step 6); delete after the watch period
Key in authorized_keys2Often missed by reviews and toolingMove valid keys to the primary file; remove the second path from AuthorizedKeysFile
cert-authority line in a user fileTrusts any certificate from that CA for the accountMove CA trust to TrustedUserCAKeys with principals, or remove
Weak or legacy key (small RSA, DSA)Weak cryptography; DSA support is gone in recent OpenSSHReissue as Ed25519 or a FIDO-backed key
File writable by group or othersIgnored today under StrictModes, active after a permission fix; possible tamperingInvestigate the writer, fix ownership, then review the keys
Comment naming a person who has left, or a generic comment on a recent additionLeaver access or planted persistenceTreat as a possible incident; check file change history first

Reading the options field

The options before the key type decide what a key can do. Use these to score each line.

OptionEffect (sshd(8))What its absence means
restrictTurns on all restrictions: no port, agent or X11 forwarding, no PTY, no ~/.ssh/rc, including restrictions added in future versionsForwarding and interactive use are allowed
from="pattern-list"Requires the client host name or address (CIDR allowed) to matchThe key works from any source
command="..."Runs this command whenever the key is used, ignoring the client's commandThe holder chooses what to run
expiry-time="timespec"Rejects the key after the given date and timeThe key never expires
principals= with cert-authorityLimits which certificate principals are acceptedAny principal the CA signs
verify-requiredRequires user verification (for example a PIN) on FIDO keysTouch only, or nothing for non-FIDO keys
permitopen, permitlistenLimit local and remote forwarding destinationsAny destination if forwarding is allowed

Choosing a collection method

MethodSuitsWatch out for
Endpoint query agent (for example osquery)Large fleets that already run an agent; scheduled, repeatable resultsCustom key paths and AuthorizedKeysCommand backends may not be covered
Configuration management facts or an ad hoc read-only runEstates managed by one tool; quick first passHosts outside management are the ones most likely to hold stray keys
Vulnerability or compliance scanner with credentialsMixed estates with existing scan coverageThe scanner's own account is a key holder; scope and monitor it
Dedicated SSH key management productThousands of hosts, regulated environments, planned move to certificatesCost and agent rollout; still validate against sshd -T on a sample

A small team with a few dozen servers can do the whole job with a read-only script run from configuration management and a spreadsheet keyed on fingerprint. A large estate needs a scheduled collector feeding the NHI inventory, a log join that runs daily, and owners recorded per key. Network devices, appliances and cloud instance metadata also hold SSH keys and need their own collection route; see the NHI Inventory Reconciliation guide for merging sources.

Verify it worked

  • Coverage: the number of hosts with a completed collection equals the number of hosts in your asset inventory that run sshd.
  • Path completeness: every distinct AuthorizedKeysFile and AuthorizedKeysCommand value seen in step 1 has a collection method.
  • Spot check: on a sample of hosts, compare the inventory against a manual read of each key file and the sshd -T output.
  • Removal check: after step 7, re-run collection; removed fingerprints must not reappear, and no new Accepted publickey records should show them.

Detection and measurement

Inventory once is not enough: keys come back unless changes are watched. Monitor writes to key files and sshd configuration (an auditd watch or file integrity monitoring on /root/.ssh, home .ssh directories and /etc/ssh/sshd_config and its include directory), and alert on any new fingerprint that has no change ticket. The Linux File Integrity Monitoring Guide covers the tooling. Useful metrics:

  • Authorised keys per host and per account: trend over time; spikes point to sprawl or tampering.
  • Keys with an owner: percentage of fingerprints mapped to a named person or system owner, target 100%.
  • Unused keys: fingerprints with no login in the window, trending to zero.
  • Unrestricted automation keys: non-human keys without from= and command= or restrict.
  • Root keys: count of keys on UID 0 accounts, target as close to zero as operations allow.
  • Unapproved additions: new fingerprints per week without a change record, and mean time to remove them.

Rollback and common errors

  • Automation breaks after removal: restore the saved line from the change record to the original file with the original owner and mode (user read and write only, as sshd(8) recommends), then check the job's log. Add the key to the inventory with an owner and restrictions before closing.
  • Key restored but still refused: check StrictModes ownership and permissions on the file, ~/.ssh and the home directory, and check whether a RevokedKeys list now contains it. If the RevokedKeys file itself is unreadable, sshd refuses public key authentication for all users.
  • Lockout of administrators: keep console or out-of-band access and a break-glass path tested before removing keys on root or admin accounts.
  • Breaking sshd with a config edit: run sshd -t before reloading. If you add an AuthorizedKeysCommand, set AuthorizedKeysCommandUser too: sshd refuses to start without it.

Common failure patterns

  • Scanning only ~/.ssh/authorized_keys: custom AuthorizedKeysFile paths, authorized_keys2 and lookup commands are skipped, so the riskiest keys are missed.
  • Skipping service and system accounts: the inventory covers people and misses the automation keys with the widest reach.
  • Treating the comment as identity: sshd does not use the comment field; anyone who can write the file can write any comment. Use fingerprints and change records.
  • Deleting without a usage window: quarterly or annual jobs fail weeks later and the key is restored without restrictions.
  • Clean-up without lock-down: users can still edit their own key files, so sprawl returns within months.
  • Ignoring the private key side: removing a public key does not tell you where its private key lives. Search for identity keys on build servers and jump hosts too; see How to find unused GitHub deploy keys and SSH keys for the Git side.

Hardening afterwards

  • Root-owned key locations: point AuthorizedKeysFile at a root-owned path per user (for example under /etc/ssh/authorized_keys/%u) managed only by configuration management, so users and compromised processes cannot add keys.
  • Restrict automation keys: every non-human key gets restrict, from= and command=, and an expiry-time where the job allows.
  • Move people to certificates: short-lived user certificates signed by a CA listed in TrustedUserCAKeys remove most per-host keys. See the OpenSSH Server Hardening Guide.
  • Limit root login: set PermitRootLogin to no or forced-commands-only for reviewed exceptions. See Root, sudo and superuser accounts on Linux and Unix.

Framework mapping

FrameworkItemHow this runbook supports it
NIST CSF 2.0PR.AA-01, PR.AA-05Credentials for services and users are managed; access is reviewed against least privilege
NIST CSF 2.0DE.CM-09Monitoring of key file changes and key use
NIST SP 800-53 Rev. 5AC-2, IA-5, SC-12Account review, authenticator management, key management
NIST SP 800-53 Rev. 5CM-8, AU-12Component inventory; login audit records used to find unused keys
MITRE ATT&CKT1098.004, T1021.004, T1552.004Planted keys, SSH lateral movement, stolen private keys

Practitioner checklist

  • Run sshd -T (with -C for each account class) on every host and record key-related settings.
  • Collect key files for every account in getent passwd, including root, service accounts and authorized_keys2.
  • Inventory keys served by any AuthorizedKeysCommand backend and any CA in TrustedUserCAKeys.
  • Store one record per key line with host, account, path, options, type, comment and SHA256 fingerprint.
  • Join fingerprints to sshd login records over a window that covers the slowest automation.
  • Assign an owner to every key and flag shared, unrestricted and root keys first.
  • Disable by quarantine with a saved copy, watch for failures, then delete through configuration management.
  • Move key files to root-owned paths and monitor writes to key files and sshd configuration.
  • Re-run collection on a schedule and alert on new fingerprints without a change record.

Standards and references

Related NHI Mgmt Group resources: SSH Key Management Guide, SSH Key Compromise Response Playbook, How to Find credentials in cron jobs and scheduled tasks, NHI Dormancy Detection.

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 11 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.