Skip to content

Allow explicit opt-in to selected denied Node built-ins #13

Description

@mcollina

Problem

The default-deny Node capability policy introduced by #4 intentionally has no runtime override: a consumer cannot re-enable a denied built-in through worker options. Narrow hostFunctions are the preferred authority-grant mechanism, but some trusted integrations may require an existing Node module interface that cannot reasonably be adapted.

Evaluate and implement an explicit host-controlled opt-in mechanism for selected, package-reviewed denied built-ins without turning the policy into an arbitrary allowlist or weakening the runtime-upgrade gate.

This should build on #4 / PR #11 after that work is merged.

Security requirements

  • Default behavior must remain unchanged and deny the module.
  • An opt-in must never restore an OS permission omitted from the worker or dropped through process.permission.drop().
  • Unknown built-ins, new runtime identities, and unreviewed export or nested-surface changes must continue to fail closed.
  • Classify denied modules as either permanently non-overridable or eligible for a reviewed opt-in. Same-process escape and authority-amplification surfaces must remain non-overridable unless a separate security design proves otherwise.
  • Parse the host option through captured own-data-descriptor operations. Reject inherited properties, accessors, proxies, symbols, duplicates, polluted defaults, and unknown fields without invoking caller-controlled behavior.
  • Enforce the resulting policy consistently across static and dynamic ESM, bare and node: specifiers, CommonJS, createRequire(), Module._load() aliases, VM default loading, and process.getBuiltinModule().
  • Preserve module-specific attenuation. Opting into a module must not silently restore exports that remain denied by the reviewed policy.
  • Guest mutation, deletion, descriptor replacement, syncBuiltinESMExports(), or hook replacement must not broaden the selected capability.
  • Keep capability configuration and resolver state private, immutable, and unavailable to guest introspection.

Design questions

  • Should this be a per-worker option, a separately constructed capability token, or a package-level policy extension?
  • Should callers select only a reviewed module profile, or also a reviewed subset of exports?
  • Which currently denied modules have a defensible opt-in use case, and which must remain permanently denied?
  • How should mode-dependent capabilities such as staged-snapshot filesystem access interact with the opt-in?
  • Should an attempted opt-in fail synchronously during option validation or reject during worker startup?
  • When is a narrow hostFunction strictly preferable, and how should documentation guide that choice?

Acceptance criteria

  • Inventory every currently denied built-in and classify it as permanently denied or eligible for explicit opt-in, with rationale.
  • Document the chosen API and compare it with narrow hostFunctions, capability tokens, and unrestricted module allowlists.
  • Keep the no-option/default path byte-for-byte equivalent in effective authority to the default-deny policy.
  • Permit only identities and export surfaces already reviewed and pinned by the package; runtime drift remains fail closed.
  • Preserve Permission Model restrictions and prove that JavaScript configuration cannot grant missing OS permissions.
  • Cover every loading path and alias in one-shot script, persistent script, persistent module, staged-file one-shot, and staged-file module modes.
  • Add regressions for malformed options, inherited/accessor-backed values, proxies, symbols, prototype pollution, mutation, export resynchronization, admission recovery, and unsupported opt-ins.
  • Document compatibility, threat-model impact, non-overridable modules, migration guidance, and examples showing when to use a hostFunction instead.
  • Measure worker-startup and steady-state overhead.
  • Pass the full Linux, macOS, and Windows matrix on Node 26.5.1, the reviewed Node 26.8 API boundary, and current Node 26.x.

Activity

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

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions