CVE-2026-14904
Executive Summary
CVE-2026-14904 is a critical vulnerability in AWS Research and Engineering Studio (RES), an open-source solution for managing secure virtual desktops and computing resources on AWS. The flaw resides in the Auth.GetUserPrivateKey API and is classified as an Improper Link Resolution Before File Access (CWE-59). An authenticated remote attacker can replace their SSH private key file (~/.ssh/id_rsa) with a symbolic link pointing to any file on the host. Because the cluster-manager process runs as root, this allows reading arbitrary files, including other users' SSH private keys and application configuration secrets. The vulnerability has a CVSS score of 7.5 (High) and affects all versions prior to RES 2026.06. No public exploit code or PoC is currently available, but the attack vector is straightforward for an authenticated user.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability is not directly related to a package manager (NPM, PyPI, Go, Ruby) but affects an open-source AWS solution distributed via GitHub and AWS Marketplace. The supply chain risk is moderate, as the vulnerable component is the cluster-manager service, which is part of the RES deployment. Users should verify the integrity of their RES installation and ensure no unauthorized modifications have been made.
CVSS Breakdown & Threat Level
- CVSS Score: 7.5 (High)
- Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
- Attack Vector: Network (AV:N) – The vulnerability is exploitable remotely over the network.
- Attack Complexity: Low (AC:L) – No special conditions are required; the attacker only needs to replace a file with a symlink.
- Privileges Required: Low (PR:L) – The attacker must be an authenticated user of the RES system.
- User Interaction: None (UI:N) – No user interaction is required.
- Scope: Unchanged (S:U) – The vulnerable component and the impacted component are the same.
- Confidentiality Impact: High (C:H) – Arbitrary file read, including sensitive secrets.
- Integrity Impact: None (I:N) – No data modification.
- Availability Impact: None (A:N) – No denial of service.
Threat Level: High. The vulnerability allows an authenticated attacker to read arbitrary files as root, leading to credential theft and potential lateral movement.
Deep Dive & Mechanics
The vulnerability is rooted in the Auth.GetUserPrivateKey API endpoint, which is designed to retrieve the SSH private key for an authenticated user. The API reads the file at the path ~/.ssh/id_rsa relative to the user's home directory. However, the code does not validate whether the file is a regular file or a symbolic link. An attacker can:
- Authenticate to the RES system.
- Replace their
~/.ssh/id_rsafile with a symbolic link pointing to a target file (e.g.,/etc/kubernetes/admin.conf,/root/.ssh/id_rsa, or/var/lib/aws-res/secrets). - Call the
Auth.GetUserPrivateKeyAPI. - The cluster-manager process, running as root, follows the symlink and reads the target file.
- The contents are returned to the attacker.
The root cause is the lack of a O_NOFOLLOW flag or similar check when opening the file. The fix in version 2026.06 likely adds a check to ensure the file is not a symbolic link before reading.
Vulnerable vs. Patched Code
Vulnerable Code (Conceptual):
# Vulnerable: No symlink check
def get_user_private_key(username):
key_path = f"/home/{username}/.ssh/id_rsa"
with open(key_path, 'r') as f:
return f.read()
Patched Code (Conceptual):
# Patched: Check for symlink
import os
def get_user_private_key(username):
key_path = f"/home/{username}/.ssh/id_rsa"
if os.path.islink(key_path):
raise PermissionError("Symlink detected")
with open(key_path, 'r') as f:
return f.read()
The patched version uses os.path.islink() to detect and reject symbolic links before opening the file.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- Authenticated user account on the RES system.
- Ability to write to the user's home directory (e.g., via SSH or web shell).
Exploitation Steps:
- SSH into the RES cluster-manager instance as an authenticated user.
- Remove the existing SSH private key file:
rm ~/.ssh/id_rsa - Create a symbolic link to a sensitive file:
ln -s /etc/kubernetes/admin.conf ~/.ssh/id_rsa - Call the
Auth.GetUserPrivateKeyAPI (e.g., via curl):curl -X POST https://cluster-manager.example.com/api/auth/get-user-private-key \ -H "Authorization: Bearer <token>" \ -d '{"username": "attacker"}' - The API returns the contents of
/etc/kubernetes/admin.conf.
Alternative Target Files:
/root/.ssh/id_rsa– Root SSH key./var/lib/aws-res/secrets– Application secrets./etc/shadow– Password hashes (if readable by root).
Blue Team (Detection & Hardening)
Detection:
- Monitor for symlink creation in user home directories:
auditctl -w /home/ -p wa -k user_home_symlink - Alert on API calls to
Auth.GetUserPrivateKeythat return unusually large or unexpected data. - Use file integrity monitoring (e.g., AIDE, Tripwire) to detect changes to
~/.ssh/id_rsa.
Hardening:
- Apply the patch by upgrading to RES version 2026.06.
- Implement a WAF rule to block API requests with suspicious payloads.
- Restrict user write access to home directories where possible.
- Run the cluster-manager process with reduced privileges (e.g., as a non-root user).
Indicators of Compromise (IOCs)
- File System:
- Symlink at
~/.ssh/id_rsapointing to an unexpected file. - Unauthorized reads of sensitive files (e.g.,
/etc/shadow,/root/.ssh/id_rsa).
- Symlink at
- Network:
- API calls to
/api/auth/get-user-private-keyfrom authenticated users. - Unusual data exfiltration from the cluster-manager instance.
- API calls to
- Logs:
- Audit logs showing
opensyscalls withO_NOFOLLOWnot set. - Application logs showing successful reads of symlinked files.
- Audit logs showing
Detection Engineering
YARA Rule
rule CVE_2026_14904_Symlink_Detection {
meta:
description = "Detects symlink creation for CVE-2026-14904 exploitation"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2026-14904"
strings:
$symlink_cmd = "ln -s" ascii nocase
$id_rsa_path = "/.ssh/id_rsa" ascii nocase
condition:
$symlink_cmd and $id_rsa_path
}
Sigma Rule
title: CVE-2026-14904 Symlink Exploitation Attempt
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects creation of a symlink to ~/.ssh/id_rsa for CVE-2026-14904 exploitation
author: Valters IT
logsource:
category: process_creation
product: linux
detection:
selection:
Image|endswith: '/ln'
CommandLine|contains: '-s'
CommandLine|contains: '/.ssh/id_rsa'
condition: selection
falsepositives:
- Legitimate SSH key management
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"CVE-2026-14904 - Auth.GetUserPrivateKey API Call";
flow:to_server,established;
content:"POST"; http_method;
content:"/api/auth/get-user-private-key"; http_uri;
content:"username"; http_client_body;
classtype:attempted-recon;
sid:1000001;
rev:1;
)
Remediation & Mitigation
Immediate Actions:
- Upgrade to RES version 2026.06 – This is the only complete fix.
- Restrict user home directory permissions – Ensure users cannot create symlinks in their home directories (e.g., set immutable flag on
~/.ssh/). - Monitor for exploitation – Deploy the YARA, Sigma, and Suricata rules above.
Long-Term Mitigations:
- Implement a file integrity monitoring solution for critical directories.
- Run the cluster-manager process as a non-root user with minimal permissions.
- Conduct a security review of all API endpoints that read user files.
Workaround (if patching is delayed):
- Remove the
Auth.GetUserPrivateKeyAPI endpoint or restrict it to admin users only. - Use a custom wrapper that checks for symlinks before reading files.
Valters IT
DevSecOps & Cyber Threat Intelligence