feat(permissions): add --deny-module for per-module permission restrictions
Adds a `--deny-module=<pattern>:<perms>` flag that denies specific runtime
permissions to modules matched by `<pattern>` on the JS call stack at the
moment a permission-checked op is invoked. This implements stack-inspection
style per-module permissions on top of V8's existing op-stack-trace plumbing.
Examples:
deno run --deny-module=npm:chalk:all main.ts
deno run --deny-module=npm:lodash:net,run main.ts
deno run --deny-module=jsr:@scope/pkg:write main.ts
deno run --deny-module=https://untrusted.example.com/:net main.ts
When a denied module is found anywhere on the JS call stack at the moment a
permission op runs, the requested permission is rejected regardless of the
process-wide allowlist. Behavior is opt-in: zero-cost when no rules are
configured, since the runtime only enables stack-trace capture if at least
one --deny-module rule exists.
Pattern syntax:
* `npm:<name>` — matches `npm:<name>[@version][/...]` specifiers and
`file:.../node_modules/<name>/...` paths.
* `jsr:<scope>/<name>` — matches `jsr:<scope>/<name>...` specifiers.
* Anything else — literal substring match against the script URL.
Permission kinds accepted: read, write, net, env, sys, run, ffi, import, all.
Closes denoland/orchid#64
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>