QuickJS
CVE-2025-62493
MEDIUM
Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessRun attacker-controlled JavaScript in QuickJS
-
ExploitConvert 127-bit BigInt using radix 32
-
ExecutionLoop over-reads adjacent heap limb
-
ImpactLeak sensitive heap bytes via result string
Vulnerability Assessment
| Weakness |
CWE
ASVS 5.0
V15 - Secure Coding and Architecture Bounds checking, read limits
MITRE ATT&CK
1 technique across 1 tactic: Collection The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | Exploitation requires the ability to execute attacker-controlled JavaScript within the QuickJS engine and to invoke BigInt-to-string conversion (js_bigint_to_string1) under the specific edge case: a BigInt whose bit length sits near a limb boundary (e.g. 127 bits) converted with a power-of-two radix whose log2_radix does not evenly divide the bit count (notably radix 32, log2_radix=5), producing the off-by-one n_digits and the trailing read of r->tab[pos+1] one limb past the allocation. Limiting factors: the host application must expose QuickJS to untrusted script (not all embeddings do); impact is confined to information disclosure of heap memory immediately adjacent to the BigInt buffer (no code execution or memory-corruption write); and what is actually leaked depends on heap layout, making sensitive-data exposure opportunistic rather than guaranteed. |
| Impact | Signals point to a moderate-to-low real-world priority rather than an emergency. The input CVSS 4.0 base score is 5.9 (medium), and its metrics (AV:A, AC:H, AT:P, PR:L, UI:P) describe a hard-to-reach, interaction- and precondition-dependent flaw with high confidentiality impact (VC:H/SC:H) but only limited integrity/availability effect. EPSS is low at 0.38% (31st percentile), and the issue is NOT in CISA KEV, so there is no evidence of active exploitation. Counterbalancing this, publicly available exploit code exists (Google issue tracker), which raises the floor on exploitability. The vulnerability is a CWE-125 out-of-bounds READ yielding information disclosure only - no memory-write/RCE primitive is described, which caps worst-case severity. One notable conflict: this is a JavaScript-engine bug triggered by attacker-supplied script, which is conventionally modeled as AV:N (often PR:N/UI:N), yet the supplied vector uses AV:A/AC:H/AT:P/PR:L/UI:P - verify the vendor's deployment assumptions, because the provided vector appears to assume a specific embedded/adjacent usage context rather than a generic 'engine runs untrusted script' model. Overall: patch in normal cycles; it is a credible heap info-leak with a public PoC but low measured exploitation probability and no code-execution impact. |
| Exploit ScenarioDerived | An attacker able to run crafted JavaScript inside an application embedding QuickJS creates a 127-bit BigInt and converts it to a string with a power-of-two radix (e.g. radix 32 via toString(32)), triggering the off-by-one n_digits calculation. The conversion loop then reads one 64-bit limb past the allocated BigInt buffer, folding adjacent heap bytes into the returned string and disclosing them. Publicly available exploit code for this condition exists on Google's issue tracker, lowering the effort required. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Oct 19, 2026
An out-of-bounds heap read in QuickJS's BigInt-to-string conversion (js_bigint_to_string1) lets script-controlled BigInt values leak memory adjacent to the BigInt limb buffer. Any embedding that executes untrusted JavaScript and permits BigInt-to-string conversion with a power-of-two radix such as 32 is affected; the CPE entry (cpe:2.3:a:quickjs_project:quickjs:*:*:*:*:*:*:*:*) carries no version bound, so all builds without the upstream fix should be treated as vulnerable. Publicly available exploit code exists, but there is no confirmation of active exploitation (not in CISA KEV) and EPSS is low at 0.38% (31st percentile), consistent with an information-disclosure-only primitive whose real value depends on heap layout; the independent assessment rates confidentiality impact as limited rather than severe.
RemediationAI
Apply the upstream QuickJS fix (confirm the exact patched release in the QuickJS changelog at https://bellard.org/quickjs/Changelog and rebuild or re-vendor the engine; downstream embedders must pull the updated engine rather than patch at the application layer). If an immediate engine upgrade is not possible, the most effective control is to prevent the vulnerable path: block or normalize calls to BigInt.prototype.toString with power-of-two radices (reject or rewrite radix 32/16/8/2 conversions) and cap BigInt bit lengths in any wrapper or policy layer exposed to untrusted script - the trade-off is reduced functionality for scripts that legitimately use non-decimal BigInt formatting. A second option is to run script evaluation in a separate, low-privilege process with a segregated heap and no long-lived secrets in memory, which does not stop the read but limits what adjacent heap data is worth leaking and contains any crash from the availability side effect. Auditing the embedding to confirm whether untrusted users can reach QuickJS at all (many embeddings only evaluate trusted configuration) is the cheapest triage step; if scripts are trusted, risk is largely theoretical. Reference material: https://bellard.org/quickjs/Changelog and the upstream issue record at https://issuetracker.google.com/434193024. Note that published proof-of-concept code exists, so testing for the leak pattern (converting a 127-bit BigInt with radix 32 and inspecting trailing output bytes) is feasible as a regression check after patching.
Affects your stack
Find out whether the stacks and servers you run are on an affected version.
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
QuickJS represents BigInt values as a fixed array of 64-bit limbs (JS_LIMB_BITS = 64) prefixed by a bit length (n_bits). When converting to a string, js_bigint_to_string1 estimates the digit count with n_digits = (n_bits + log2_radix - 1) / log2_radix, which is an off-by-one ceiling in edge cases where the bit count sits just below a limb boundary. A 127-bit value converted to radix 32 (log2_radix = 5) yields n_digits = 26, i.e. 130 bits of extraction from a two-limb allocation; the loop's final iterations execute c = (r->tab[pos] >> shift) | (r->tab[pos + 1] << (JS_LIMB_BITS - shift)) with pos = 1, so r->tab[2] is read one limb past the buffer. This is a classic CWE-125 out-of-bounds read (matching the supplied CWE), caused by an arithmetic error in size computation rather than a write primitive, so there is no memory corruption path. Extraction succeeds only when the conversion loop actually reaches the overrun, which requires attacker-influenced radix and a BigInt length near a limb boundary; the leaked bytes surface in the resulting string and are therefore observable by the attacker. Note the upstream CVSS 4.0 vector (5.9, AV:A/PR:L/UI:P) and the independent CVSS 3.1 assessment (AV:N/AC:H/PR:N/UI:N, C:L/I:N/A:L) differ, but both agree the defect is a hard-to-trigger confidentiality-only leak with at most minor availability effect; the assessment's view should be used for prioritization.
Know when Quickjs gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
CVSS:4.0/AV:A/AC:H/AT:P/PR:L/UI:P/VC:H/VI:L/VA:L/SC:H/SI:L/SA:L
Attacker-supplied script reaches the engine (AV:N, PR:N, UI:N), but the boundary-aligned BigInt/radix edge case makes it AC:H; impact is a limited adjacent-heap info leak (C:L) with possible crash (A:L), no integrity effect.
Primary rating from Vendor (google).
CVSS VectorVendor: google
DescriptionCVE.org
A vulnerability exists in the QuickJS engine's BigInt string conversion logic (js_bigint_to_string1) due to an incorrect calculation of the required number of digits, which in turn leads to reading memory past the allocated BigInt structure.
- The function determines the number of characters (n_digits) needed for the string representation by calculating:
$$ \\ \text{n\_digits} = (\text{n\_bits} + \text{log2\_radix} - 1) / \text{log2\_radix}$$
$$$$This formula is off-by-one in certain edge cases when calculating the necessary memory limbs. For instance, a 127-bit BigInt using radix 32 (where $\text{log2\_radix}=5$) is calculated to need $\text{n\_digits}=26$.
- The maximum number of bits actually stored is $\text{n\_bits}=127$, which requires only two 64-bit limbs ($\text{JS\_LIMB\_BITS}=64$).
- The conversion loop iterates $\text{n\_digits}=26$ times, attempting to read 5 bits in each iteration, totaling $26 \times 5 = 130$ bits.
- In the final iterations of the loop, the code attempts to read data that spans two limbs:
C
c = (r->tab[pos] >> shift) | (r->tab[pos + 1] << (JS_LIMB_BITS - shift));
- Since the BigInt was only allocated two limbs, the read operation for r->tab[pos + 1] becomes an Out-of-Bounds Read when pos points to the last valid limb (e.g., $pos=1$).
This vulnerability allows an attacker to cause the engine to read and process data from the memory immediately following the BigInt buffer. This can lead to Information Disclosure of sensitive data stored on the heap adjacent to the BigInt object.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
A buffer overflow occurs when a program writes more data to a memory buffer than it was allocated to hold, causing the excess data to spill into adjacent memory regions.
Information disclosure occurs when an application unintentionally exposes sensitive data that aids attackers in reconnaissance or directly compromises security.
Affected Products (CPE)CVE.org
A use-after-free in QuickJS's quickjs-libc standard library lets JavaScript code corrupt heap memory from inside the int
Use-after-free in QuickJS object-printing routines can corrupt memory when an attacker-influenced Array, Map, or Set is
QuickJS commit 2788d71 was discovered to contain a stack-overflow via the component js_proxy_isArray at quickjs.c. Rated
Heap out-of-bounds write in QuickJS's BigInt string parser can corrupt memory when an embedding application converts an
Integer overflow in QuickJS's libregexp bytecode accounting can become an out-of-bounds write when a crafted recursive r
Type confusion in QuickJS's handling of the string addition (+) operation allows local attackers to trigger out-of-bound
Information disclosure in QuickJS occurs through a floating-point precision error in TypedArray.prototype.indexOf() when
Heap out-of-bounds write in QuickJS's bytecode deserializer (JS_ReadFunctionTag) lets a crafted serialized blob corrupt
quickjs-ng through 0.9.0 has a missing length check in JS_ReadString for a string, leading to a heap-based buffer overfl
quickjs-ng through 0.9.0 has an incorrect size calculation in JS_ReadBigInt for a BigInt, leading to a heap-based buffer
Heap-based buffer overflow in QuickJS up to version 0.11.0 within the js_typed_array_constructor function allows unauthe
A vulnerability was found in quickjs-ng QuickJS up to 0.8.0. Rated medium severity (CVSS 5.3), this vulnerability is rem
NVD
CVE.org
EPSS
GitHub PoC
Exploit-DB