diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2023-11-25 11:41:21 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-25 11:41:21 -0500 |
commit | a4ec7dfae01485290af91c62c1ce17a742dcb104 (patch) | |
tree | ac5f66523e5151b56e10304026ba096871fbb825 | |
parent | 00e4c47890e9b5d95557b06f2048d14a79de8401 (diff) |
feat(unstable): --unstable-unsafe-proto (#21313)
Closes https://github.com/denoland/deno/issues/21276
-rw-r--r-- | cli/args/flags.rs | 44 | ||||
-rw-r--r-- | cli/main.rs | 5 | ||||
-rw-r--r-- | cli/tests/integration/run_tests.rs | 14 | ||||
-rw-r--r-- | cli/tests/testdata/run/unsafe_proto/main.js | 5 | ||||
-rw-r--r-- | cli/tests/testdata/run/unsafe_proto/main.out | 2 | ||||
-rw-r--r-- | cli/tests/testdata/run/unsafe_proto/main_with_unsafe_proto_flag.out | 2 | ||||
-rw-r--r-- | cli/tests/testdata/run/unsafe_proto/worker.js | 2 | ||||
-rw-r--r-- | cli/worker.rs | 6 | ||||
-rw-r--r-- | runtime/js/90_deno_ns.js | 2 | ||||
-rw-r--r-- | runtime/js/99_main.js | 18 |
10 files changed, 55 insertions, 45 deletions
diff --git a/cli/args/flags.rs b/cli/args/flags.rs index d1f6c153d..d7d51b374 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -844,45 +844,11 @@ pub fn flags_from_vec(args: Vec<String>) -> clap::error::Result<Flags> { if matches.get_flag("unstable") { flags.unstable = true; } - if matches.get_flag("unstable-broadcast-channel") { - flags.unstable_features.push( - deno_runtime::deno_broadcast_channel::UNSTABLE_FEATURE_NAME.to_string(), - ); - } - if matches.get_flag("unstable-ffi") { - flags - .unstable_features - .push(deno_runtime::deno_ffi::UNSTABLE_FEATURE_NAME.to_string()); - } - if matches.get_flag("unstable-fs") { - flags - .unstable_features - .push(deno_runtime::deno_fs::UNSTABLE_FEATURE_NAME.to_string()); - } - if matches.get_flag("unstable-http") { - flags - .unstable_features - .push(deno_runtime::ops::http::UNSTABLE_FEATURE_NAME.to_string()); - } - if matches.get_flag("unstable-kv") { - flags - .unstable_features - .push(deno_runtime::deno_kv::UNSTABLE_FEATURE_NAME.to_string()); - } - if matches.get_flag("unstable-net") { - flags - .unstable_features - .push(deno_runtime::deno_net::UNSTABLE_FEATURE_NAME.to_string()); - } - if matches.get_flag("unstable-worker-options") { - flags - .unstable_features - .push(deno_runtime::ops::worker_host::UNSTABLE_FEATURE_NAME.to_string()); - } - if matches.get_flag("unstable-cron") { - flags - .unstable_features - .push(deno_runtime::deno_cron::UNSTABLE_FEATURE_NAME.to_string()); + + for (name, _, _) in crate::UNSTABLE_GRANULAR_FLAGS { + if matches.get_flag(&format!("unstable-{}", name)) { + flags.unstable_features.push(name.to_string()); + } } flags.unstable_bare_node_builtins = diff --git a/cli/main.rs b/cli/main.rs index 1fa4ee851..94b59b9d6 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -310,6 +310,11 @@ pub(crate) static UNSTABLE_GRANULAR_FLAGS: &[( "Enable unstable Deno.cron API", 8, ), + ( + "unsafe-proto", + "Enable unsafe __proto__ support. This is a security risk.", + 9, + ), ]; pub(crate) fn unstable_exit_cb(_feature: &str, api_name: &str) { diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs index 0ddedbdfb..4ac18cd50 100644 --- a/cli/tests/integration/run_tests.rs +++ b/cli/tests/integration/run_tests.rs @@ -4716,3 +4716,17 @@ itest!(workspaces_nested_member { http_server: true, exit_code: 1, }); + +itest!(unsafe_proto { + args: "run -A run/unsafe_proto/main.js", + output: "run/unsafe_proto/main.out", + http_server: false, + exit_code: 0, +}); + +itest!(unsafe_proto_flag { + args: "run -A --unstable-unsafe-proto run/unsafe_proto/main.js", + output: "run/unsafe_proto/main_with_unsafe_proto_flag.out", + http_server: false, + exit_code: 0, +}); diff --git a/cli/tests/testdata/run/unsafe_proto/main.js b/cli/tests/testdata/run/unsafe_proto/main.js new file mode 100644 index 000000000..eb95c55a0 --- /dev/null +++ b/cli/tests/testdata/run/unsafe_proto/main.js @@ -0,0 +1,5 @@ +console.log(Object.hasOwn(Object.prototype, "__proto__")); + +new Worker(import.meta.resolve("./worker.js"), { + type: "module", +}); diff --git a/cli/tests/testdata/run/unsafe_proto/main.out b/cli/tests/testdata/run/unsafe_proto/main.out new file mode 100644 index 000000000..4b095fd0f --- /dev/null +++ b/cli/tests/testdata/run/unsafe_proto/main.out @@ -0,0 +1,2 @@ +false +false diff --git a/cli/tests/testdata/run/unsafe_proto/main_with_unsafe_proto_flag.out b/cli/tests/testdata/run/unsafe_proto/main_with_unsafe_proto_flag.out new file mode 100644 index 000000000..bb101b641 --- /dev/null +++ b/cli/tests/testdata/run/unsafe_proto/main_with_unsafe_proto_flag.out @@ -0,0 +1,2 @@ +true +true diff --git a/cli/tests/testdata/run/unsafe_proto/worker.js b/cli/tests/testdata/run/unsafe_proto/worker.js new file mode 100644 index 000000000..b22bc8713 --- /dev/null +++ b/cli/tests/testdata/run/unsafe_proto/worker.js @@ -0,0 +1,2 @@ +console.log(Object.hasOwn(Object.prototype, "__proto__")); +close(); diff --git a/cli/worker.rs b/cli/worker.rs index 361aad2ec..5be64e117 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -570,7 +570,8 @@ impl CliMainWorkerFactory { // TODO(bartlomieju): this is cruft, update FeatureChecker to spit out // list of enabled features. let feature_checker = shared.feature_checker.clone(); - let mut unstable_features = Vec::with_capacity(8); + let mut unstable_features = + Vec::with_capacity(crate::UNSTABLE_GRANULAR_FLAGS.len()); for (feature_name, _, id) in crate::UNSTABLE_GRANULAR_FLAGS { if feature_checker.check(feature_name) { unstable_features.push(*id); @@ -768,7 +769,8 @@ fn create_web_worker_callback( // TODO(bartlomieju): this is cruft, update FeatureChecker to spit out // list of enabled features. let feature_checker = shared.feature_checker.clone(); - let mut unstable_features = Vec::with_capacity(8); + let mut unstable_features = + Vec::with_capacity(crate::UNSTABLE_GRANULAR_FLAGS.len()); for (feature_name, _, id) in crate::UNSTABLE_GRANULAR_FLAGS { if feature_checker.check(feature_name) { unstable_features.push(*id); diff --git a/runtime/js/90_deno_ns.js b/runtime/js/90_deno_ns.js index ab2a5c308..bd664d2ea 100644 --- a/runtime/js/90_deno_ns.js +++ b/runtime/js/90_deno_ns.js @@ -208,6 +208,8 @@ const denoNsUnstableById = { 8: { cron: cron.cron, }, + // Unsafe proto + // 9: {}, }; // when editing this list, also update unstableDenoProps in cli/tsc/99_main_compiler.js diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index 1af2585a5..67667427f 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -1,9 +1,5 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -// Removes the `__proto__` for security reasons. -// https://tc39.es/ecma262/#sec-get-object.prototype.__proto__ -delete Object.prototype.__proto__; - // Remove Intl.v8BreakIterator because it is a non-standard API. delete Intl.v8BreakIterator; @@ -14,6 +10,7 @@ const primordials = globalThis.__bootstrap.primordials; const { ArrayPrototypeFilter, ArrayPrototypeIndexOf, + ArrayPrototypeIncludes, ArrayPrototypeMap, ArrayPrototypePush, ArrayPrototypeShift, @@ -570,6 +567,12 @@ function bootstrapMainRuntime(runtimeOptions) { } } + if (!ArrayPrototypeIncludes(unstableFeatures, /* unsafe-proto */ 9)) { + // Removes the `__proto__` for security reasons. + // https://tc39.es/ecma262/#sec-get-object.prototype.__proto__ + delete Object.prototype.__proto__; + } + // Setup `Deno` global - we're actually overriding already existing global // `Deno` with `Deno` namespace from "./deno.ts". ObjectDefineProperty(globalThis, "Deno", util.readOnly(finalDenoNs)); @@ -668,6 +671,13 @@ function bootstrapWorkerRuntime( ObjectAssign(finalDenoNs, denoNsUnstableById[id]); } } + + if (!ArrayPrototypeIncludes(unstableFeatures, /* unsafe-proto */ 9)) { + // Removes the `__proto__` for security reasons. + // https://tc39.es/ecma262/#sec-get-object.prototype.__proto__ + delete Object.prototype.__proto__; + } + ObjectDefineProperties(finalDenoNs, { pid: util.getterOnly(opPid), noColor: util.getterOnly(() => ops.op_bootstrap_no_color()), |