Skip to content

permission: keep parent allowlist when Worker execArgv is empty - #65359

Open
yunshingng wants to merge 5 commits into
nodejs:mainfrom
yunshingng:permission-worker-execargv-inherit
Open

permission: keep parent allowlist when Worker execArgv is empty#65359
yunshingng wants to merge 5 commits into
nodejs:mainfrom
yunshingng:permission-worker-execargv-inherit

Conversation

@yunshingng

@yunshingng yunshingng commented Aug 17, 2026

Copy link
Copy Markdown

Description

Under --permission, creating a Worker with execArgv: [] could drop the parent's filesystem allowlist compared to a default Worker.

This change re-attaches parent Permission Model flags when execArgv is provided explicitly (including an empty array).

Test plan

  • test/parallel/test-permission-worker-empty-execargv.js
  • CI

cc @RafaelGSS

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/security-wg

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. worker Issues and PRs related to Worker support. labels Aug 17, 2026
@RafaelGSS RafaelGSS added the permission Issues and PRs related to the Permission Model label Aug 17, 2026

@RafaelGSS RafaelGSS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! However, I'm not sure this is something we should fix. The permission model doesn't inherit to worker threads by design.

--allow-child-process: if you grant it, you are trusting that code. We've been closing worker "bypass" reports as documented limitations for that reason.

Modifying execArgv is also a legit use case (giving the worker different flags than the parent), and this PR would remove that - we could argue that's a semver-major.

Even if we wanted inheritance, I don't think this approach works. Flags from NODE_OPTIONS don't show up in process.execArgv, so they wouldn't be copied at all. Repeated flags like --allow-fs-read=/a --allow-fs-read=/b only copy the first value (bug on this implementation)

So it gives the impression of inheritance without actually guaranteeing it, which IMO is worse than the current documented behavior. Doing this properly would mean enforcing it on the C++ side (intersection with the parent options) and it would likely be semver-major.

@yunshingng
yunshingng force-pushed the permission-worker-execargv-inherit branch from fc2103a to c7d385d Compare August 18, 2026 14:33
C++-side intersection after Worker option parse when the parent has the
Permission Model enabled:

- No JS process.execArgv copying (avoids NODE_OPTIONS / repeated-flag gaps)
- If the worker did not configure permission flags (e.g. execArgv: []),
  effective grants become the parent grant set
- If the worker configured permission flags, boolean and fs grants are
  intersected with the parent so the worker cannot exceed the parent
- Non-permission execArgv differences remain possible

May be semver-major relative to documented non-inheritance; for reviewer call.

Signed-off-by: yunshingng <yunshingng25@gmail.com>
@yunshingng
yunshingng force-pushed the permission-worker-execargv-inherit branch from c7d385d to bca44e6 Compare August 18, 2026 14:53
@yunshingng
yunshingng requested a review from RafaelGSS August 18, 2026 15:08
- Normalize path boundary checks for allow-list intersection
- Rewrite permission-related exec_argv to match clamped options
- Preserve non-permission execArgv entries
- Expand tests: --no-warnings, allow path success, repeated allows

Signed-off-by: yunshingng <yunshingng25@gmail.com>
@yunshingng

yunshingng commented Aug 18, 2026

Copy link
Copy Markdown
Author

Thanks for the review!— agreed this should be treated as semver-major if we change the
behavior.

The intent of the current diff is not a patch-level fix and not a security
advisory fix. It’s a deliberate model change: when the parent has the
Permission Model enabled, a Worker’s permission-related grants must not
exceed the parent (C++ intersection after option parse), including the
execArgv: [] case.

That avoids the incomplete JS execArgv copying approach (NODE_OPTIONS,
repeated --allow-*, false sense of inheritance).

Please treat / label this PR as semver-major. I’m happy to adjust the
implementation or tests for the major-line process you prefer.

Replace merged/broken helper text with a single clean implementation:
complete WorkerConfiguredPermission, one path-intersection loop, one
clamp call site, and exec_argv rewrite consistent with options.

Signed-off-by: yunshingng <yunshingng25@gmail.com>
- Normalize allow-list paths with PathResolve before prefix checks
- Case-insensitive path prefix matching on Windows
- Strip space-separated --allow-fs-read/--allow-fs-write path tokens
  from exec_argv when rewriting permission flags

Signed-off-by: yunshingng <yunshingng25@gmail.com>
Avoid treating longer distinct options that share a prefix
(e.g. --allow-fs-read-extra) as permission args when stripping/rewriting
exec_argv.

Signed-off-by: yunshingng <yunshingng25@gmail.com>

@yunshingng yunshingng left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some bug fixed , mostly done

@yunshingng

Copy link
Copy Markdown
Author

re: "doesn't inherit to a worker thread" — that's actually inconsistent with what the worker_threads doc says. It describes execArgv itself as "By default, options are inherited from the parent thread," and separately says workers pick up the parent's CLI flags automatically as long as you don't touch execArgv. --allow-fs-read etc are CLI flags, so a default Worker inheriting them is literally the documented behavior on that page. not arguing to change the design here, just that the two docs contradict each other right now regardless of what we land on.

separately: omit execArgv and you keep the parent's allowlist, pass execArgv: [] and you lose it. that's backwards — the more explicit/careful-looking code ends up less safe than doing nothing. feels worth fixing on its own, independent of the bigger inheritance question.

also curious — did this specific execArgv: [] vs omitted case come up in the past "documented limitation" closures, or were those about full inheritance? if it's the latter I don't think that precedent covers this one as-is.

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

Labels

needs-ci PRs that need a full CI run. permission Issues and PRs related to the Permission Model worker Issues and PRs related to Worker support.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants