Skip to content

Commit ec61426

Browse files
RafaelGSSHaxatron
andcommitted
permission: v8.writeHeapSnapshot and process.report
Co-Authored-By: haxatron <[email protected]>
1 parent b38bc9f commit ec61426

File tree

6 files changed

+73
-0
lines changed

6 files changed

+73
-0
lines changed

lib/internal/process/report.js

Lines changed: 2 additions & 0 deletions
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

Lines changed: 4 additions & 0 deletions
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,7 @@ void TriggerHeapSnapshot(const FunctionCallbackInfo<Value>& args) {
454455

455456
if (filename_v->IsUndefined()) {
456457
DiagnosticFilename name(env, "Heap", "heapsnapshot");
458+
// TODO(rafaelgss): resolve(name) and THROW_IF_INSUFFICIENT_PERMISSIONS
457459
if (WriteSnapshot(env, *name, options).IsNothing()) return;
458460
if (String::NewFromUtf8(isolate, *name).ToLocal(&filename_v)) {
459461
args.GetReturnValue().Set(filename_v);
@@ -463,6 +465,8 @@ void TriggerHeapSnapshot(const FunctionCallbackInfo<Value>& args) {
463465

464466
BufferValue path(isolate, filename_v);
465467
CHECK_NOT_NULL(*path);
468+
THROW_IF_INSUFFICIENT_PERMISSIONS(
469+
env, permission::PermissionScope::kFileSystemWrite, path.ToStringView());
466470
if (WriteSnapshot(env, *path, options).IsNothing()) return;
467471
return args.GetReturnValue().Set(filename_v);
468472
}

src/node_report.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,7 @@ std::string TriggerNodeReport(Isolate* isolate,
871871
filename = *DiagnosticFilename(
872872
env != nullptr ? env->thread_id() : 0, "report", "json");
873873
}
874+
// TODO(rafaelgss): resolve(filename) and THROW_IF_INSUFFICIENT_PERMISSIONS
874875
}
875876

876877
// Open the report file stream for writing. Supports stdout/err,

src/node_report_module.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "node_internals.h"
55
#include "node_options.h"
66
#include "node_report.h"
7+
#include "permission/permission.h"
78
#include "util-inl.h"
89

910
#include "handle_wrap.h"
@@ -44,6 +45,8 @@ void WriteReport(const FunctionCallbackInfo<Value>& info) {
4445
else
4546
error = Local<Value>();
4647

48+
THROW_IF_INSUFFICIENT_PERMISSIONS(
49+
env, permission::PermissionScope::kFileSystemWrite, filename);
4750
filename = TriggerNodeReport(env, *message, *trigger, filename, error);
4851
// Return value is the report filename
4952
info.GetReturnValue().Set(
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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.toNamespacedPath(path.resolve('./secret.txt')),
19+
}));
20+
}
21+
22+
{
23+
// TODO(rafaelgss): current working directory isn't supported
24+
// until path.resolve isn't available in C++
25+
assert.throws(() => {
26+
process.report.writeReport();
27+
}, common.expectsError({
28+
code: 'ERR_ACCESS_DENIED',
29+
permission: 'FileSystemWrite',
30+
}));
31+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
// TODO(rafaelgss): current working directory isn't supported
25+
// until path.resolve isn't available in C++
26+
assert.throws(() => {
27+
v8.writeHeapSnapshot();
28+
}, common.expectsError({
29+
code: 'ERR_ACCESS_DENIED',
30+
permission: 'FileSystemWrite',
31+
}));
32+
}

0 commit comments

Comments
 (0)