Cabecera Penligente

ssh-keysign-pwn, The Linux fd theft bug behind CVE-2026-46333

ssh-keysign-pwn is the public name attached to CVE-2026-46333, a Linux kernel bug in the ptrace access-check path that can let an unprivileged local user read root-owned secrets such as SSH host private keys and /etc/shadow. It is not a classic remote OpenSSH vulnerability. It is not fixed by changing one SSH server setting. It is a kernel access-control failure that becomes dangerous when an attacker already has a low-privilege foothold on a vulnerable Linux host.

The short operational version is blunt: patch the kernel, reboot into the patched kernel or apply a trusted livepatch, then treat exposed SSH host keys and password hashes as potentially compromised if you have reason to believe the host was targeted. The upstream Linux fix is commit 31e62c2ebbfd, titled “ptrace: slightly saner get_dumpable() logic,” and NVD tracks the issue as CVE-2026-46333. The kernel commit changes the logic for tasks that no longer have a memory descriptor, caching the last user-dumpable state and requiring proper CAP_SYS_PTRACE authority where appropriate. (GitHub)

The bug matters because modern intrusions rarely stop at the first foothold. A web RCE running as www-data, a compromised CI job, a stolen developer shell account, an abused shared-hosting account, or a container workload with access to the host kernel may not start as root. A local kernel bug that reads root-owned secrets can turn that foothold into credential theft, host impersonation, password hash cracking, lateral movement, or a stronger privilege-escalation path.

The facts that matter first

QuestionPractical answer
Public namessh-keysign-pwn
CVECVE-2026-46333
Componente afectadoLinux kernel ptrace access-check logic, especially __ptrace_may_access() and dumpability handling
Main primitiveLocal unprivileged process can exploit an exit-time window to duplicate file descriptors from a privileged dying process
Public exploit targetsssh-keysign for SSH host private keys and chage para /etc/shadow, according to the public PoC repository
Remote exploit by itselfNo. The attacker needs local code execution or a local account
ImpactoRead access to root-owned secrets; possible credential theft, host-key compromise, offline password cracking, and post-compromise expansion
FixVendor kernel update containing the upstream logic fix, followed by reboot, or trusted livepatch where supported
Temporary controlsRestrict unprivileged ptrace where supported, isolate untrusted users, remove SUID bits from known targets only when operationally acceptable, and prioritize patching
Highest-risk systemsMulti-tenant Linux hosts, CI runners, Kubernetes and container build nodes, jump boxes, developer workstations with secrets, and shared academic or HPC shell systems

Qualys reported the underlying vulnerability to the kernel security contact, and the oss-security post from the Qualys Security Advisory team states that the issue had been fixed before public exploit code was referenced in the thread. The same thread notes that Jann Horn had proposed a related patch in 2020, which helps explain why several public write-ups describe the issue as a long-lived logic problem rather than a newly introduced helper-specific bug. (openwall.com)

Why ssh-keysign-pwn is not just an OpenSSH story

The name is easy to misread. ssh-keysign is part of OpenSSH, and the public exploit name points at it, but the vulnerable access-control decision lives in the Linux kernel. ssh-keysign is a useful target because it legitimately needs access to local SSH host private keys when host-based authentication is in use. The ssh-keysign(8) manual describes it as the helper used by ssh(1) to access local host keys and generate the signature required for host-based authentication, and it notes that it is disabled by default unless EnableSSHKeysign yes is set in the global client configuration. (man7.org)

That default does not make the kernel bug harmless. The public ssh-keysign-pwn PoC says its sshkeysign_pwn target pulls /etc/ssh/ssh_host_{ecdsa,ed25519,rsa}_key, and describes a sequence where ssh-keysign opens host key files before dropping privileges and then exits when EnableSSHKeysign=no, with file descriptors still open long enough to be raced. The same repository describes a second target, chage_pwn, that pulls /etc/shadow through the chage -l path. (GitHub)

That distinction is important for defenders. If the bug were only “host-based SSH authentication is enabled,” many teams could close it by checking one configuration value. CVE-2026-46333 is broader. The relevant class is “privileged or setuid-root programs that open sensitive files, then pass through a state where the process has no memory descriptor but still holds file descriptors.” ssh-keysign y chage are the public examples, not a mathematical proof that no other binaries can be shaped into targets.

The kernel bug, in plain terms

Linux has to decide when one process may inspect another. That decision appears in several places, including ptrace, /proc, process inspection, and newer pidfd-related interfaces. A central helper in this decision path is __ptrace_may_access().

