mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
src: pass resource on permission checks for spawn
This commit enhances the permission model errors when no --allow-child-process is used and the error is emitted. Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com> PR-URL: https://github.com/nodejs/node/pull/58758 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Edy Silva <edigleyssonsilva@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
This commit is contained in:
parent
e679e38b25
commit
b04c4a44a5
|
|
@ -518,9 +518,6 @@ static void Execve(const FunctionCallbackInfo<Value>& args) {
|
||||||
Isolate* isolate = env->isolate();
|
Isolate* isolate = env->isolate();
|
||||||
Local<Context> context = env->context();
|
Local<Context> context = env->context();
|
||||||
|
|
||||||
THROW_IF_INSUFFICIENT_PERMISSIONS(
|
|
||||||
env, permission::PermissionScope::kChildProcess, "");
|
|
||||||
|
|
||||||
CHECK(args[0]->IsString());
|
CHECK(args[0]->IsString());
|
||||||
CHECK(args[1]->IsArray());
|
CHECK(args[1]->IsArray());
|
||||||
CHECK(args[2]->IsArray());
|
CHECK(args[2]->IsArray());
|
||||||
|
|
@ -530,6 +527,11 @@ static void Execve(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
|
||||||
// Copy arguments and environment
|
// Copy arguments and environment
|
||||||
Utf8Value executable(isolate, args[0]);
|
Utf8Value executable(isolate, args[0]);
|
||||||
|
|
||||||
|
THROW_IF_INSUFFICIENT_PERMISSIONS(env,
|
||||||
|
permission::PermissionScope::kChildProcess,
|
||||||
|
executable.ToStringView());
|
||||||
|
|
||||||
std::vector<std::string> argv_strings(argv_array->Length());
|
std::vector<std::string> argv_strings(argv_array->Length());
|
||||||
std::vector<std::string> envp_strings(envp_array->Length());
|
std::vector<std::string> envp_strings(envp_array->Length());
|
||||||
std::vector<char*> argv(argv_array->Length() + 1);
|
std::vector<char*> argv(argv_array->Length() + 1);
|
||||||
|
|
|
||||||
|
|
@ -186,8 +186,6 @@ class ProcessWrap : public HandleWrap {
|
||||||
Local<Context> context = env->context();
|
Local<Context> context = env->context();
|
||||||
ProcessWrap* wrap;
|
ProcessWrap* wrap;
|
||||||
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.This());
|
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.This());
|
||||||
THROW_IF_INSUFFICIENT_PERMISSIONS(
|
|
||||||
env, permission::PermissionScope::kChildProcess, "");
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (!args[0]->IsObject()) {
|
if (!args[0]->IsObject()) {
|
||||||
|
|
@ -201,6 +199,20 @@ class ProcessWrap : public HandleWrap {
|
||||||
|
|
||||||
options.exit_cb = OnExit;
|
options.exit_cb = OnExit;
|
||||||
|
|
||||||
|
// TODO(bnoordhuis) is this possible to do without mallocing ?
|
||||||
|
|
||||||
|
// options.file
|
||||||
|
Local<Value> file_v;
|
||||||
|
if (!js_options->Get(context, env->file_string()).ToLocal(&file_v)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CHECK(file_v->IsString());
|
||||||
|
node::Utf8Value file(env->isolate(), file_v);
|
||||||
|
options.file = *file;
|
||||||
|
|
||||||
|
THROW_IF_INSUFFICIENT_PERMISSIONS(
|
||||||
|
env, permission::PermissionScope::kChildProcess, file.ToStringView());
|
||||||
|
|
||||||
// options.uid
|
// options.uid
|
||||||
Local<Value> uid_v;
|
Local<Value> uid_v;
|
||||||
if (!js_options->Get(context, env->uid_string()).ToLocal(&uid_v)) {
|
if (!js_options->Get(context, env->uid_string()).ToLocal(&uid_v)) {
|
||||||
|
|
@ -225,17 +237,6 @@ class ProcessWrap : public HandleWrap {
|
||||||
options.gid = static_cast<uv_gid_t>(gid);
|
options.gid = static_cast<uv_gid_t>(gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bnoordhuis) is this possible to do without mallocing ?
|
|
||||||
|
|
||||||
// options.file
|
|
||||||
Local<Value> file_v;
|
|
||||||
if (!js_options->Get(context, env->file_string()).ToLocal(&file_v)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CHECK(file_v->IsString());
|
|
||||||
node::Utf8Value file(env->isolate(), file_v);
|
|
||||||
options.file = *file;
|
|
||||||
|
|
||||||
// Undocumented feature of Win32 CreateProcess API allows spawning
|
// Undocumented feature of Win32 CreateProcess API allows spawning
|
||||||
// batch files directly but is potentially insecure because arguments
|
// batch files directly but is potentially insecure because arguments
|
||||||
// are not escaped (and sometimes cannot be unambiguously escaped),
|
// are not escaped (and sometimes cannot be unambiguously escaped),
|
||||||
|
|
|
||||||
|
|
@ -378,8 +378,24 @@ void SyncProcessRunner::RegisterExternalReferences(
|
||||||
|
|
||||||
void SyncProcessRunner::Spawn(const FunctionCallbackInfo<Value>& args) {
|
void SyncProcessRunner::Spawn(const FunctionCallbackInfo<Value>& args) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
|
Local<Context> context = env->context();
|
||||||
|
|
||||||
|
std::string resource = "";
|
||||||
|
if (env->permission()->enabled() && args[0]->IsObject()) {
|
||||||
|
Local<Object> js_options = args[0].As<Object>();
|
||||||
|
Local<Value> js_file;
|
||||||
|
if (!js_options->Get(context, env->file_string()).ToLocal(&js_file)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (js_file->IsString()) {
|
||||||
|
node::Utf8Value executable(env->isolate(), js_file.As<String>());
|
||||||
|
resource = executable.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
THROW_IF_INSUFFICIENT_PERMISSIONS(
|
THROW_IF_INSUFFICIENT_PERMISSIONS(
|
||||||
env, permission::PermissionScope::kChildProcess, "");
|
env, permission::PermissionScope::kChildProcess, resource);
|
||||||
env->PrintSyncTrace();
|
env->PrintSyncTrace();
|
||||||
SyncProcessRunner p(env);
|
SyncProcessRunner p(env);
|
||||||
Local<Value> result;
|
Local<Value> result;
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,14 @@ if (process.argv[2] === 'child') {
|
||||||
message: 'Access to this API has been restricted. Use --allow-child-process to manage permissions.',
|
message: 'Access to this API has been restricted. Use --allow-child-process to manage permissions.',
|
||||||
code: 'ERR_ACCESS_DENIED',
|
code: 'ERR_ACCESS_DENIED',
|
||||||
permission: 'ChildProcess',
|
permission: 'ChildProcess',
|
||||||
|
resource: process.execPath,
|
||||||
}));
|
}));
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
childProcess.spawnSync(process.execPath, ['--version']);
|
childProcess.spawnSync(process.execPath, ['--version']);
|
||||||
}, common.expectsError({
|
}, common.expectsError({
|
||||||
code: 'ERR_ACCESS_DENIED',
|
code: 'ERR_ACCESS_DENIED',
|
||||||
permission: 'ChildProcess',
|
permission: 'ChildProcess',
|
||||||
|
resource: process.execPath,
|
||||||
}));
|
}));
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
childProcess.exec(...common.escapePOSIXShell`"${process.execPath}" --version`);
|
childProcess.exec(...common.escapePOSIXShell`"${process.execPath}" --version`);
|
||||||
|
|
@ -53,6 +55,7 @@ if (process.argv[2] === 'child') {
|
||||||
}, common.expectsError({
|
}, common.expectsError({
|
||||||
code: 'ERR_ACCESS_DENIED',
|
code: 'ERR_ACCESS_DENIED',
|
||||||
permission: 'ChildProcess',
|
permission: 'ChildProcess',
|
||||||
|
resource: process.execPath,
|
||||||
}));
|
}));
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
childProcess.execFile(...common.escapePOSIXShell`"${process.execPath}" --version`);
|
childProcess.execFile(...common.escapePOSIXShell`"${process.execPath}" --version`);
|
||||||
|
|
|
||||||
|
|
@ -17,5 +17,5 @@ if (process.argv[2] === 'replaced') {
|
||||||
} else {
|
} else {
|
||||||
throws(mustCall(() => {
|
throws(mustCall(() => {
|
||||||
process.execve(process.execPath, [process.execPath, __filename, 'replaced'], process.env);
|
process.execve(process.execPath, [process.execPath, __filename, 'replaced'], process.env);
|
||||||
}), { code: 'ERR_ACCESS_DENIED', permission: 'ChildProcess' });
|
}), { code: 'ERR_ACCESS_DENIED', permission: 'ChildProcess', resource: process.execPath });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user