Commit 02bae370c16 for nodejs
commit 02bae370c1618609aa17bb8b29e0a749f8a042e5
Author: Rafael Gonzaga <rafael.nunu@hotmail.com>
Date: Tue Oct 13 10:33:55 2026 -0300
permission: keep explicit fs grants when dropping a covering directory
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: https://github.com/nodejs/node/pull/66556
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
diff --git a/src/permission/fs_permission.cc b/src/permission/fs_permission.cc
index 6293844476f..0baf1291a96 100644
--- a/src/permission/fs_permission.cc
+++ b/src/permission/fs_permission.cc
@@ -218,15 +218,25 @@ void FSPermission::RebuildTree(PermissionScope scope) {
void FSPermission::GrantAccess(PermissionScope perm, const std::string& res) {
const std::string path = WildcardIfDir(res);
- if (perm == PermissionScope::kFileSystemRead &&
- !granted_in_fs_.Lookup(path)) {
- granted_in_fs_.Insert(path);
- granted_paths_in_.push_back(path);
+ // Track every explicit grant, even when already covered by another one,
+ // so that it still applies if the covering grant is dropped later.
+ if (perm == PermissionScope::kFileSystemRead) {
+ if (std::find(granted_paths_in_.begin(), granted_paths_in_.end(), path) ==
+ granted_paths_in_.end()) {
+ granted_paths_in_.push_back(path);
+ }
+ if (!granted_in_fs_.Lookup(path)) {
+ granted_in_fs_.Insert(path);
+ }
deny_all_in_ = false;
- } else if (perm == PermissionScope::kFileSystemWrite &&
- !granted_out_fs_.Lookup(path)) {
- granted_out_fs_.Insert(path);
- granted_paths_out_.push_back(path);
+ } else if (perm == PermissionScope::kFileSystemWrite) {
+ if (std::find(granted_paths_out_.begin(), granted_paths_out_.end(), path) ==
+ granted_paths_out_.end()) {
+ granted_paths_out_.push_back(path);
+ }
+ if (!granted_out_fs_.Lookup(path)) {
+ granted_out_fs_.Insert(path);
+ }
deny_all_out_ = false;
}
}
diff --git a/test/parallel/test-permission-drop-fs-granted-path.js b/test/parallel/test-permission-drop-fs-granted-path.js
index a011944cd0d..fdb9b194979 100644
--- a/test/parallel/test-permission-drop-fs-granted-path.js
+++ b/test/parallel/test-permission-drop-fs-granted-path.js
@@ -133,6 +133,40 @@ fs.writeFileSync(path.join(dir, 'item2.txt'), 'bbb');
assert.strictEqual(child.status, 0);
}
+// Grant a directory and a file inside it separately, drop the directory
+// the explicit file grant still applies regardless of the flag order
+for (const files of [
+ [dir, path.join(dir, 'item1.txt')],
+ [path.join(dir, 'item1.txt'), dir],
+]) {
+ const child = spawnSync(process.execPath, [
+ '--permission',
+ ...files.map((file) => `--allow-fs-read=${file}`),
+ ...files.map((file) => `--allow-fs-write=${file}`),
+ '-e',
+ `
+ const assert = require('assert');
+ const fs = require('fs');
+ const dir = ${JSON.stringify(dir)};
+
+ for (const scope of ['fs.read', 'fs.write']) {
+ assert.ok(process.permission.has(scope, dir + '/item1.txt'));
+ assert.ok(process.permission.has(scope, dir + '/item2.txt'));
+
+ process.permission.drop(scope, dir);
+
+ assert.ok(process.permission.has(scope, dir + '/item1.txt'));
+ assert.ok(!process.permission.has(scope, dir + '/item2.txt'));
+ }
+ assert.strictEqual(fs.readFileSync(dir + '/item1.txt', 'utf8'), 'aaa');
+ `,
+ ]);
+ if (child.status !== 0) {
+ console.error('Case 5 stderr:', child.stderr?.toString());
+ }
+ assert.strictEqual(child.status, 0);
+}
+
// Drop entire scope without reference - revokes everything
{
const child = spawnSync(process.execPath, [