GHSA-6976-qm5m-7mcj json
A `BigInt` division panics, and two neighbouring operations answer wrongly in silence
published 3mo ago modified 30d ago also RUSTSEC-2026-0236
- cvss
- 7.5
- version 3.1, OSV
- cisa kev
- Not listed
- not in CISA's catalog
- epss
- —
- no score, EPSS covers CVEs only
- public exploits
- 0
- none known
Summary
`viperjs` is a JavaScript engine intended to run untrusted script inside a host application, so script text is data rather than a trusted caller and a panic reachable from script is a denial of service in the embedder's process.
A divisor whose magnitude lands exactly on the engine's internal limb ceiling reaches an out-of-bounds index. On every released version up to and including 0.2.1:
```js const d = (1n << 33554399n) * 2n; 1n / d; // panic: index out of bounds ```
Two further operations on the same value returned wrong results without raising anything, which is the more dangerous half for an embedder that acts on the answer:
```js d % 7n; // 0n — the true remainder is 1n String(d); // "0" ```
## Cause
The left-shift helper reserved one limb for the bits a shift may push past the top of the magnitude, measured *that* width against the size ceiling, and then trimmed the reserved limb away again — so a magnitude landing exactly on the ceiling was refused on account of room it does not keep. The division treated that refusal as unreachable and discarded it with `unwrap_or_default`, leaving an empty divisor magnitude; the subsequent `divisor[n - 1]` is then an index of `usize::MAX`.
The crate is `#![forbid(unsafe_code)]`, so this is a panic and not memory unsafety.
## Remediation
Upgrade to 0.2.2, in which all three behaviours are fixed: both divisions now produce correct results, and `String()` of a magnitude beyond what the engine can divide raises a `RangeError` rather than producing `"0"` — ECMA-262 §6.1.4 requires an implementation that imposes a limit to throw rather than answer something else.
There is no workaround short of upgrading; the values are reachable from any script the embedder evaluates.
Reported by [@Zniece](https://github.com/Zniece).
Patch / fix
- crates.io viperjs 0.2.2
Is GHSA-6976-qm5m-7mcj in your dependencies? Fencer shows which of your repositories are affected as soon as an advisory lands, and opens the fix as a pull request.
Check with FencerCVSS scores
| assigned by | version | score | vector |
|---|---|---|---|
| OSV | 3.1 | 7.5 | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H |
Affected packages
| ecosystem | package | affected | fixed in |
|---|---|---|---|
| crates.io | viperjs | >=0.0.0-0, <0.2.2 |
0.2.2 |
References
Sources
Fencer Intel keeps one entry per vulnerability: the CVE id wins, then GHSA, and records that alias each other are merged, except that two CVEs always keep separate entries. The same data is available as JSON.