Skip to content

Commit ad5d803

Browse files
committed
src,permission: make ERR_ACCESS_DENIED more descriptive
This commit also adds a suggestion flag (if exists) when ERR_ACCESS_DENIED is thrown, so users don't need to jump into the documentation to see how to manage that permission error. PR-URL: #57585 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 9dd90cc commit ad5d803

8 files changed

+55
-16
lines changed

src/permission/permission.cc

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,15 @@ static void Has(const FunctionCallbackInfo<Value>& args) {
5959

6060
} // namespace
6161

62-
#define V(Name, label, _) \
62+
#define V(Name, label, _, __) \
6363
if (perm == PermissionScope::k##Name) return #Name;
6464
const char* Permission::PermissionToString(const PermissionScope perm) {
6565
PERMISSIONS(V)
6666
return nullptr;
6767
}
6868
#undef V
6969

70-
#define V(Name, label, _) \
70+
#define V(Name, label, _, __) \
7171
if (perm == label) return PermissionScope::k##Name;
7272
PermissionScope Permission::StringToPermission(const std::string& perm) {
7373
PERMISSIONS(V)
@@ -84,32 +84,47 @@ Permission::Permission() : enabled_(false) {
8484
std::shared_ptr<PermissionBase> inspector =
8585
std::make_shared<InspectorPermission>();
8686
std::shared_ptr<PermissionBase> wasi = std::make_shared<WASIPermission>();
87-
#define V(Name, _, __) \
87+
#define V(Name, _, __, ___) \
8888
nodes_.insert(std::make_pair(PermissionScope::k##Name, fs));
8989
FILESYSTEM_PERMISSIONS(V)
9090
#undef V
91-
#define V(Name, _, __) \
91+
#define V(Name, _, __, ___) \
9292
nodes_.insert(std::make_pair(PermissionScope::k##Name, child_p));
9393
CHILD_PROCESS_PERMISSIONS(V)
9494
#undef V
95-
#define V(Name, _, __) \
95+
#define V(Name, _, __, ___) \
9696
nodes_.insert(std::make_pair(PermissionScope::k##Name, worker_t));
9797
WORKER_THREADS_PERMISSIONS(V)
9898
#undef V
99-
#define V(Name, _, __) \
99+
#define V(Name, _, __, ___) \
100100
nodes_.insert(std::make_pair(PermissionScope::k##Name, inspector));
101101
INSPECTOR_PERMISSIONS(V)
102102
#undef V
103-
#define V(Name, _, __) \
103+
#define V(Name, _, __, ___) \
104104
nodes_.insert(std::make_pair(PermissionScope::k##Name, wasi));
105105
WASI_PERMISSIONS(V)
106106
#undef V
107107
}
108108

109+
const char* GetErrorFlagSuggestion(node::permission::PermissionScope perm) {
110+
switch (perm) {
111+
#define V(Name, _, __, Flag) \
112+
case node::permission::PermissionScope::k##Name: \
113+
return Flag[0] != '\0' ? "Use " Flag " to manage permissions." : "";
114+
PERMISSIONS(V)
115+
#undef V
116+
default:
117+
return "";
118+
}
119+
}
120+
109121
MaybeLocal<Value> CreateAccessDeniedError(Environment* env,
110122
PermissionScope perm,
111123
const std::string_view& res) {
112-
Local<Object> err = ERR_ACCESS_DENIED(env->isolate());
124+
const char* suggestion = GetErrorFlagSuggestion(perm);
125+
Local<Object> err = ERR_ACCESS_DENIED(
126+
env->isolate(), "Access to this API has been restricted. %s", suggestion);
127+
113128
Local<Value> perm_string;
114129
Local<Value> resource_string;
115130
std::string_view perm_str = Permission::PermissionToString(perm);

src/permission/permission_base.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,19 @@ class Environment;
1515
namespace permission {
1616

1717
#define FILESYSTEM_PERMISSIONS(V) \
18-
V(FileSystem, "fs", PermissionsRoot) \
19-
V(FileSystemRead, "fs.read", FileSystem) \
20-
V(FileSystemWrite, "fs.write", FileSystem)
18+
V(FileSystem, "fs", PermissionsRoot, "") \
19+
V(FileSystemRead, "fs.read", FileSystem, "--allow-fs-read") \
20+
V(FileSystemWrite, "fs.write", FileSystem, "--allow-fs-write")
2121

22-
#define CHILD_PROCESS_PERMISSIONS(V) V(ChildProcess, "child", PermissionsRoot)
22+
#define CHILD_PROCESS_PERMISSIONS(V) \
23+
V(ChildProcess, "child", PermissionsRoot, "--allow-child-process")
2324

24-
#define WASI_PERMISSIONS(V) V(WASI, "wasi", PermissionsRoot)
25+
#define WASI_PERMISSIONS(V) V(WASI, "wasi", PermissionsRoot, "--allow-wasi")
2526

2627
#define WORKER_THREADS_PERMISSIONS(V) \
27-
V(WorkerThreads, "worker", PermissionsRoot)
28+
V(WorkerThreads, "worker", PermissionsRoot, "--allow-worker")
2829

29-
#define INSPECTOR_PERMISSIONS(V) V(Inspector, "inspector", PermissionsRoot)
30+
#define INSPECTOR_PERMISSIONS(V) V(Inspector, "inspector", PermissionsRoot, "")
3031

3132
#define PERMISSIONS(V) \
3233
FILESYSTEM_PERMISSIONS(V) \
@@ -35,7 +36,7 @@ namespace permission {
3536
WORKER_THREADS_PERMISSIONS(V) \
3637
INSPECTOR_PERMISSIONS(V)
3738

38-
#define V(name, _, __) k##name,
39+
#define V(name, _, __, ___) k##name,
3940
enum class PermissionScope {
4041
kPermissionsRoot = -1,
4142
PERMISSIONS(V) kPermissionsCount

test/fixtures/permission/fs-read.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@ const blockedFolder = process.env.BLOCKEDFOLDER;
1414
const allowedFolder = process.env.ALLOWEDFOLDER;
1515
const regularFile = __filename;
1616

17+
// Guarantee the error message suggest the --allow-fs-read
18+
{
19+
fs.readFile(blockedFile, common.expectsError({
20+
message: 'Access to this API has been restricted. Use --allow-fs-read to manage permissions.',
21+
code: 'ERR_ACCESS_DENIED',
22+
permission: 'FileSystemRead',
23+
resource: path.toNamespacedPath(blockedFile),
24+
}));
25+
}
26+
1727
// fs.readFile
1828
{
1929
fs.readFile(blockedFile, common.expectsError({

test/fixtures/permission/fs-write.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER;
2525
assert.ok(!process.permission.has('fs.write', blockedFile));
2626
}
2727

28+
// Guarantee the error message suggest the --allow-fs-write
29+
{
30+
fs.writeFile(blockedFile, 'example', common.expectsError({
31+
message: 'Access to this API has been restricted. Use --allow-fs-write to manage permissions.',
32+
code: 'ERR_ACCESS_DENIED',
33+
permission: 'FileSystemWrite',
34+
}));
35+
}
36+
2837
// fs.writeFile
2938
{
3039
assert.throws(() => {

test/parallel/test-permission-child-process-cli.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ if (process.argv[2] === 'child') {
2626
assert.throws(() => {
2727
childProcess.spawn(process.execPath, ['--version']);
2828
}, common.expectsError({
29+
message: 'Access to this API has been restricted. Use --allow-child-process to manage permissions.',
2930
code: 'ERR_ACCESS_DENIED',
3031
permission: 'ChildProcess',
3132
}));

test/parallel/test-permission-inspector.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ if (!common.hasCrypto)
2222
const session = new Session();
2323
session.connect();
2424
}, common.expectsError({
25+
message: 'Access to this API has been restricted. ',
2526
code: 'ERR_ACCESS_DENIED',
2627
permission: 'Inspector',
2728
}));

test/parallel/test-permission-wasi.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const { WASI } = require('wasi');
1313
preopens: { '/': '/' },
1414
});
1515
}, common.expectsError({
16+
message: 'Access to this API has been restricted. Use --allow-wasi to manage permissions.',
1617
code: 'ERR_ACCESS_DENIED',
1718
permission: 'WASI',
1819
}));

test/parallel/test-permission-worker-threads-cli.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ if (isMainThread) {
2222
assert.throws(() => {
2323
new Worker(__filename);
2424
}, common.expectsError({
25+
message: 'Access to this API has been restricted. Use --allow-worker to manage permissions.',
2526
code: 'ERR_ACCESS_DENIED',
2627
permission: 'WorkerThreads',
2728
}));

0 commit comments

Comments
 (0)