Last 12 weeks · 1425 commits
5 of 6 standards met
This is groundwork for the Deno 3 default-permissions change. Today denies every capability by default and prompts one by one, which trains users into reaching for . For example needs two prompt rounds today, one of them just so the package can read its own data file. This adds a relaxed default permission profile that, when active, grants a pragmatic baseline so most CLI tools run without prompts while still blocking the two things that matter: exfiltration (net stays gated, so anything read cannot leave the machine) and persistence outside the project (write is confined to the working directory and the OS temp directory). Concretely the profile grants: read: allowed everywhere on disk write: allowed only under the cwd (recorded at process start) and the OS temp directory env: allowed net, run, ffi, sys: unchanged, still prompt in a TTY and deny non-interactively import: unchanged, keeps its existing implicit trusted-host allowance The profile is gated by the env var. It is on by default and setting the var to opts back out to today's deny-by-default behavior. Gating it behind the unstable var lets us gather feedback before committing to flipping the default. The profile only applies when the user provided no explicit allow-side permission configuration: no , no , no /, and no permission set from the config file. Any of those means behavior is byte-for-byte identical to today. flags do not disable the profile; they compose on top since deny always wins. The check reuses a new helper that, unlike the existing , ignores deny/ignore flags. The profile is applied centrally in 's caller so it covers , , , , and the repl uniformly. It deliberately does not touch (already implicit allow-all), (has its own allow-all default), or (permissions are baked at compile time; explicitly out of scope). Sharp edges handled Temp dir canonicalization: the write allow-list includes both the raw and canonicalized forms of the cwd and the OS temp dir, so a write to still matches when it is canonicalized to at check time (macOS symlinks and under ). is honored via . cwd semantics: the grant is the path recorded at process start, so does not widen it. A spec test proves this. Worker inheritance: child workers derive from the parent's PermissionsContainer, so a default worker inherits the profile (reads anywhere but cannot fetch). A spec test covers it. Decisions env is included: node-compat code reads env pervasively (yargs reads before doing anything), and the exfil risk of readable env is mitigated by net remaining gated. Deno's env permission does not separate get from set; that is acceptable here. sys is not included in v1 (, , etc. keep prompting). If testing shows this is the next biggest prompt-fatigue source for npm CLIs it is a follow-up candidate rather than scope creep here. Non-interactive behavior is unchanged: non-granted capabilities still auto-deny when there is no TTY. A reserved built-in set name that selects this profile even with the gate off was considered but deferred (left as a TODO) to keep the central default minimal. Tests New spec tests under cover: read anywhere, write under cwd and temp, env read, denied writes outside both, gated net, explicit-flag opt-out (an flag disables the profile so a cwd write then fails), composing on top, allowing everything, a gate-off control, worker inheritance, and chdir not widening the grant. The existing test corpus asserts today's deny-by-default behavior, so the shared test command builder defaults ; the new tests opt back in via . No existing expectations were changed. Real-world smoke test: with the gate on (including the default, env unset), completes with zero prompts and exit code 0.
returned early when was , skipping the marker that protects in-flight write callbacks. But an encrypted uv write can be in flight while is : the error path (server using / where fails, e.g. no ALPN overlap) flushes the TLS alert to the client via before any connection is ever stored. Use-after-free sequence: 1. fails and queues the alert bytes with (, still ), then emits to JS. 2. JS destroys the socket → / cppgc → sees and returns without setting . 3. The allocation is freed. 4. The uv write completes; checks — still — and dereferences the freed pointer. Fix: set the flag unconditionally before the early return. The rest of teardown (clearing , JS handles, callbacks) stays gated on as before, so behavior for the normal path is unchanged. Verification — pass , all 13 spec tests — pass node_compat TLS suite (240 tests): failure set is byte-identical to a baseline build run on the same machine (57 pre-existing failures, no additions/removals) and pass I used Cursor (Claude) to help investigate and write this change.
(This PR was written by GPT5-5 and reviewed by me, a human. I have no familiarity with this repository and so could not evaluate the fix for correctness, however it seems reasonable to me. If there's anything I can do to help this land please let me know; this fixes flakiness in our CI so I am motivated to address any feedback promptly.* Fixes https://github.com/denoland/deno/issues/35655 Worker shutdown used to notify the parent that the worker had closed before the worker finished shutdown cleanup. For Node workers, that meant Worker.terminate() could resolve while the worker thread was still stopping coverage collection and writing its raw coverage profile. The parent test could then finish and let deno test exit while the worker coverage file was still being written. Stop worker activity before sending the parent-visible close or terminal error event. That makes coverage and profiler cleanup complete before Worker.terminate() can resolve. Node worker termination also now keeps draining already-queued internal messages until the Rust worker close event arrives. This preserves the existing termination behavior while preventing ordinary queued messages from being delivered after termination has been requested. Add a coverage regression test that terminates a Node worker while coverage is enabled, then verifies that the worker raw profile is present and readable by deno coverage.
Closes #34736. Native addons that link against libuv directly (e.g. ) use libuv's condition variables. The host binary only exported , and , so loading such an addon failed: This adds the missing condition-variable symbols: , , , , , . They follow the existing / approach in : the opaque, platform-specific the addon allocates only stores a small token, and the real state lives in a process-global registry, so we don't depend on its layout (a fits the smallest , Windows' pointer-sized ). The condvar is backed by its own internal mutex rather than the addon's . takes the internal mutex, releases the addon mutex, then blocks on the internal mutex; a concurrent / must take that same internal mutex to notify and can't acquire it until the waiter is parked, so no wakeup is lost. returns () on timeout. The new symbols are added to and the regenerated lists so they land in the binary's dynamic symbol table. Tests Rust unit test in driving with a worker thread + , plus a size-fits assertion for the token. End-to-end NAPI addon test ( + ): a real addon resolves the symbols from the host at runtime and a worker signals a condition variable the main thread waits on. Verified passing locally.
Repository: denoland/deno. Description: A modern runtime for JavaScript and TypeScript. Stars: 107352, Forks: 6101. Primary language: Rust. Languages: Rust (61.9%), TypeScript (26.2%), JavaScript (10.6%), C (1.2%), HTML (0%). License: MIT. Homepage: https://deno.com Topics: deno, javascript, rust, typescript. Latest release: v2.9.1 (19h ago). Open PRs: 100, open issues: 1223. Last activity: 26m ago. Community health: 100%. Top contributors: bartlomieju, dsherret, ry, littledivy, nayeemrmn, lucacasonato, kt3k, kitsonk, divybot, piscisaureus and others.