CVE-2024-51491
Executive Summary
CVE-2024-51491 is a denial-of-service (DoS) vulnerability in the notion-go library, a Go implementation of the Notary Project specifications for signing and verifying OCI artifacts. The flaw resides in the Certificate Revocation List (CRL) caching mechanism. When notion-go retrieves a CRL, it attempts to atomically update its local cache using the os.Rename system call. On Linux distributions where /tmp resides on a separate filesystem (e.g., tmpfs), this rename operation fails with an EXDEV (cross-device link) error, causing the entire notation process to crash. This aborts any ongoing signature verification, effectively creating a denial-of-service condition. The vulnerability is rated low severity (CVSS 3.3) due to its local attack vector and limited impact (availability only), but it is trivially exploitable by any unprivileged user or process that can trigger a CRL check.
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 affects the notion-go Go module, which is a critical dependency for any tool or service that verifies OCI artifact signatures using the Notary Project standards. The crash occurs during standard CRL-based revocation checks, meaning any application using notion-go for signature verification is susceptible. The supply chain risk is moderate: an attacker cannot inject malicious code, but they can reliably disrupt signature verification processes, potentially blocking software deployments or updates that rely on notation for integrity checks. The fix (version 1.3.0-rc.2) replaces the os.Rename call with a copy-and-delete strategy, which works across filesystem boundaries.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
- Base Score: 3.3 (Low)
- Attack Vector: Local (AV:L) – The attacker must be able to execute code on the same system as the vulnerable
notationprocess. - Attack Complexity: Low (AC:L) – No special conditions are required; any CRL check on a system with separate
/tmpwill trigger the crash. - Privileges Required: None (PR:N) – The attacker does not need any privileges; any unprivileged user or process can trigger the vulnerability.
- User Interaction: None (UI:N) – No user action is needed beyond the normal operation of
notation. - Scope: Unchanged (S:U) – The crash does not affect other components.
- Confidentiality Impact: None (C:N)
- Integrity Impact: None (I:N)
- Availability Impact: Low (A:L) – The process crashes, but can be restarted. Repeated crashes degrade availability.
Threat Level: Low. The vulnerability is easy to exploit but requires local access and only causes a denial of service. It is not remotely exploitable.
Deep Dive & Mechanics
The vulnerability is rooted in the crl.(*FileCache).Set method within the notion-go library. The intended flow is:
- CRL Retrieval: The library downloads a fresh CRL from a remote URL.
- Temporary File Creation: It writes the CRL data to a temporary file in the system's temporary directory (e.g.,
/tmp). - Atomic Cache Update: It attempts to atomically replace the cached CRL file in the
notationcache directory (e.g.,~/.config/notation/truststore/x509/certificateRevocationList/) usingos.Rename. - Cache Hit: Subsequent CRL checks read from the cache.
The problem occurs in step 3. On many Linux distributions (notably Red Hat Enterprise Linux and its derivatives), /tmp is mounted as a tmpfs filesystem, which is separate from the filesystem where the notation cache resides (typically the root filesystem, ext4 or xfs). The os.Rename function in Go calls the rename system call, which cannot move files across different mount points. When this happens, the system call returns an EXDEV error ("Cross-device link not permitted"). The notion-go code does not handle this error gracefully; instead, it propagates the error up, causing the notation process to crash with a panic or unhandled error.
The crash is deterministic: every time a CRL check is performed on such a system, the process will terminate. This means any signature verification that requires a CRL check will fail, leading to a denial of service.
Code Path:
crl.(*FileCache).Set→os.Rename(tmpFile, cachePath)→syscall.Rename→EXDEV→ panic/crash.
Vulnerable vs. Patched Code
Vulnerable Code (before 1.3.0-rc.2):
// crl/file_cache.go
func (c *FileCache) Set(data []byte) error {
tmpFile, err := os.CreateTemp("", "crl-*")
if err != nil {
return err
}
defer os.Remove(tmpFile.Name())
if _, err := tmpFile.Write(data); err != nil {
return err
}
if err := tmpFile.Close(); err != nil {
return err
}
// Vulnerable: os.Rename fails across filesystems
if err := os.Rename(tmpFile.Name(), c.cachePath); err != nil {
return err // This error crashes the caller
}
return nil
}
Patched Code (1.3.0-rc.2 and later):
// crl/file_cache.go
func (c *FileCache) Set(data []byte) error {
tmpFile, err := os.CreateTemp("", "crl-*")
if err != nil {
return err
}
defer os.Remove(tmpFile.Name())
if _, err := tmpFile.Write(data); err != nil {
return err
}
if err := tmpFile.Close(); err != nil {
return err
}
// Patched: Use copy-then-delete for cross-filesystem safety
if err := copyFile(tmpFile.Name(), c.cachePath); err != nil {
return err
}
return nil
}
func copyFile(src, dst string) error {
srcFile, err := os.Open(src)
if err != nil {
return err
}
defer srcFile.Close()
dstFile, err := os.Create(dst)
if err != nil {
return err
}
defer dstFile.Close()
if _, err := io.Copy(dstFile, srcFile); err != nil {
return err
}
return dstFile.Sync()
}
The patch replaces the atomic os.Rename with a manual copy operation (copyFile), which works regardless of filesystem boundaries. The trade-off is that the operation is no longer atomic, but this is acceptable for a cache file.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- A Linux system where
/tmpis on a separate filesystem (e.g.,tmpfs). This is default on RHEL, CentOS, Fedora, and many other distributions. - The
notationCLI or any application usingnotion-gomust be installed and configured to perform CRL checks. - The attacker must have local access to the system (unprivileged user is sufficient).
Exploitation Steps:
Verify the vulnerability:
# Check if /tmp is on a separate filesystem df -h /tmp # Output should show tmpfsTrigger a CRL check:
# Assuming notation is installed and configured notation verify my-image:tag # This will crash if a CRL check is neededAutomate the crash (DoS):
# Simple loop to repeatedly crash notation while true; do notation verify my-image:tag 2>/dev/null done
Expected Outcome: The notation process crashes with an error similar to:
Error: failed to verify signature: failed to check certificate revocation: rename /tmp/crl-123 /home/user/.config/notation/truststore/x509/certificateRevocationList/crl.pem: cross-device link not permitted
Blue Team (Detection & Defense)
Detection:
- Monitor for repeated crashes of the
notationprocess. - Look for the specific error message "cross-device link not permitted" in application logs.
- Use the Sigma rule provided in the Detection Engineering section.
Defense:
- Immediate: Upgrade
notion-goto version 1.3.0-rc.2 or later. - Workaround: If upgrade is not possible, set the
TMPDIRenvironment variable to a directory on the same filesystem as the cache:export TMPDIR=$HOME/.cache/notation/tmp mkdir -p $TMPDIR - Monitoring: Alert on any
EXDEVerrors from thenotationprocess.
Indicators of Compromise (IOCs)
- Error Logs: The string "cross-device link not permitted" in
notationor application logs. - Process Crashes: Repeated, unexpected termination of the
notationprocess. - System Calls: Frequent
renamesystem calls returningEXDEV(error code 18) from thenotationprocess. - File System Artifacts: Stale temporary files in
/tmpwith names likecrl-*that are not cleaned up due to the crash.
Detection Engineering
YARA Rule
rule CVE_2024_51491_NotionGo_CRL_Crash {
meta:
description = "Detects crash logs from CVE-2024-51491 in notation-go"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2024-51491"
strings:
$error1 = "cross-device link not permitted" ascii wide nocase
$error2 = "rename" ascii wide nocase
$error3 = "crl" ascii wide nocase
condition:
all of ($error*) and filesize < 10KB
}
Sigma Rule
title: CVE-2024-51491 - NotionGo CRL Cache Crash
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects crashes of the notation process due to cross-device link errors during CRL cache updates.
author: Valters IT
date: 2025-04-10
references:
- https://nvd.nist.gov/vuln/detail/CVE-2024-51491
logsource:
category: application
product: notation
detection:
selection:
EventID: 1000 # Windows Application Error
Provider_Name: 'Application Error'
Message|contains: 'cross-device link not permitted'
condition: selection
falsepositives:
- None expected
level: medium
Suricata Rule
alert tcp $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2024-51491 - NotionGo CRL Download Attempt"; flow:to_server; content:"|2e|crl|2e|der|"; http_uri; classtype:attempted-dos; sid:1000001; rev:1;)
Remediation & Mitigation
Primary Remediation:
- Upgrade
notion-goto version 1.3.0-rc.2 or later. This is the only complete fix.
Mitigation (if upgrade is not immediately possible):
- Set the
TMPDIRenvironment variable to a directory on the same filesystem as thenotationcache:export TMPDIR=$HOME/.config/notation/tmp mkdir -p $TMPDIR - Alternatively, configure the system to use a single filesystem for
/tmpand the cache (not recommended for security reasons). - Disable CRL checking if not required (not recommended for production).
Long-term Prevention:
- In Go applications, always use
os.Renamewith caution and provide a fallback (e.g., copy-then-delete) for cross-filesystem scenarios. - Implement robust error handling for all filesystem operations.
Valters IT
DevSecOps & Cyber Threat Intelligence