The disputed concept is “dumpability.” In normal Unix/Linux security thinking, dumpability is tied to whether a process’s memory image may be dumped into a core file. Setuid programs and programs that handle privileged secrets are generally treated more carefully because dumping their memory could expose information that the calling user should not receive. NVD’s CVE-2026-46333 description states that dumpability is fundamentally about a task’s memory image, and that it makes little sense when the task no longer has an associated mm pointer. It also explains that ptrace_may_access() uses dumpability for other checks, including cases involving tasks without a virtual memory area. (NVD)

The vulnerable window appears during process exit. A privileged process can still hold open file descriptors after its memory descriptor has been detached. AlmaLinux summarized the bug cleanly: __ptrace_may_access() skipped its dumpable check when the target task’s mm was NULL; during do_exit(), Linux runs exit_mm() antes de exit_files(), creating a window where the process has no mm but still has file descriptors open. In that window, an unprivileged process under a matching UID can call pidfd_getfd(2) and copy open file descriptors from the dying process. (AlmaLinux OS)

The issue is subtle because every individual piece sounds reasonable in isolation. Processes need an exit sequence. File descriptors are closed separately from memory teardown. pidfd_getfd() exists for legitimate process-management use cases. ptrace access checks already consider credentials. The failure is in the combined state machine: a task without mm should not accidentally become easier to inspect if it still has sensitive file descriptors open.

Where pidfd_getfd turns a race into secret access

How CVE-2026-46333 Turns a Dying Privileged Process Into Secret Access

pidfd_getfd() is not the vulnerability. It is the interface that makes the impact easy to understand. The Linux manual page says pidfd_getfd() allocates a new file descriptor in the calling process that duplicates an existing file descriptor in another process referred to by a PID file descriptor. It also states that permission is governed by a PTRACE_MODE_ATTACH_REALCREDS ptrace access check. (man7.org)

That means the syscall is supposed to be protected by the same access-control family affected by the kernel bug. If the ptrace check incorrectly allows access during the dying-process window, the attacker does not need to open /etc/shadow directly. They only need to duplicate a file descriptor that a privileged helper already opened.

A simplified flow looks like this:

Escenario¿Qué ocurre?Por qué es importante
1Attacker runs as a local unprivileged userThe vulnerability is local; it needs code execution on the host
2A privileged helper is repeatedly triggeredPublic examples include ssh-keysign y chage
3The helper opens a root-owned sensitive fileThe helper may legitimately access files the user cannot open
4The helper exits or fails after privilege changesThe process enters a short lifetime window
5exit_mm() has run but exit_files() has nottask->mm == NULL, but fd table still exists
6Attacker calls pidfd_getfd() during the windowThe attacker attempts to duplicate a still-open fd
7The duplicated fd is read by the attacker processThe attacker sees contents of root-owned files without opening them directly

This is why detection cannot rely only on ordinary “who opened /etc/shadow?” thinking. The attacker may not perform a normal successful open of /etc/shadow; the sensitive file was opened by a legitimate privileged program, and the attacker copies the descriptor at the wrong time.

What the upstream patch changes

The upstream commit does not add a special case for ssh-keysign. It fixes the access-check semantics. The commit adds a user_dumpable bit to task_struct, stores the user-dumpable state when exit_mm() detaches the memory descriptor, and replaces the old direct mm && get_dumpable(mm) logic in __ptrace_may_access() with a helper that handles tasks with and without mm. If no mm exists and the task was not cached as user-dumpable, the path falls back to requiring CAP_SYS_PTRACE in the initial user namespace. (GitHub)

That fix matches the real bug class. The problem is not that Linux has ssh-keysign, chage, or pidfds. The problem is that access checks had an unintended gap for a target task that had crossed one exit boundary but not another. A correct fix must preserve access-control intent across that lifecycle transition.

LWN reported that stable kernels 7.0.8, 6.18.31, 6.12.89, 6.6.139, 6.1.173, 5.15.207y 5.10.256 were announced with patches for CVE-2026-46333. Kernel.org also listed 7.0.8 and several longterm releases dated May 15, 2026. Distribution backports may use different package versions, so defenders should use vendor advisories rather than only comparing upstream version strings. (lwn.net)

Why the impact is more than “read a file”

The direct primitive is read access to root-owned secrets. That is not the same as immediate root command execution. It can still be severe.

Reading /etc/shadow gives an attacker password hashes, not plaintext passwords. The attacker still needs to crack those hashes offline. The risk depends on password quality, hashing algorithm, shadow policy, local account reuse, and whether password authentication is enabled anywhere meaningful. Even if root login by password is disabled, non-root account hashes may still matter because reused passwords often bridge from Linux hosts to VPNs, SaaS systems, internal Git servers, or other infrastructure.

