DevSecOps

Locking Your ssh-Agent Exposed Local-Only Keys Until OpenSSH 10.5: A Quiet Failure of Security Assumptions

# Locking Your ssh-Agent Exposed Local-Only Keys Until OpenSSH 10.5: A Quiet Failure of Security Assumptions

On August 11, 2026, OpenSSH shipped release 10.5, and with it a fix for a bug that quietly inverted the security model of ssh-agent for an entire month between the 10.4 release in July and the 10.5 release in August. The bug, in plain terms: if you locked your ssh-agent — the state where it refuses to sign anything until you unlock it — the lock stopped distinguishing between requests coming from your local machine and requests coming through an agent-forwarded session from a remote machine. Operations that were designed to be local-only became remote-performable when the agent was locked. The fix shipped in 10.5p1, and every operator who uses agent forwarding — which is most operators who SSH through jump hosts — needs to understand what this bug did, what it didn't do, and how to verify they're no longer exposed.

The bug was first reported through AI-assisted bug hunting — a category of vulnerability disclosure that is itself becoming a meaningful slice of OpenSSH's intake. The OpenSSH project has publicly noted that AI-assisted reports are accelerating the cadence of disclosures, but that they still require human threat modeling, testing, and triage before they ship as security releases. 10.5 is a direct consequence of that pipeline working: an AI noticed the inconsistency, a human verified the impact, and a release was cut.

What the bug actually did

The mechanism is specific enough that operators need to understand it. The ssh-agent has a concept of "locking" — when locked, the agent refuses to perform any signing operation until the user unlocks it with their passphrase. This is the standard defense when you walk away from your laptop: lock the screen, and the agent stops signing new requests. The threat model assumes that even if an attacker has compromised your running session — through X11 forwarding, through a malicious script, through any of the usual vectors — they cannot use your agent while it's locked.

That threat model broke in 10.4. The session-bind@openssh.com extension — which is the mechanism ssh uses to distinguish local requests from requests that arrived through agent forwarding — interacts with the locking state in a way that 10.4 implemented incorrectly. Specifically, when the agent was locked, the session-bind check was being skipped rather than enforced. The result: a request that arrived through an agent-forwarded connection could ask the agent to perform operations that, per the design, should only be available to local requests.

The "operations that should only be local" include two particularly nasty ones:

1. **Adding PKCS#11 tokens to the agent.** This is the mechanism for adding smart cards, HSMs, and security keys as providers. If a remote request can add a PKCS#11 provider, the attacker can route signing operations through their own provider without your awareness.

2. **Using keys with destination restrictions.** OpenSSH supports keys that are restricted to specific destination hosts or specific commands. If a remote request can use a destination-restricted key for a non-destination host, the entire concept of per-key destination restrictions collapses.

Neither of these is a "sign this key for me" operation that would normally be blocked by locking. They are configuration operations that the locking model never explicitly addressed, because the locking model assumed that local vs. remote distinction was enforced at a different layer. The bug was that, in 10.4, that layer was bypassed.

