Skip to content

Commit 916cfec

Browse files
j0t3xBridgeAR
authored andcommitted
lib,src: audit process.env in lib/ for setuid binary
Wrap SafeGetenv() in util binding with the purpose of protecting the cases when env vars are accessed with the privileges of another user in jsland. PR-URL: #18511 Fixes: #9160 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
1 parent ec9e792 commit 916cfec

File tree

4 files changed

+31
-7
lines changed

4 files changed

+31
-7
lines changed

lib/module.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const {
3434
internalModuleReadJSON,
3535
internalModuleStat
3636
} = process.binding('fs');
37+
const { safeGetenv } = process.binding('util');
3738
const internalModule = require('internal/module');
3839
const preserveSymlinks = !!process.binding('config').preserveSymlinks;
3940
const experimentalModules = !!process.binding('config').experimentalModules;
@@ -697,10 +698,13 @@ Module._initPaths = function() {
697698
const isWindows = process.platform === 'win32';
698699

699700
var homeDir;
701+
var nodePath;
700702
if (isWindows) {
701703
homeDir = process.env.USERPROFILE;
704+
nodePath = process.env.NODE_PATH;
702705
} else {
703-
homeDir = process.env.HOME;
706+
homeDir = safeGetenv('HOME');
707+
nodePath = safeGetenv('NODE_PATH');
704708
}
705709

706710
// $PREFIX/lib/node, where $PREFIX is the root of the Node.js installation.
@@ -719,7 +723,6 @@ Module._initPaths = function() {
719723
paths.unshift(path.resolve(homeDir, '.node_modules'));
720724
}
721725

722-
var nodePath = process.env.NODE_PATH;
723726
if (nodePath) {
724727
paths = nodePath.split(path.delimiter).filter(function(path) {
725728
return !!path;

lib/os.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
'use strict';
2323

24-
const { pushValToArrayMax } = process.binding('util');
24+
const { pushValToArrayMax, safeGetenv } = process.binding('util');
2525
const constants = process.binding('constants').os;
2626
const { deprecate } = require('internal/util');
2727
const { getCIDRSuffix } = require('internal/os');
@@ -127,9 +127,9 @@ function tmpdir() {
127127
if (path.length > 1 && path.endsWith('\\') && !path.endsWith(':\\'))
128128
path = path.slice(0, -1);
129129
} else {
130-
path = process.env.TMPDIR ||
131-
process.env.TMP ||
132-
process.env.TEMP ||
130+
path = safeGetenv('TMPDIR') ||
131+
safeGetenv('TMP') ||
132+
safeGetenv('TEMP') ||
133133
'/tmp';
134134
if (path.length > 1 && path.endsWith('/'))
135135
path = path.slice(0, -1);

src/node_util.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ using v8::Object;
1414
using v8::Private;
1515
using v8::Promise;
1616
using v8::Proxy;
17+
using v8::String;
1718
using v8::Value;
1819

1920

@@ -174,6 +175,16 @@ void PromiseReject(const FunctionCallbackInfo<Value>& args) {
174175
args.GetReturnValue().Set(ret.FromMaybe(false));
175176
}
176177

178+
void SafeGetenv(const FunctionCallbackInfo<Value>& args) {
179+
CHECK(args[0]->IsString());
180+
Utf8Value strenvtag(args.GetIsolate(), args[0]);
181+
std::string text;
182+
if (!node::SafeGetenv(*strenvtag, &text)) return;
183+
args.GetReturnValue()
184+
.Set(String::NewFromUtf8(
185+
args.GetIsolate(), text.c_str(),
186+
v8::NewStringType::kNormal).ToLocalChecked());
187+
}
177188

178189
void Initialize(Local<Object> target,
179190
Local<Value> unused,
@@ -225,6 +236,8 @@ void Initialize(Local<Object> target,
225236
env->SetMethod(target, "createPromise", CreatePromise);
226237
env->SetMethod(target, "promiseResolve", PromiseResolve);
227238
env->SetMethod(target, "promiseReject", PromiseReject);
239+
240+
env->SetMethod(target, "safeGetenv", SafeGetenv);
228241
}
229242

230243
} // namespace util

test/parallel/test-util-internal.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,17 @@ const fixtures = require('../common/fixtures');
88
const {
99
getHiddenValue,
1010
setHiddenValue,
11-
arrow_message_private_symbol: kArrowMessagePrivateSymbolIndex
11+
arrow_message_private_symbol: kArrowMessagePrivateSymbolIndex,
12+
safeGetenv
1213
} = process.binding('util');
1314

15+
for (const oneEnv in process.env) {
16+
assert.strictEqual(
17+
safeGetenv(oneEnv),
18+
process.env[oneEnv]
19+
);
20+
}
21+
1422
assert.strictEqual(
1523
getHiddenValue({}, kArrowMessagePrivateSymbolIndex),
1624
undefined);

0 commit comments

Comments
 (0)