CVE-2024-32477
Executive Summary
CVE-2024-32477 is a high-severity vulnerability in the Deno runtime (versions prior to 1.42.2) that allows an attacker to bypass Deno's permission model. The vulnerability exploits a race condition between the flushing of standard input (libc::tcflush(0, libc::TCIFLUSH)) and the reading of user input during permission prompts. By injecting ANSI escape sequences (specifically those that query terminal state, like \033[6n for cursor position), an attacker can append arbitrary data to the standard input stream, effectively forging a user's acceptance of a permission request. This can lead to unauthorized file system access, network access, or environment variable reading, depending on the permissions requested. The CVSS score is 7.7 (High), and the vulnerability is confirmed unpatched in versions before 1.42.2.
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
Deno is a runtime for JavaScript, TypeScript, and WebAssembly, often used in server-side applications and tooling. This vulnerability is particularly dangerous in supply chain contexts because:
- Malicious packages can exploit this to bypass Deno's sandbox and gain unauthorized access to the host system.
- CI/CD pipelines using Deno scripts with permission prompts are at risk if an attacker can inject ANSI sequences into the terminal (e.g., via a compromised dependency or log output).
- Developer machines running Deno scripts from untrusted sources are vulnerable if the terminal is shared or if output is piped through a terminal emulator that responds to ANSI queries.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H
- Base Score: 7.7 (High)
- Attack Vector (AV): Local (L) – The attacker must have local access to the terminal or be able to inject ANSI sequences into the Deno process's standard input.
- Attack Complexity (AC): High (H) – The race condition window is small and requires precise timing.
- Privileges Required (PR): None (N) – No prior privileges needed.
- User Interaction (UI): Required (R) – The victim must be running a Deno script that triggers a permission prompt.
- Scope (S): Changed (C) – The vulnerability allows bypassing the security boundary of the permission model.
- Confidentiality (C): High (H) – Full read access to files, network, or environment.
- Integrity (I): High (H) – Full write access to files or network.
- Availability (A): High (H) – Could lead to denial of service or system compromise.
Threat Level: High. While the attack complexity is high, the impact is severe, and the vulnerability is in a widely used runtime.
Deep Dive & Mechanics
The vulnerability lies in how Deno handles permission prompts when running scripts that require elevated privileges (e.g., --allow-read, --allow-net). When a script requests a permission, Deno displays a prompt to the user (e.g., "Allow? [y/n]") and reads the response from standard input.
The race condition occurs between two operations:
libc::tcflush(0, libc::TCIFLUSH)– This flushes the input buffer of the terminal (file descriptor 0, stdin). It is intended to clear any leftover input before the prompt.- Reading standard input – Deno then reads the user's response.
An attacker can exploit this by sending ANSI escape sequences that query the terminal emulator (e.g., \033[6n for cursor position). The terminal emulator responds by writing the requested information back to the PTY (pseudo-terminal) channel, which is the same channel used for standard input. If the attacker times the injection correctly, the terminal's response can be written to stdin after the tcflush but before Deno reads the user's input. This effectively appends data (like a "y" character) to the input stream, causing Deno to interpret it as the user's approval.
Key components:
- ANSI escape sequences: Specifically sequences that request terminal information (e.g., Device Status Report
\033[6n). - Race window: The time between
tcflushand theread()call. - PTY channel: The shared channel for terminal I/O, allowing the terminal emulator's response to be injected into stdin.
Vulnerable vs. Patched Code
Vulnerable Code (Deno < 1.42.2):
The vulnerable code is in the permission prompt handling, likely in cli/permissions/prompter.rs or similar. The race condition is present because tcflush is called, but there is no synchronization to prevent the terminal emulator's response from being written to stdin after the flush.
// Pseudo-code of vulnerable logic
fn prompt_permission(perm: &str) -> bool {
// Flush stdin to clear any pending input
unsafe { libc::tcflush(0, libc::TCIFLUSH); }
// Display prompt
eprint!("Allow {}? [y/n] ", perm);
// Read user input
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap();
// Check if input starts with 'y' or 'Y'
input.trim().to_lowercase() == "y"
}
Patched Code (Deno >= 1.42.2): The patch likely introduces a more robust mechanism to ensure that only genuine user input is read, possibly by:
- Using a dedicated input channel that is not shared with the terminal emulator's response.
- Implementing a timeout or sequence number to validate the input.
- Disabling ANSI escape sequence processing during the prompt.
// Pseudo-code of patched logic
fn prompt_permission(perm: &str) -> bool {
// Use a separate, non-terminal input method
// Or validate that the input is from the user, not from terminal responses
let input = read_user_input_without_ansi_injection();
input.trim().to_lowercase() == "y"
}
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- A target running Deno < 1.42.2.
- Ability to inject ANSI escape sequences into the terminal (e.g., via a malicious script that prints to stdout/stderr, or by controlling a process that shares the terminal).
- The target must run a Deno script that triggers a permission prompt (e.g.,
deno run --allow-read script.js).
Exploit Steps:
- Craft a malicious script that, when executed, prints ANSI escape sequences to stdout/stderr that will be interpreted by the terminal emulator.
- The script should also trigger a permission prompt (e.g., by attempting to read a file).
- The ANSI sequence
\033[6n(Request Cursor Position) will cause the terminal emulator to respond with\033[<row>;<col>R. This response is written to the PTY channel. - Time the injection so that the terminal's response arrives after
tcflushbut before theread()call. This can be achieved by sending the ANSI sequence just before the permission prompt is displayed. - The terminal's response will contain characters that, when read by Deno, will be interpreted as user input. For example, if the response starts with
\033[, Deno will read the escape character and then the rest. However, the attacker can craft the response to include a "y" character by using a different ANSI sequence that returns a predictable string containing "y".
Example Exploit Script (Conceptual):
import subprocess
import time
# Start Deno with a script that triggers a permission prompt
proc = subprocess.Popen(
["deno", "run", "--allow-read", "malicious.js"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
# Send ANSI escape sequence to inject "y" into stdin
# This sequence requests cursor position, and the terminal responds with a string
# We can manipulate the response by controlling the terminal state
# For simplicity, we assume the terminal responds with a string containing "y"
ansi_injection = b"\033[6n" # Request cursor position
proc.stdin.write(ansi_injection)
proc.stdin.flush()
# Wait for the permission prompt
time.sleep(0.5)
# The terminal's response will be read by Deno as user input
# If the response contains "y", the permission will be granted
output, error = proc.communicate()
print(output.decode())
Note: This is a conceptual exploit. Actual exploitation requires precise timing and knowledge of the terminal emulator's behavior.
Blue Team (Detection & Defense)
Detection:
- Monitor for unusual ANSI escape sequences in logs or terminal output.
- Look for permission prompts being answered unexpectedly quickly.
- Use process monitoring to detect Deno processes that are granted permissions without user interaction.
Defense:
- Update Deno to version 1.42.2 or later.
- Run Deno scripts in isolated environments (e.g., containers) where terminal emulation is limited.
- Use
--no-promptflag to disable permission prompts entirely (if acceptable). - Implement additional input validation for permission prompts.
Indicators of Compromise (IOCs)
- Network: Unusual outbound connections from Deno processes that were not explicitly allowed.
- File System: Unexpected file reads/writes by Deno processes.
- Process: Deno processes that have been granted permissions without user interaction.
- Logs: Permission prompt logs showing "Allow" without corresponding user input.
- Terminal: Presence of ANSI escape sequences in logs or terminal output that are not part of normal operation.
Detection Engineering
YARA Rule
rule CVE_2024_32477_ANSI_Injection {
meta:
description = "Detects ANSI escape sequences used in CVE-2024-32477 exploitation"
author = "Valters IT"
date = "2024-01-01"
reference = "CVE-2024-32477"
strings:
$ansi_seq1 = /\x1b\[6n/ // Request Cursor Position
$ansi_seq2 = /\x1b\[[0-9]+;[0-9]+R/ // Cursor Position Report
$ansi_seq3 = /\x1b\[5n/ // Device Status Report
condition:
any of them
}
Sigma Rule
title: CVE-2024-32477 - Deno Permission Bypass via ANSI Injection
id: cve-2024-32477
status: experimental
description: Detects potential exploitation of CVE-2024-32477 by monitoring for ANSI escape sequences in Deno process output.
author: Valters IT
logsource:
category: process_creation
product: windows
detection:
selection:
Image|endswith: '\deno.exe'
CommandLine|contains: '--allow'
condition: selection
falsepositives:
- Legitimate use of ANSI escape sequences in Deno scripts
level: high
Suricata Rule
alert tcp any any -> any any (msg:"CVE-2024-32477 - Deno Permission Bypass via ANSI Injection"; flow:to_server; content:"|1b 5b 36 6e|"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Update Deno to version 1.42.2 or later.
- Disable permission prompts where possible using the
--no-promptflag. - Run Deno scripts in sandboxed environments (e.g., Docker containers with minimal terminal capabilities).
Long-term Mitigations:
- Implement input validation for permission prompts to ensure they come from the user, not from terminal responses.
- Use a separate, non-terminal channel for permission prompts (e.g., a GUI dialog or a dedicated IPC mechanism).
- Monitor for ANSI escape sequences in logs and alert on suspicious patterns.
Workarounds:
- If updating is not possible, avoid running untrusted Deno scripts that require permissions.
- Use
deno evalwith explicit permissions instead of interactive prompts.
Valters IT
DevSecOps & Cyber Threat Intelligence