Skip to content

Commit d274c3b

Browse files
tniessenRafaelGSS
authored andcommitted
crypto,https,tls: disable engines if perms enabled
When the experimental permission model is enabled, the running JavaScript code is subject to certain restrictions, all of which can be bypassed or even disabled by native code due to the nature of the permission model implementation. That is why Node.js native addons are disabled by default when the permission model is enabled. However, the built-in crypto, https, and tls modules still allow loading custom OpenSSL engines. Because OpenSSL engines can execute arbitrary (native) code while being loaded by Node.js, this has the same security implications as allowing native addons. In other words, allowing user code to load OpenSSL engines at runtime effectively enables bypassing any supposed security restrictions. This patch adds appropriate checks before attempting to dynamically load an OpenSSL engine that throw an error if the permission model is enabled. PR-URL: nodejs-private/node-private#409 Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> CVE-ID: CVE-2023-30586
1 parent 9c17e33 commit d274c3b

File tree

5 files changed

+26
-0
lines changed

5 files changed

+26
-0
lines changed

doc/api/permissions.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,8 @@ Wildcards are supported too:
544544
There are constraints you need to know before using this system:
545545

546546
* Native modules are restricted by default when using the Permission Model.
547+
* OpenSSL engines currently cannot be requested at runtime when the Permission
548+
Model is enabled, affecting the built-in crypto, https, and tls modules.
547549
* Relative paths are not supported through the CLI (`--allow-fs-*`).
548550
* The model does not inherit to a child node process.
549551
* The model does not inherit to a worker thread.

src/crypto/crypto_context.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,13 @@ void SecureContext::SetEngineKey(const FunctionCallbackInfo<Value>& args) {
648648

649649
CHECK_EQ(args.Length(), 2);
650650

651+
if (UNLIKELY(env->permission()->enabled())) {
652+
return THROW_ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED(
653+
env,
654+
"Programmatic selection of OpenSSL engines is unsupported while the "
655+
"experimental permission model is enabled");
656+
}
657+
651658
CryptoErrorStore errors;
652659
Utf8Value engine_id(env->isolate(), args[1]);
653660
EnginePointer engine = LoadEngineById(*engine_id, &errors);
@@ -1102,6 +1109,13 @@ void SecureContext::SetClientCertEngine(
11021109
// support multiple calls to SetClientCertEngine.
11031110
CHECK(!sc->client_cert_engine_provided_);
11041111

1112+
if (UNLIKELY(env->permission()->enabled())) {
1113+
return THROW_ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED(
1114+
env,
1115+
"Programmatic selection of OpenSSL engines is unsupported while the "
1116+
"experimental permission model is enabled");
1117+
}
1118+
11051119
CryptoErrorStore errors;
11061120
const Utf8Value engine_id(env->isolate(), args[0]);
11071121
EnginePointer engine = LoadEngineById(*engine_id, &errors);

src/crypto/crypto_util.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,13 @@ void SetEngine(const FunctionCallbackInfo<Value>& args) {
638638

639639
const node::Utf8Value engine_id(env->isolate(), args[0]);
640640

641+
if (UNLIKELY(env->permission()->enabled())) {
642+
return THROW_ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED(
643+
env,
644+
"Programmatic selection of OpenSSL engines is unsupported while the "
645+
"experimental permission model is enabled");
646+
}
647+
641648
args.GetReturnValue().Set(SetEngine(*engine_id, flags));
642649
}
643650
#endif // !OPENSSL_NO_ENGINE

src/node_errors.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ void AppendExceptionLine(Environment* env,
3737
V(ERR_CLOSED_MESSAGE_PORT, Error) \
3838
V(ERR_CONSTRUCT_CALL_REQUIRED, TypeError) \
3939
V(ERR_CONSTRUCT_CALL_INVALID, TypeError) \
40+
V(ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED, Error) \
4041
V(ERR_CRYPTO_INITIALIZATION_FAILED, Error) \
4142
V(ERR_CRYPTO_INVALID_AUTH_TAG, TypeError) \
4243
V(ERR_CRYPTO_INVALID_COUNTER, TypeError) \

src/permission/permission.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class Permission {
3939
return is_scope_granted(permission, res);
4040
}
4141

42+
FORCE_INLINE bool enabled() const { return enabled_; }
43+
4244
static PermissionScope StringToPermission(const std::string& perm);
4345
static const char* PermissionToString(PermissionScope perm);
4446
static void ThrowAccessDenied(Environment* env,

0 commit comments

Comments
 (0)