Skip to content

Commit 4f8badc

Browse files
RafaelGSSHaxatron
authored andcommitted
permission: v8.writeHeapSnapshot and process.report
Co-Authored-By: haxatron <[email protected]> Signed-off-by: RafaelGSS <[email protected]> PR-URL: nodejs#48564 Reviewed-By: Paolo Insogna <[email protected]> Reviewed-By: Marco Ippolito <[email protected]>
1 parent 0b0a5ee commit 4f8badc

File tree

5 files changed

+77
-0
lines changed

5 files changed

+77
-0
lines changed

lib/internal/process/report.js

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
const {
33
ERR_SYNTHETIC,
44
} = require('internal/errors').codes;
5+
const { getValidatedPath } = require('internal/fs/utils');
56
const {
67
validateBoolean,
78
validateObject,
@@ -19,6 +20,7 @@ const report = {
1920
file = undefined;
2021
} else if (file !== undefined) {
2122
validateString(file, 'file');
23+
file = getValidatedPath(file);
2224
}
2325

2426
if (err === undefined) {

src/heap_utils.cc

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "env-inl.h"
33
#include "memory_tracker-inl.h"
44
#include "node_external_reference.h"
5+
#include "permission/permission.h"
56
#include "stream_base-inl.h"
67
#include "util-inl.h"
78

@@ -454,6 +455,8 @@ void TriggerHeapSnapshot(const FunctionCallbackInfo<Value>& args) {
454455

455456
if (filename_v->IsUndefined()) {
456457
DiagnosticFilename name(env, "Heap", "heapsnapshot");
458+
THROW_IF_INSUFFICIENT_PERMISSIONS(
459+
env, permission::PermissionScope::kFileSystemWrite, env->GetCwd());
457460
if (WriteSnapshot(env, *name, options).IsNothing()) return;
458461
if (String::NewFromUtf8(isolate, *name).ToLocal(&filename_v)) {
459462
args.GetReturnValue().Set(filename_v);
@@ -463,6 +466,8 @@ void TriggerHeapSnapshot(const FunctionCallbackInfo<Value>& args) {
463466

464467
BufferValue path(isolate, filename_v);
465468
CHECK_NOT_NULL(*path);
469+
THROW_IF_INSUFFICIENT_PERMISSIONS(
470+
env, permission::PermissionScope::kFileSystemWrite, path.ToStringView());
466471
if (WriteSnapshot(env, *path, options).IsNothing()) return;
467472
return args.GetReturnValue().Set(filename_v);
468473
}

src/node_report.cc

+10
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "node_metadata.h"
88
#include "node_mutex.h"
99
#include "node_worker.h"
10+
#include "permission/permission.h"
1011
#include "util.h"
1112

1213
#ifdef _WIN32
@@ -856,6 +857,8 @@ std::string TriggerNodeReport(Isolate* isolate,
856857
// Determine the required report filename. In order of priority:
857858
// 1) supplied on API 2) configured on startup 3) default generated
858859
if (!name.empty()) {
860+
THROW_IF_INSUFFICIENT_PERMISSIONS(
861+
env, permission::PermissionScope::kFileSystemWrite, name, name);
859862
// Filename was specified as API parameter.
860863
filename = name;
861864
} else {
@@ -871,6 +874,13 @@ std::string TriggerNodeReport(Isolate* isolate,
871874
filename = *DiagnosticFilename(
872875
env != nullptr ? env->thread_id() : 0, "report", "json");
873876
}
877+
if (env != nullptr) {
878+
THROW_IF_INSUFFICIENT_PERMISSIONS(
879+
env,
880+
permission::PermissionScope::kFileSystemWrite,
881+
std::string_view(env->GetCwd()),
882+
filename);
883+
}
874884
}
875885

876886
// Open the report file stream for writing. Supports stdout/err,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Flags: --experimental-permission --allow-fs-read=*
2+
'use strict';
3+
4+
const common = require('../common');
5+
common.skipIfWorker();
6+
if (!common.hasCrypto)
7+
common.skip('no crypto');
8+
9+
const assert = require('assert');
10+
const path = require('path');
11+
12+
{
13+
assert.throws(() => {
14+
process.report.writeReport('./secret.txt');
15+
}, common.expectsError({
16+
code: 'ERR_ACCESS_DENIED',
17+
permission: 'FileSystemWrite',
18+
resource: path.resolve('./secret.txt'),
19+
}));
20+
}
21+
22+
{
23+
assert.throws(() => {
24+
process.report.writeReport();
25+
}, common.expectsError({
26+
code: 'ERR_ACCESS_DENIED',
27+
permission: 'FileSystemWrite',
28+
resource: process.cwd(),
29+
}));
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Flags: --experimental-permission --allow-fs-read=*
2+
'use strict';
3+
4+
const common = require('../common');
5+
common.skipIfWorker();
6+
if (!common.hasCrypto)
7+
common.skip('no crypto');
8+
9+
const assert = require('assert');
10+
const v8 = require('v8');
11+
const path = require('path');
12+
13+
{
14+
assert.throws(() => {
15+
v8.writeHeapSnapshot('./secret.txt');
16+
}, common.expectsError({
17+
code: 'ERR_ACCESS_DENIED',
18+
permission: 'FileSystemWrite',
19+
resource: path.toNamespacedPath(path.resolve('./secret.txt')),
20+
}));
21+
}
22+
23+
{
24+
assert.throws(() => {
25+
v8.writeHeapSnapshot();
26+
}, common.expectsError({
27+
code: 'ERR_ACCESS_DENIED',
28+
permission: 'FileSystemWrite',
29+
}));
30+
}

0 commit comments

Comments
 (0)