Skip to content

Support script-relative paths in allow-fs-read / allow-fs-write #59820

@davidje13

Description

@davidje13

What is the problem this feature will solve?

When creating a script with a shebang line, it can be desirable to add "hardening" flags to the script itself. For example:

#!/usr/bin/env -S node --permission --allow-fs-read=./content/*

// code here

Where we have a content directory which is a sibling of the script. This example works fine when the script is invoked from its own directory (e.g. ./myscript.js), but fails if invoked from another directory, because the --allow-fs-read path is relative to the current working directory, not the script itself.

There are obvious use-cases for both cwd-relative and script-relative paths, so it would be nice if the allow-fs-read and allow-fs-write flags could support both.

What is the feature you are proposing to solve the problem?

Support a prefix on the paths to make them relative to the entry script's directory, for example something like:

#!/usr/bin/env -S node --permission --allow-fs-read=$ENTRYDIR/content/*

where $ENTRYDIR is just an opaque prefix string, but designed to look like a shell variable to make its behaviour more obvious. Since existing valid paths all start with / or . (or X:\ on windows), this syntax should avoid changing anything for existing users (even if somebody has a directory called $ENTRYDIR which they wish to reference, it will currently be written as ./$ENTRYDIR, which will not trigger this behaviour).

This would not be compatible with --entry-url and would likely need to print an error or warning if used together.

There are many other CLI flags which take paths relative to the current working directory, so it would be nice to support a syntax which could be rolled out to all of them eventually.

What alternatives have you considered?

The prefix could be different to avoid potential confusion if users think it is a real environment variable. Some possibilities: entry-relative://content/*, <entry>/content/*, entrypoint:./content/*

This could also be achieved with new separate flags, such as --allow-fs-script-relative-read=./content/*, but this bloats the API, especially if the ability is rolled out to other flags.

Another permissions-model-specific possibility is allowing scripts to programmatically shed permissions (if that's possible with the underlying APIs?), which would enable code like this:

#!/usr/bin/env -S node --import --permission --allow-fs-read=*

import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';

process.permission.reduce('fs.read', [
  join(dirname(fileURLToPath(import.meta.url)), '*'),
]);

(which is potentially useful in other situations too, such as if a script needs to load a config file, but then never needs the filesystem again: it can shed the fs.read permission entirely once it is done with it)

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestIssues that request new features to be added to Node.js.

    Type

    No type

    Projects

    Status

    Awaiting Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions