Skip to content

chunk-js: URL.parse reentrancy and stack call-site caching can abort the process #300

Open

Description

@oglassdev

Follow-up to #297. Review of the structuredClone fix found two more places where application JavaScript can make native code panic inside a V8 callback, which aborts the whole process hosting core. Both reproduce as SIGABRT in chunk-js, and both live in upstream crates.

  1. URL.parse reentrancy (deno_web 0.289.0, url.rs:39). A subclass whose constructor builds a second URL consumes the serialization URL.parse is waiting to retrieve, and the op panics because UrlSerialization is missing. A setter on URL's brand symbol triggers the same failure.
  2. Call-site cache poisoning (deno_core 0.411.0, error.rs:1837, 1847, 1857 and 2055). With Error.prepareStackTrace returning raw frames, an inherited Array.prototype index setter poisons the internal call-site cache. getFileName, getLineNumber, getColumnNumber and toString then unwrap or cast values unchecked.

Options

  • Patch the unchecked sites, either upstream or as a small [patch.crates-io] fork, so they throw instead of panic.
  • Or avoid the paths in chunk-js: drop URL.parse and make the URL constructor non-reentrant, and stop exposing raw call sites by not honouring Error.prepareStackTrace.

Also check the other deno_core and deno_web callbacks that application code can reach for the same class of bug.

Activity

  1. oglassdev commented on Oct 12, 2026

    @oglassdev
    ContributorAuthor

    Status after #341, which closes both paths reported here and a third found while auditing (a failed dynamic import() whose rejection had a non-string message).

    Still open:

    • Abort through errorAdditionalPropertyKeys. deno_core (error.rs near 1274) sizes a Vec from an application-supplied array while converting a thrown error. throw Object.assign(new Error("x"), { [Symbol.for("errorAdditionalPropertyKeys")]: new Array(4294967295) }) aborts from an invocation, a top-level throw, a microtask error or an unhandled rejection. Review of fix(js): stop application JavaScript from aborting core through URL.parse, stack traces and import() #341 showed an in-crate fix is feasible: install the report-exception and unhandled-rejection hooks before bootstrap removes Deno, own the raw V8 exception and promise boundaries for invocation and module evaluation, and convert with a bounded conversion (JsError::from_v8_message worked in a probe) instead of from_v8_exception. The existing .map_err(js_error) calls are too late. The dependency's fallback paths need covering too.
    • Deadline escape during error conversion (a hang, not an abort). deno_core (error.rs near 1666) cancels termination before converting the exception, so an error whose message getter never returns outlives the deadline. Owning the conversion as above would likely close this as well.

    🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions