Skip to content

Commit 6de2673

Browse files
committed
lib: enable global WebCrypto by default
Enables `--experimental-global-webcrypto` by default, and ensures that the classic `node:crypto` core module is still available in `--eval` or `--print` contexts. PR-URL: #42083 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Filip Skokan <panva.ip@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com>
1 parent 572d556 commit 6de2673

16 files changed

Lines changed: 203 additions & 37 deletions

‎.eslintrc.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ module.exports = {
322322
CompressionStream: 'readable',
323323
CountQueuingStrategy: 'readable',
324324
CustomEvent: 'readable',
325+
crypto: 'readable',
325326
Crypto: 'readable',
326327
CryptoKey: 'readable',
327328
DecompressionStream: 'readable',

‎doc/api/cli.md‎

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -351,16 +351,6 @@ added:
351351

352352
Expose the [CustomEvent Web API][] on the global scope.
353353

354-
### `--experimental-global-webcrypto`
355-
356-
<!-- YAML
357-
added:
358-
- v17.6.0
359-
- v16.15.0
360-
-->
361-
362-
Expose the [Web Crypto API][] on the global scope.
363-
364354
### `--experimental-import-meta-resolve`
365355

366356
<!-- YAML
@@ -413,6 +403,14 @@ added: v18.0.0
413403

414404
Disable experimental support for the [Fetch API][].
415405

406+
### `--no-experimental-global-webcrypto`
407+
408+
<!-- YAML
409+
added: REPLACEME
410+
-->
411+
412+
Disable exposition of [Web Crypto API][] on the global scope.
413+
416414
### `--no-experimental-repl-await`
417415

418416
<!-- YAML
@@ -1839,7 +1837,6 @@ Node.js options that are allowed are:
18391837
*`--enable-source-maps`
18401838
*`--experimental-abortcontroller`
18411839
*`--experimental-global-customevent`
1842-
*`--experimental-global-webcrypto`
18431840
*`--experimental-import-meta-resolve`
18441841
*`--experimental-json-modules`
18451842
*`--experimental-loader`
@@ -1872,6 +1869,7 @@ Node.js options that are allowed are:
18721869
*`--no-addons`
18731870
*`--no-deprecation`
18741871
*`--no-experimental-fetch`
1872+
*`--no-experimental-global-webcrypto`
18751873
*`--no-experimental-repl-await`
18761874
*`--no-extra-info-on-fatal-exception`
18771875
*`--no-force-async-hooks-checks`

‎doc/api/globals.md‎

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -345,10 +345,14 @@ A browser-compatible implementation of [`CountQueuingStrategy`][].
345345
added:
346346
- v17.6.0
347347
- v16.15.0
348+
changes:
349+
- version: REPLACEME
350+
pr-url: https://github.com/nodejs/node/pull/42083
351+
description: No longer behind `--experimental-global-webcrypto` CLI flag.
348352
-->
349353

350-
> Stability: 1 - Experimental. Enable this API with the
351-
> [`--experimental-global-webcrypto`][] CLI flag.
354+
> Stability: 1 - Experimental. Disable this API with the
355+
> [`--no-experimental-global-webcrypto`][] CLI flag.
352356
353357
A browser-compatible implementation of {Crypto}. This global is available
354358
only if the Node.js binary was compiled with including support for the
@@ -360,10 +364,14 @@ only if the Node.js binary was compiled with including support for the
360364
added:
361365
- v17.6.0
362366
- v16.15.0
367+
changes:
368+
- version: REPLACEME
369+
pr-url: https://github.com/nodejs/node/pull/42083
370+
description: No longer behind `--experimental-global-webcrypto` CLI flag.
363371
-->
364372

365-
> Stability: 1 - Experimental. Enable this API with the
366-
> [`--experimental-global-webcrypto`][] CLI flag.
373+
> Stability: 1 - Experimental. Disable this API with the
374+
> [`--no-experimental-global-webcrypto`][] CLI flag.
367375
368376
A browser-compatible implementation of the [Web Crypto API][].
369377

@@ -373,10 +381,14 @@ A browser-compatible implementation of the [Web Crypto API][].
373381
added:
374382
- v17.6.0
375383
- v16.15.0
384+
changes:
385+
- version: REPLACEME
386+
pr-url: https://github.com/nodejs/node/pull/42083
387+
description: No longer behind `--experimental-global-webcrypto` CLI flag.
376388
-->
377389

378-
> Stability: 1 - Experimental. Enable this API with the
379-
> [`--experimental-global-webcrypto`][] CLI flag.
390+
> Stability: 1 - Experimental. Disable this API with the
391+
> [`--no-experimental-global-webcrypto`][] CLI flag.
380392
381393
A browser-compatible implementation of {CryptoKey}. This global is available
382394
only if the Node.js binary was compiled with including support for the
@@ -725,10 +737,14 @@ The WHATWG [`structuredClone`][] method.
725737
added:
726738
- v17.6.0
727739
- v16.15.0
740+
changes:
741+
- version: REPLACEME
742+
pr-url: https://github.com/nodejs/node/pull/42083
743+
description: No longer behind `--experimental-global-webcrypto` CLI flag.
728744
-->
729745

730-
> Stability: 1 - Experimental. Enable this API with the
731-
> [`--experimental-global-webcrypto`][] CLI flag.
746+
> Stability: 1 - Experimental. Disable this API with the
747+
> [`--no-experimental-global-webcrypto`][] CLI flag.
732748
733749
A browser-compatible implementation of {SubtleCrypto}. This global is available
734750
only if the Node.js binary was compiled with including support for the
@@ -870,8 +886,8 @@ A browser-compatible implementation of [`WritableStreamDefaultWriter`][].
870886

871887
[Web Crypto API]: webcrypto.md
872888
[`--experimental-global-customevent`]: cli.md#--experimental-global-customevent
873-
[`--experimental-global-webcrypto`]: cli.md#--experimental-global-webcrypto
874889
[`--no-experimental-fetch`]: cli.md#--no-experimental-fetch
890+
[`--no-experimental-global-webcrypto`]: cli.md#--no-experimental-global-webcrypto
875891
[`AbortController`]: https://developer.mozilla.org/en-US/docs/Web/API/AbortController
876892
[`ByteLengthQueuingStrategy`]: webstreams.md#class-bytelengthqueuingstrategy
877893
[`CompressionStream`]: webstreams.md#class-compressionstream

‎doc/node.1‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ Use this flag to enable ShadowRealm support.
165165
.ItFl-no-experimental-fetch
166166
Disable experimental support for the Fetch API.
167167
.
168+
.ItFl-no-experimental-global-webcrypto
169+
Disable exposition of the Web Crypto API on the global scope.
170+
.
168171
.ItFl-no-experimental-repl-await
169172
Disable top-level await keyword support in REPL.
170173
.

‎lib/internal/main/eval_string.js‎

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
// `--interactive`.
55

66
const{
7+
ObjectDefineProperty,
8+
RegExpPrototypeExec,
79
globalThis,
810
}=primordials;
911

@@ -25,9 +27,31 @@ const print = getOptionValue('--print');
2527
constloadESM=getOptionValue('--import').length>0;
2628
if(getOptionValue('--input-type')==='module')
2729
evalModule(source,print);
28-
else
30+
else{
31+
// For backward compatibility, we want the identifier crypto to be the
32+
// `node:crypto` module rather than WebCrypto.
33+
constisUsingCryptoIdentifier=
34+
getOptionValue('--experimental-global-webcrypto')&&
35+
RegExpPrototypeExec(/\bcrypto\b/,source)!==null;
36+
constshouldDefineCrypto=isUsingCryptoIdentifier&&internalBinding('config').hasOpenSSL;
37+
38+
if(isUsingCryptoIdentifier&&!shouldDefineCrypto){
39+
// This is taken from `addBuiltinLibsToObject`.
40+
constobject=globalThis;
41+
constname='crypto';
42+
constsetReal=(val)=>{
43+
// Deleting the property before re-assigning it disables the
44+
// getter/setter mechanism.
45+
deleteobject[name];
46+
object[name]=val;
47+
};
48+
ObjectDefineProperty(object,name,{__proto__: null,set: setReal});
49+
}
2950
evalScript('[eval]',
30-
source,
51+
shouldDefineCrypto ? (
52+
print ? `let crypto=require("node:crypto");{${source}}` : `(crypto=>{{${source}}})(require('node:crypto'))`
53+
) : source,
3154
getOptionValue('--inspect-brk'),
3255
print,
3356
loadESM);
57+
}

‎lib/internal/process/pre_execution.js‎

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const {
2525

2626
const{
2727
ERR_MANIFEST_ASSERT_INTEGRITY,
28+
ERR_NO_CRYPTO,
2829
}=require('internal/errors').codes;
2930
constassert=require('internal/assert');
3031

@@ -247,23 +248,29 @@ function setupFetch() {
247248
// removed.
248249
functionsetupWebCrypto(){
249250
if(process.config.variables.node_no_browser_globals||
250-
!getOptionValue('--experimental-global-webcrypto')){
251+
getOptionValue('--no-experimental-global-webcrypto')){
251252
return;
252253
}
253254

254-
letwebcrypto;
255-
ObjectDefineProperty(globalThis,'crypto',
256-
{__proto__: null, ...ObjectGetOwnPropertyDescriptor({
257-
getcrypto(){
258-
webcrypto??=require('internal/crypto/webcrypto');
259-
returnwebcrypto.crypto;
260-
}
261-
},'crypto')});
262255
if(internalBinding('config').hasOpenSSL){
263-
webcrypto??=require('internal/crypto/webcrypto');
256+
constwebcrypto=require('internal/crypto/webcrypto');
257+
ObjectDefineProperty(globalThis,'crypto',
258+
{__proto__: null, ...ObjectGetOwnPropertyDescriptor({
259+
getcrypto(){
260+
returnwebcrypto.crypto;
261+
}
262+
},'crypto')});
264263
exposeInterface(globalThis,'Crypto',webcrypto.Crypto);
265264
exposeInterface(globalThis,'CryptoKey',webcrypto.CryptoKey);
266265
exposeInterface(globalThis,'SubtleCrypto',webcrypto.SubtleCrypto);
266+
}else{
267+
ObjectDefineProperty(globalThis,'crypto',
268+
{__proto__: null, ...ObjectGetOwnPropertyDescriptor({
269+
getcrypto(){
270+
thrownewERR_NO_CRYPTO();
271+
}
272+
},'crypto')});
273+
267274
}
268275
}
269276

‎src/node_options.cc‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,8 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
370370
AddOption("--experimental-global-webcrypto",
371371
"expose experimental Web Crypto API on the global scope",
372372
&EnvironmentOptions::experimental_global_web_crypto,
373-
kAllowedInEnvironment);
373+
kAllowedInEnvironment,
374+
true);
374375
AddOption("--experimental-json-modules", "", NoOp{}, kAllowedInEnvironment);
375376
AddOption("--experimental-loader",
376377
"use the specified module as a custom loader",

‎src/node_options.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ class EnvironmentOptions : public Options {
110110
bool enable_source_maps = false;
111111
bool experimental_fetch = true;
112112
bool experimental_global_customevent = false;
113-
bool experimental_global_web_crypto = false;
113+
bool experimental_global_web_crypto = true;
114114
bool experimental_https_modules = false;
115115
std::string experimental_specifier_resolution;
116116
bool experimental_wasm_modules = false;

‎test/common/index.js‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,9 @@ if (process.env.NODE_TEST_KNOWN_GLOBALS !== '0') {
357357
constleaked=[];
358358

359359
for(constvalinglobal){
360-
if(!knownGlobals.includes(global[val])){
360+
// globalThis.crypto is a getter that throws if Node.js was compiled
361+
// without OpenSSL.
362+
if(val!=='crypto'&&!knownGlobals.includes(global[val])){
361363
leaked.push(val);
362364
}
363365
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use strict';
2+
3+
constcommon=require('../common');
4+
constassert=require('assert');
5+
6+
if(!common.hasCrypto){
7+
assert.fail('When Node.js is compiled without OpenSSL, overriding the global '+
8+
'crypto is allowed on string eval');
9+
}
10+
11+
constchild=require('child_process');
12+
constnodejs=`"${process.execPath}"`;
13+
14+
// Trying to define a variable named `crypto` using `var` triggers an exception.
15+
16+
child.exec(
17+
`${nodejs} `+
18+
'-p "var crypto = {randomBytes:1};typeof crypto.randomBytes"',
19+
common.mustSucceed((stdout)=>{
20+
assert.match(stdout,/^number/);
21+
}));

0 commit comments

Comments
 (0)