Reading SSH host private keys is a different kind of problem. Host keys identify servers. If stolen, they can enable host impersonation in environments where clients trust those keys, disrupt trust-on-first-use assumptions, or aid man-in-the-middle attacks where network positioning exists. The practical damage depends on whether clients pin host keys, whether the host participates in automation, whether known_hosts entries are centrally managed, and whether host certificates or short-lived host keys are used.

The public PoC repository claims confirmed results on Raspberry Pi OS Bookworm 6.12.75, Debian 13, Ubuntu 22.04, Ubuntu 24.04, Ubuntu 26.04, Arch, and CentOS 9. Treat that as public exploit author testing, not as a complete vendor impact matrix. Vendor trackers are still the authority for your fleet. (GitHub)

The systems that deserve first response

CVE-2026-46333 deserves different urgency depending on local exposure. A single-user laptop that never runs untrusted code has a different risk profile from a shared build runner executing third-party pull requests. The vulnerability becomes most serious where low-privilege local execution is already a realistic attacker position.

Medio ambientePrioridadPor qué es importanteFirst action
Shared hosting and shell serversCríticaUntrusted users already have local accounts; known public targets may existApply kernel fix or livepatch, restrict ptrace where feasible, audit SUID helper exposure
CI runners and build farmsCríticaPull requests, build scripts, dependency hooks, and test jobs can produce local code executionPatch nodes, isolate jobs, rotate secrets exposed to runners
Kubernetes worker nodesAltaContainers share the host kernel; local kernel bugs can matter even when container users are not host rootPatch node images, drain and reboot, restrict untrusted workloads
Developer workstationsAltaThey often hold SSH keys, credentials, package tokens, and local admin pathsPatch quickly, rotate keys if exploit is suspected, check local helper exposure
Jump boxes and bastionsAltaThey concentrate trust relationships and administrative SSH flowsPatch immediately, review host keys and authentication logs
HPC and university clustersAltaMulti-user shell access is common and long-running kernels are commonPatch scheduling nodes and login nodes first
Single-purpose internal serversMedioRisk depends on whether attackers can get local code executionPatch within emergency kernel cadence
Single-user desktopsLower but not zeroExploitation requires local code execution, but malicious apps or scripts can supply thatPatch through normal security update path, faster if used for admin work

The wrong lesson is “local only, therefore low priority.” The right lesson is “local only, therefore prioritize by foothold likelihood.” In 2026 infrastructure, low-privileged local code execution is not rare. It is the normal intermediate state after a compromised web service, malicious package script, CI abuse, shell account compromise, or container workload escape attempt.

A safe exposure check for defenders

The safest production check is not “run the public exploit and see whether it prints secrets.” Production systems contain real secrets, and exploit attempts can create unnecessary legal, operational, and evidentiary problems. Use vendor package state, running kernel state, helper exposure, and monitoring signals first.

Start with the running kernel:

uname -a
uname -r
cat /proc/version

On Debian-family systems, use the vendor package database and security tracker data rather than assuming a raw upstream number is enough:

dpkg -l 'linux-image*' | awk '/^ii/ {print $2, $3}'
apt-cache policy linux-image-amd64 2>/dev/null || true

Debian’s tracker lists CVE-2026-46333 fixed for linux in bullseye security at 5.10.251-5, bookworm security at 6.1.172-1, trixie security at 6.12.88-1, and unstable at 7.0.7-1, while older unfixed package rows remain marked vulnerable. Those package versions are Debian-specific and should not be applied to other distributions. (Debian Security Tracker)

On RPM-family systems, collect kernel package state and confirm which kernel is actually booted:

rpm -q kernel kernel-core 2>/dev/null || true
uname -r
dnf updateinfo list --cves CVE-2026-46333 2>/dev/null || true

For AlmaLinux, the project stated that AlmaLinux 9 and 10 were vulnerable to the public exploits, while AlmaLinux 8 had the underlying logic bug but was not exploitable with the then-current public PoCs; AlmaLinux still planned to ship the patch for AlmaLinux 8. That is a good example of why exploitability and underlying vulnerability should be tracked separately. (AlmaLinux OS)

Check whether the known public target helpers are present and setuid:

for p in \
  /usr/lib/openssh/ssh-keysign \
  /usr/libexec/openssh/ssh-keysign \
  /usr/bin/chage