What 10.5 fixes (and what it doesn't)

OpenSSH 10.5p1 contains three distinct security fixes. The ssh-agent locking bug is the most discussed, but the release also addresses two other issues that operators should review.

**The agent locking fix.** When the agent is locked, the session-bind check is now properly enforced. Remote-forwarded requests cannot bypass the lock by skipping the local/remote distinction. The fix is straightforward: the code path that handles a locked agent now applies the same session-bind validation that an unlocked agent would apply. The behavior matches the documented threat model.

**The `restrict` keyword in authorized_keys.** Before 10.5, the `restrict` keyword in `authorized_keys` was supposed to apply to tunnel forwarding (the `-w` flag for SSH tunnel devices) but did not. In 10.5, this oversight is fixed — `restrict` now correctly disables tunnel forwarding for keys that include it. This is a smaller bug than the agent one, but for operators who rely on `restrict` to constrain what a compromised key can do, the prior behavior was a defense-in-depth gap.

**A use-after-free in the client when remote forwarding is added via the multiplexing socket.** Tracked separately (and with its own CVE identifier, CVE-2026-73282, per third-party advisories), this is a memory safety bug in `ssh` itself when certain remote-forwarding operations are concurrent. The fix prevents a `realloc` use-after-free that could potentially be leveraged for arbitrary code execution in the client. The exploitation complexity is high, but the fix is included in 10.5p1 and operators should not delay the upgrade.

There is also a feature addition that security teams will appreciate: `ssh-keygen` now supports setting or clearing touch-required and verify-required flags on FIDO private keys during passphrase reset. This makes it easier to manage the security posture of hardware-backed keys without having to regenerate them.

Why AI-assisted disclosure is now structural

The OpenSSH release notes for 10.5 are notable not just for what they fix but for the implicit acknowledgment that AI-assisted bug reports are now a meaningful slice of the project's intake. The disclosure pipeline — AI notices something, human verifies, project ships fix — is producing more releases per year than the historical cadence. This is good for the security of the ecosystem in aggregate, but it also means operators need to expect more frequent OpenSSH upgrades as the new normal.

For DevOps teams that manage OpenSSH at scale — across fleets of bastion hosts, jump hosts, CI runners, and developer workstations — the operational implication is that quarterly upgrade cycles are no longer adequate. OpenSSH now ships security fixes on the order of weeks-to-months, not years. The teams that have build pipelines capable of rebuilding OpenSSH against their base images in days, not weeks, are the teams that will keep up.

What to do this week

**1. Upgrade to 10.5p1 immediately on every system where ssh-agent runs.** That includes developer laptops, CI runners, jump hosts, and any bastion that forwards agent connections. The bug only affects systems that ran 10.4 with an agent that could be locked, but if your fleet is heterogeneous, the safest assumption is that some subset was exposed.

**2. Audit your authorized_keys for `restrict` keyword usage.** If you have keys with `restrict` that you expected to disable tunnel forwarding, verify in 10.5 that the behavior now matches your expectation. For keys without `restrict`, consider whether they should have it — destination restrictions, command restrictions, and tunnel forwarding restrictions are defense-in-depth controls that reduce the blast radius of a compromised key.

**3. Review your FIDO key management.** The new ssh-keygen flags for touch-required and verify-required make it easier to harden hardware-backed keys. If you have FIDO keys in your environment, set the appropriate flags during the next maintenance window.

**4. Check your client for the multiplexing use-after-free exposure.** CVE-2026-73282 (the `realloc` use-after-free in client remote forwarding via multiplexing socket) is fixed in 10.5p1. If your SSH clients connect through multiplexing sockets — common in CI runners and connection-pooling tools — verify that all client installations are on 10.5p1 or later.

**5. Reset the lock state on any agent that was running 10.4.** If you had an ssh-agent running 10.4 and locked it during the exposure window, the safest assumption is that any forwarded connection during that window could have probed the bug. Reset the agent, rotate any keys that were loaded during the exposure period, and review your authorized_keys on remote hosts for unexpected entries.

**6. Document the exposure window in your change log.** If you have compliance obligations around SSH key management, the August 11 fix date and the 10.4 release window are the boundaries of the exposure window. Your audit trail should show when you upgraded and what you did to verify.

The structural lesson

The OpenSSH 10.5 disclosure is a case study in how security boundaries fail in subtle ways. The bug was not in the cryptographic primitives, not in the protocol, and not in the obvious place. It was in the interaction between two features — agent locking and session-bind — that each worked correctly in isolation but together produced an inverted security model. This is the category of bug that AI-assisted code review is unusually good at finding, because the failure mode requires tracing control flow across two features that are documented separately.

For your organization, the lesson is not "stop using SSH." The lesson is "expect more of these cross-feature failures as software complexity grows." Your test suites need to cover interactions, not just individual features. Your threat models need to assume that any two features can interact in ways their original designers did not anticipate. Your upgrade cadence needs to match the disclosure cadence — and for OpenSSH in 2026, that cadence is monthly.

For the full technical breakdown, the canonical sources are the OpenSSH 10.5 release notes, the project commit log for the fix, and the third-party CVE assignments for the additional fixes bundled in the release.

Practical upgrade playbook for OpenSSH at scale

Upgrading OpenSSH across a heterogeneous fleet — laptops, CI runners, production servers, bastion hosts — requires a playbook that goes beyond "run the package manager." Here is the operational approach that works in 2026 for organizations managing more than a few dozen OpenSSH installations.

**Inventory your version distribution.** Before you upgrade, know what you have. Most organizations discover they have a wider version spread than they assumed: developer laptops on the latest stable, production servers two minor versions behind, jump hosts on the long-term support branch, CI runners frozen on whatever version was current when the container image was built. Pull a version report from your configuration management database, your MDM, your container registry metadata, or your endpoint management tool. Group by version, by role, and by upgrade path.

**Prioritize by exposure surface.** Not every OpenSSH installation has the same risk profile. A bastion host that fronts a production environment serving millions of users has higher exposure than a CI runner that runs ephemeral jobs. A developer laptop that connects to multiple production systems has higher exposure than a build server that only runs unit tests. Prioritize the upgrade sequence by exposure surface, not by inventory order. The bastion goes first; the CI runner goes later.

**Test against your operational patterns.** Before rolling out to production, validate that your SSH client configurations still work. Things to verify: bastion host authentication chains, agent forwarding configurations, jump host sequences, FIDO key usage, and any custom SSH key types or certificate authorities your organization uses. The OpenSSH project maintains good backward compatibility, but version-specific features sometimes break in subtle ways.

**Roll out in waves.** Do not upgrade everything at once. Start with a small cohort (1-2% of fleet), monitor for issues, expand the cohort, monitor again. This is standard practice but worth re-stating because OpenSSH upgrades affect every SSH-using developer in your organization, and a broken upgrade that prevents anyone from connecting is much more visible than a broken upgrade that breaks a single service.

**Maintain rollback capability.** Your upgrade process should include a documented rollback to the previous version. Most package managers make this trivial (downgrade the package, restart the service), but the rollback must be tested before you need it. A rollback that fails because the previous package is not in your repository is not a rollback.

**Coordinate with your certificate authority lifecycle.** If you issue SSH certificates through an internal CA, the upgrade may interact with certificate validation. Verify that your CA certificates are still trusted by the upgraded OpenSSH version, and that any certificate extensions you rely on (source-address restrictions, forced-command specifications, etc.) are still respected.

For container-based CI environments, the upgrade is typically faster — rebuild the base image, roll forward the runner fleet. For VM-based or bare-metal infrastructure, the upgrade requires maintenance windows. For developer laptops, the upgrade is usually self-service through the OS package manager, but you should communicate the urgency and verify completion through your MDM.

Cross-feature security boundaries: the structural lesson

The OpenSSH 10.5 disclosure is a useful case study in what happens when two features that were each independently secure combine in a way that breaks the security model. The pattern shows up across the software industry, and your organization will encounter it in your own systems.

The general pattern: feature A was designed with security assumptions X, Y, Z. Feature B was designed with security assumptions P, Q, R. The two features interact in a way that the designers of either did not fully anticipate. The interaction produces a security boundary failure that neither feature's documentation explicitly addresses.

This pattern is particularly common in three categories: cryptographic libraries that expose primitive operations to higher-level APIs, network protocols with extensible negotiation phases, and access control systems that compose multiple authorization decisions. OpenSSH's agent locking interacting with session-bind extension is the third category — two authorization decisions composing in a way that bypasses one of them.

For your threat modeling practice, the implication is to look for these cross-feature boundaries explicitly. When you document a feature's security assumptions, ask: what other features in the system could violate these assumptions? When you design a new feature, ask: what security assumptions of existing features does this new feature depend on? When you review an incident report from another organization, ask: did the failure involve a cross-feature boundary?

The AI-assisted code review tools that are accelerating OpenSSH's disclosure cadence are particularly good at finding these cross-feature failures, because the failures require tracing control flow across the boundary between two features. This is exactly the kind of analysis that machine learning models with broad code context can do well. Expect more disclosures in this category across other open-source projects in 2026 and 2027, and build your detection and response capabilities to handle the cadence.

The agent locking failure as a teaching case

For security teams that run internal training, the OpenSSH 10.5 disclosure is a useful teaching example. The bug demonstrates several principles that are hard to illustrate with simpler examples.

**Security boundaries fail at boundaries.** The locked agent boundary was secure on the local side (no signing operations) and the forwarded session boundary was secure on the lock-state side (forwarded sessions cannot bypass the lock). The failure was in how the two boundaries interacted when an attacker submitted a request that triggered both checks. Each check passed individually; together, they produced a path that should not have existed.

**Threat models degrade over time.** The original ssh-agent threat model assumed that local vs. forwarded distinction would be enforced at the locking layer. That assumption held for years because the code path was straightforward. When new features (like session-bind extension) were added, the assumption silently broke. Threat models are living documents; they need to be revisited when adjacent features change.

**AI-assisted vulnerability discovery is here.** The fact that this bug was found by an AI-assisted review, not by a human auditor, is itself a lesson. The bug had existed since OpenSSH 10.4 (July 2026) and was found in time for 10.5 (August 2026) — one month of exposure. If a human auditor had found it, the timeline might have been similar, but the volume of AI-assisted reports means the overall disclosure cadence is faster than it would have been with human-only review.

**Patching cadence must match disclosure cadence.** For OpenSSH in 2026, that means monthly. For your organization, the right cadence depends on the disclosure rate of the software you depend on. Track your vendors' disclosure rates; let that drive your patching cadence, not an arbitrary quarterly cycle.

Use this case in your next security training. It is a concrete, recent, and operationally relevant example that engineers will recognize as affecting their daily work.