do
  if [ -e "$p" ]; then
    stat -c '%A %U %G %n' "$p"
  fi
done

Check SSH client configuration, but do not treat it as the final answer:

grep -R --line-number -E '^\s*(EnableSSHKeysign|HostbasedAuthentication)\s+' \
  /etc/ssh/ssh_config /etc/ssh/ssh_config.d/*.conf 2>/dev/null || true

This configuration check is useful because it tells you whether host-based SSH authentication may be operationally needed. It does not prove that CVE-2026-46333 is mitigated. The public ssh-keysign exploit path is specifically interesting because the helper can still be a target even when the feature is disabled by configuration, due to the order of opening files, privilege changes, and exit handling described by the PoC author. (GitHub)

Detecting exploit attempts

Detection is hard because the race window is short and the final read may happen through a duplicated file descriptor. You are looking for behavior around the chain, not just a clean log entry saying “attacker opened /etc/shadow."

Useful signals include abnormal bursts of ssh-keysign o chage, repeated short-lived helper processes, unexpected pidfd_getfd use, suspicious ptrace-related activity by non-developer accounts, and later signs of credential use. A successful exploit may require repeated attempts, and the public PoC repository says the example can hit in 100 to 2000 spawns. (GitHub)

On Linux systems with auditd, you can add a temporary watch for pidfd_getfd if your audit userspace recognizes the syscall name:

sudo auditctl -a always,exit \
  -F arch=b64 \
  -S pidfd_getfd \
  -F auid>=1000 \
  -F auid!=4294967295 \
  -k pidfd_getfd_watch

Then query:

sudo ausearch -k pidfd_getfd_watch
sudo aureport -x --summary | egrep 'ssh-keysign|chage|pidfd'

On systems where the syscall name is not available in audit rules, you may need the numeric syscall value for your architecture, or you may prefer eBPF-based tracing. In a short incident window, bpftrace can provide live visibility:

sudo bpftrace -e '
tracepoint:syscalls:sys_enter_pidfd_getfd
{
  printf("%s pid=%d pidfd=%d targetfd=%d flags=%d\n",
    comm, pid, args->pidfd, args->targetfd, args->flags);
}'

For helper execution bursts:

sudo bpftrace -e '
tracepoint:sched:sched_process_exec
/str(args->filename) == "/usr/bin/chage" ||
 str(args->filename) == "/usr/lib/openssh/ssh-keysign" ||
 str(args->filename) == "/usr/libexec/openssh/ssh-keysign"/
{
  printf("%s pid=%d uid=%d\n", str(args->filename), pid, uid);
}'

These commands are detection aids, not guarantees. Normal developer workflows can use ptrace-like behavior. Monitoring tools may attach to processes. Some distributions may not expose identical tracepoint fields. Treat alerts as triage leads and correlate them with account, host role, process tree, terminal session, CI job, container ID, and network activity.

A practical triage workflow

A good CVE-2026-46333 response should separate five questions:

QuestionPor qué es importanteEvidence to collect
Is the running kernel vulnerable?Installed packages do not matter until the host boots the fixed kerneluname -r, package version, vendor advisory status
Can untrusted users run code locally?The bug needs local executionshell users, CI jobs, container workloads, exposed web apps
Are known target helpers setuid and reachable?Public PoCs target ssh-keysign y chagestat, package inventory, container namespace view
Are secrets high value on this host?Host keys and password hashes have different blast radius per environmentSSH host key usage, known_hosts management, account policy
Is there evidence of exploitation?Patch alone may not address stolen secretsaudit logs, process bursts, auth logs, outbound connections, shadow access timeline

For many organizations, the fastest responsible path is to patch first and investigate second. That is acceptable when the patch is low-risk and the exposure is high. Do not delay emergency kernel remediation while debating whether every host has EnableSSHKeysign yes. That setting does not define the kernel vulnerability.

Mitigation and patching

The durable fix is a patched kernel. Install the vendor kernel update, reboot into it, and verify the running kernel. For fleets, enforce reboot verification because a package manager can report a fixed kernel installed while the machine is still running a vulnerable kernel.

A generic sequence looks like this:

# Debian or Ubuntu family
sudo apt update
sudo apt full-upgrade
sudo reboot

# After reboot
uname -r
dpkg -l 'linux-image*' | awk '/^ii/ {print $2, $3}'
# RHEL, AlmaLinux, Rocky, Fedora-like family
sudo dnf update 'kernel*'
sudo reboot

# After reboot
uname -r
rpm -q kernel kernel-core 2>/dev/null || true

For CloudLinux, the vendor published several temporary mitigation layers. The most direct CloudLinux-specific mitigation is kernel.user_ptrace=0, a non-upstream sysctl that gates unprivileged ptrace. CloudLinux states that setting it to 0 blocks the public proof-of-concept on CL9 and CL10, but it also breaks unprivileged gdb -p, strace -p, and similar attach-debug workflows. (blog.cloudlinux.com)

# CloudLinux-specific, not an upstream Linux sysctl
sudo sysctl -w kernel.user_ptrace=0

# Persist across reboots on CloudLinux
echo 'kernel.user_ptrace = 0' | sudo tee /etc/sysctl.d/99-ptracenull.conf
sudo sysctl --system

CloudLinux also described per-binary SUID-bit removal for the two known public targets as a fallback when the sysctl cannot be used, while warning that this covers only known PoC targets and may break legitimate functionality. Removing SUID from ssh-keysign can break host-based SSH authentication, and removing it from chage prevents non-root users from using that helper for their own password-aging information. (blog.cloudlinux.com)

# Emergency fallback for known public targets only.
# Do not use blindly if host-based SSH auth or user password-aging workflows depend on these.
sudo chmod u-s /usr/lib/openssh/ssh-keysign 2>/dev/null || true
sudo chmod u-s /usr/libexec/openssh/ssh-keysign 2>/dev/null || true
sudo chmod u-s /usr/bin/chage

# Verify SUID bit is gone
ls -l /usr/lib/openssh/ssh-keysign /usr/libexec/openssh/ssh-keysign /usr/bin/chage 2>/dev/null

This is not a replacement for patching. It is a narrow risk-reduction step for the two most visible public targets. The kernel bug class is broader than those paths.

What to rotate after suspected exploitation

If a system was vulnerable but there is no evidence of exploitation, many teams will patch and monitor. If there is credible evidence that the public exploit or a variant ran on the host, treat secrets as potentially compromised.

Start with SSH host private keys:

sudo ls -l /etc/ssh/ssh_host_*_key
sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub 2>/dev/null || true
sudo ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub 2>/dev/null || true
sudo ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key.pub 2>/dev/null || true

A host key rotation plan should include generating new host keys, restarting SSH, updating known_hosts entries or central host-key stores, and communicating expected host key changes to administrators and automation owners. Sudden host key changes can look like a man-in-the-middle attack to clients, so a clean rotation needs coordination.

Para /etc/shadow, the right response depends on account policy. If password authentication is disabled, MFA is enforced, service accounts have locked passwords, and local hashes are strong, the blast radius is smaller. If human passwords are reused, weak, old, or accepted by SSH, VPN, sudo, or internal services, reset affected passwords and review authentication logs.

A minimal incident checklist:

PasoAcciónReason
1Isolate the host if compromise is likelyPrevent further access and preserve evidence
2Capture volatile evidenceProcess history, audit logs, shell history, CI job logs, container metadata
3Patch and rebootClose the kernel path
4Rotate SSH host keys where exposure is crediblePrevent host impersonation with stolen keys
5Reset local passwords where /etc/shadow exposure is credibleReduce offline-cracking impact
6Review lateral movementStolen secrets may be useful outside the original host
7Re-enable temporary functionality only after patch verificationAvoid leaving debug and user-management workflows broken unnecessarily

Do not rely on file modification timestamps to answer whether secrets were read. CVE-2026-46333 is not a normal file write. It is a descriptor theft path.

Why disabling EnableSSHKeysign is not enough

EnableSSHKeysign no may mean host-based SSH authentication is not intentionally enabled. That helps you understand business impact if you temporarily remove SUID from ssh-keysign. It does not close the kernel race by itself.

The public PoC description matters here: it says ssh-keysign opens host key files before permanently_set_uid() and then bails on EnableSSHKeysign=no with file descriptors still open. That is precisely why the exploit name points at ssh-keysign even though the kernel bug is the root cause. (GitHub)

A better mental model is:

ControlarPara qué sirveWhat it does not do
EnableSSHKeysign noDisables intended host-based SSH key signing in normal client configurationDoes not patch the kernel or necessarily prevent the helper from being used as a race target
Removing SUID from ssh-keysignPrevents the known helper target from opening host keys as rootDoes not fix other possible targets and may break legitimate host-based auth
Restricting unprivileged ptraceCan block the descriptor-copy path on platforms that support the controlMay break debugging and is not universally available under the same sysctl
Kernel patchFixes the access-control logicRequires deployment, reboot or livepatch verification

How this compares to Copy Fail, Dirty Frag, and Fragnesia

CVE-2026-46333 landed in the same public conversation as several other Linux kernel local bugs, but it is technically different from the page-cache corruption family. Copy Fail, Dirty Frag, and Fragnesia are useful comparisons because they show why “local kernel bug” should not be dismissed, especially in multi-tenant and CI environments.

IssueCVECore ideaExploitation conditionRiesgo prácticoFix or mitigation theme
ssh-keysign-pwnCVE-2026-46333ptrace access-check logic mishandles tasks with no mm during exit, enabling fd duplication from privileged dying processesLocal unprivileged code execution; reachable target helper or equivalent shapeReads root-owned secrets such as host keys or /etc/shadowPatch kernel; restrict ptrace where supported; reduce known SUID target exposure
Copy FailCVE-2026-31431Linux crypto algif_aead in-place behavior can corrupt page cache through AF_ALG y splice()Local unprivileged code executionPage-cache write primitive against readable files, used in public analysis for root escalationPatch kernel; reduce unneeded attack surface; prioritize multi-tenant hosts
Dirty FragCVE-2026-43284 and CVE-2026-43500Kernel networking and memory-fragment handling issues in ESP and RxRPC pathsLocal unprivileged code executionRoot escalation through page-cache corruption-style primitivesPatch kernel; consider module-level mitigations only where operationally safe
FragnesiaCVE-2026-46300Logic bug in XFRM ESP-in-TCP attack surface enabling page-cache corruption of read-only filesLocal unprivileged code executionRoot escalation by corrupting cached executable contentPatch kernel; apply vendor temporary module mitigations where acceptable

NVD describes Copy Fail’s fix as reverting algif_aead back to out-of-place operation because the source and destination come from different mappings, removing complexity added for in-place handling. Microsoft characterized Copy Fail as a Linux kernel crypto-subsystem bug that could corrupt the cache of readable files, including setuid binaries, leading to root privilege code execution. (NVD)

Microsoft’s Dirty Frag write-up states that Dirty Frag involved Linux kernel networking and memory-fragment handling components, including ESP and RxRPC, and lists CVE-2026-43284 and CVE-2026-43500. Ubuntu also described Dirty Frag as two local privilege-escalation vulnerabilities disclosed on May 7, 2026, affecting kernel modules tied to ESP and RxRPC. (microsoft.com)

Fragnesia, tracked as CVE-2026-46300, is described by Red Hat as a flaw in the Linux kernel’s XFRM ESP-in-TCP subsystem allowing a local attacker to achieve privilege escalation; AlmaLinux warned that its proof-of-concept was public and that systems with untrusted local code, CI runners, and multi-tenant hosts should treat it urgently. (Portal del cliente de Red Hat)

The shared lesson is not that every local Linux CVE is the same. The shared lesson is that local post-compromise primitives increasingly target kernel boundary assumptions: page cache identity, helper privilege transitions, descriptor ownership, networking buffers, and cross-subsystem invariants. Defenders need response workflows that understand where low-privilege code can run, not just which internet-facing services are open.

Container and CI implications

Containers do not carry their own kernel. A containerized process uses the host kernel. That does not mean every container can exploit every local kernel bug, but it does mean kernel local vulnerabilities are relevant to container platforms, especially when untrusted code runs on shared nodes.

For CVE-2026-46333, the key questions are:

QuestionPor qué es importante
Can the workload invoke target helpers or equivalent host-visible binaries?Public examples rely on helper programs that may not exist inside a minimal container
Does the container have access to pidfd and ptrace-related syscall paths?Seccomp, LSMs, namespaces, and runtime defaults can influence reachability
Does the host allow multiple tenants on the same kernel?A successful local kernel exploit affects host trust, not just app trust
Are SSH host keys or sensitive secrets mounted into the container?Direct secret mounts increase impact even without helper targets
Are CI jobs allowed to run arbitrary PR code?CI turns remote contribution into local code execution by design

CI systems are especially exposed because they intentionally execute code submitted by developers, dependencies, or external contributors. A malicious test script does not need internet-facing exploitability if the build runner is vulnerable and holds secrets or shares kernel state with other jobs. Treat CVE-2026-46333 as a runner hygiene issue, not just a server patch issue.

A defensive runner check can be as simple as inventorying kernel state across nodes:

#!/usr/bin/env bash
set -euo pipefail

echo "host=$(hostname)"
echo "kernel=$(uname -r)"
echo "os=$(grep PRETTY_NAME /etc/os-release | cut -d= -f2- | tr -d '\"')"

echo
echo "[known helper state]"
for p in /usr/lib/openssh/ssh-keysign /usr/libexec/openssh/ssh-keysign /usr/bin/chage; do
  if [ -e "$p" ]; then
    stat -c '%A %U %G %n' "$p"
  fi
done

echo
echo "[ssh client hostbased settings]"
grep -R -E '^\s*(EnableSSHKeysign|HostbasedAuthentication)\s+' \
  /etc/ssh/ssh_config /etc/ssh/ssh_config.d/*.conf 2>/dev/null || true

Use that output for triage, not as a vulnerability scanner with a universal pass/fail result. A patched kernel with SUID helpers present is normal. An unpatched high-risk runner with helpers present is not.

Why CVSS alone is a poor prioritization signal here

At the time NVD initially published CVE-2026-46333, NVD had not provided CVSS severity metrics in the page snapshot available during disclosure. That is common for fresh kernel CVEs. Waiting for a score before triage is a mistake. NVD’s page already contained the important technical description: the issue concerns ptrace dumpability logic for tasks with no associated mm, and the fix changes how such cases are handled. (NVD)

Risk depends on environment. A local information disclosure can be urgent on a shared host and less urgent on a single-purpose appliance with no untrusted code path. The right inputs are:

  • Whether any untrusted local users exist.
  • Whether remote services can lead to low-privilege code execution.
  • Whether CI or container workloads run third-party code.
  • Whether the host stores reusable credentials.
  • Whether SSH host keys are used for strong trust decisions.
  • Whether patching requires a reboot window or livepatch is available.
  • Whether temporary ptrace restrictions are operationally acceptable.

This is also where evidence-driven security workflows matter. Penligent’s public materials describe AI-assisted penetration testing workflows around CVE validation, privilege escalation, lateral movement, evidence generation, and controlled operator scope, while its Linux kernel write-up on Copy Fail shows the same kind of local-kernel-risk analysis that applies to post-foothold vulnerabilities such as CVE-2026-46333. In an authorized environment, the useful pattern is not “blindly run a public exploit”; it is to turn a fresh CVE into scoped asset selection, safe validation, patch verification, and reproducible evidence that infrastructure owners can act on. (Penligente)

Penligent’s homepage also emphasizes controlled agentic workflows and human-in-the-loop control, which is the right posture for this class of issue: local kernel validation should be bounded, logged, and tied to remediation proof rather than treated as a free-form exploit exercise. (Penligente)

Common mistakes during response

The first mistake is calling ssh-keysign-pwn an OpenSSH remote bug. That framing sends teams to the wrong owner and the wrong fix. OpenSSH’s helper is a known target, but the fix is in the kernel.

The second mistake is checking only installed package versions. Installed fixed kernels do not protect a running host until the system boots the fixed kernel or applies a verified livepatch. Always pair package checks with uname -r.

The third mistake is treating EnableSSHKeysign no as a complete mitigation. It can inform operational impact, but the public exploit path explicitly discusses the helper exiting after the disabled setting while still having relevant descriptors open. (GitHub)

The fourth mistake is ignoring /etc/shadow because passwords are “hashed.” Hashes are not plaintext, but they are offline cracking material. Weak passwords, reused passwords, and service-account secrets can still turn a hash leak into real access.

The fifth mistake is rotating secrets before patching. If exploitation is credible, patch or isolate first. Otherwise, a still-vulnerable host may leak freshly rotated secrets.

The sixth mistake is running public exploit code in production as a “scanner.” That can expose real secrets, pollute evidence, create legal issues, and normalize unsafe testing habits. Use vendor advisories and safe telemetry first. Use isolated lab VMs for exploit reproduction.

A defensible remediation plan

Patch, Verify, Monitor, and Rotate Secrets After ssh-keysign-pwn

For a medium or large fleet, a defensible CVE-2026-46333 plan looks like this:

  1. Identify Linux hosts where untrusted local code can run.
  2. Prioritize multi-tenant hosts, CI runners, Kubernetes nodes, bastions, and developer machines.
  3. Install vendor kernel updates or livepatches.
  4. Reboot or verify livepatch status.
  5. Confirm the running kernel is fixed.
  6. Apply temporary ptrace restriction only where patching is delayed and workflows tolerate it.
  7. Avoid broad SUID removal unless you understand the business impact.
  8. Monitor for pidfd_getfd, abnormal helper bursts, and suspicious credential use.
  9. Rotate SSH host keys and reset passwords if exploitation is credible.
  10. Record evidence: host list, kernel versions before and after, reboot status, secrets rotated, exceptions, and owner sign-off.

A simple fleet output format can help infrastructure teams avoid ambiguity:

hostname,environment,running_kernel,package_fixed,rebooted,known_helpers_suid,ptrace_restricted,owner,status
ci-runner-07,ci,6.12.x,false,false,true,false,platform,patch-now
bastion-02,prod,5.15.x,true,true,true,n/a,infra,verified
devbox-14,workstation,6.6.x,true,false,true,false,endpoint,reboot-required

En rebooted field is not bureaucracy. It is the difference between “fixed package installed” and “vulnerable kernel no longer running.”

PREGUNTAS FRECUENTES

What is ssh-keysign-pwn?

  • ssh-keysign-pwn is the public name for CVE-2026-46333.
  • It is a Linux kernel local information disclosure vulnerability in the ptrace access-check path.
  • Public examples show unprivileged local users reading root-owned secrets such as SSH host private keys and /etc/shadow.
  • The core bug is not that OpenSSH accepts a bad network request; it is that Linux mishandles access checks for a process in a specific exit-time state.

Is ssh-keysign-pwn an OpenSSH vulnerability?

  • Not in the usual sense.
  • ssh-keysign is a public exploit target because it can open SSH host private keys as a privileged helper.
  • The vulnerable logic lives in the Linux kernel, specifically around __ptrace_may_access() and dumpability handling.
  • Patching OpenSSH alone is not the normal fix; the durable fix is a patched kernel or trusted kernel livepatch.

Can a remote attacker exploit CVE-2026-46333 directly?

  • Not directly from the network based on the public technical description.
  • The attacker needs local code execution, a local account, a compromised service user, a malicious CI job, or a comparable foothold.
  • The bug becomes serious when low-privileged local execution already exists.
  • Internet-facing systems are still relevant if a web app, container, dependency script, or management service can become that local foothold.

Does disabling EnableSSHKeysign fix the issue?

  • No, not as a complete fix.
  • EnableSSHKeysign no may disable normal host-based SSH authentication behavior.
  • The public PoC describes a path where ssh-keysign opens host key files and then exits after the disabled configuration path, leaving a raceable fd state.
  • Patch the kernel. Use configuration and SUID changes only as risk-reduction measures when you understand their side effects.

How do I check if my system is patched?

  • Check the running kernel with uname -r.
  • Check your vendor’s security advisory or package tracker for CVE-2026-46333.
  • Confirm that the fixed kernel is not merely installed but actually running after reboot.
  • On Debian, use the Debian security tracker’s fixed package versions for Debian releases.
  • On enterprise distributions, use vendor advisories, errata, and update tools rather than upstream version numbers alone.

What should I rotate if exploitation is suspected?

  • Rotate SSH host private keys if there is credible evidence the ssh-keysign target or equivalent secret-read path was used.
  • Update known_hosts entries, host-key pinning stores, automation trust stores, and SSH certificate records if relevant.
  • Reset local passwords if /etc/shadow exposure is credible, especially where passwords may be weak or reused.
  • Review authentication logs, lateral movement indicators, CI secrets, deployment keys, and service account credentials.

How is ssh-keysign-pwn different from Copy Fail, Dirty Frag, and Fragnesia?

  • ssh-keysign-pwn, CVE-2026-46333, is a ptrace access-check and process-exit race that can leak root-owned secrets.
  • Copy Fail, CVE-2026-31431, involves Linux crypto behavior and page-cache corruption through AF_ALG y splice().
  • Dirty Frag, CVE-2026-43284 and CVE-2026-43500, involves kernel networking and memory-fragment handling paths tied to ESP and RxRPC.
  • Fragnesia, CVE-2026-46300, involves XFRM ESP-in-TCP and page-cache corruption.
  • They are related operationally because all are local kernel issues that become dangerous after an attacker gains low-privileged code execution.

Closing judgment

ssh-keysign-pwn is dangerous because it breaks an assumption defenders rely on: a process that opened a root-only secret should not accidentally lend that secret to an unprivileged user during exit. The exploit path is clever, but the response does not need to be exotic. Patch the kernel, verify the running version, reduce untrusted local execution where you can, monitor for descriptor-copy and helper-spawn signals, and rotate secrets if exploitation is plausible.

The systems to treat first are not necessarily the ones with the most dramatic banners in a scanner. They are the systems where low-privilege code is normal: CI runners, multi-tenant hosts, developer machines, Kubernetes nodes, and bastions. For CVE-2026-46333, context decides urgency, but patching remains the only durable fix.

Comparte el post:
Entradas relacionadas
es_ESSpanish