1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
- From: Shelley Vohr <[email protected]>
- Date: Tue, 18 Mar 2025 10:41:27 +0100
- Subject: fix: ensure TraverseParent bails on resource path exit
- Electron's security model requires that we do not traverse outside of the
- resource path. This commit ensures that the TraverseParent function
- bails out if the parent path is outside of the resource path.
- diff --git a/src/node_modules.cc b/src/node_modules.cc
- index 210a01d24e11764dc9fc37a77b354f11383693f8..4e9f70a1c41b44d2a1863b778d4f1e37279178d9 100644
- --- a/src/node_modules.cc
- +++ b/src/node_modules.cc
- @@ -290,8 +290,41 @@ const BindingData::PackageConfig* BindingData::TraverseParent(
- Realm* realm, const std::filesystem::path& check_path) {
- std::filesystem::path current_path = check_path;
- auto env = realm->env();
- + Isolate* isolate = env->isolate();
- const bool is_permissions_enabled = env->permission()->enabled();
-
- + // Get the resources path with trailing slash.
- + std::string resources_path;
- + {
- + HandleScope handle_scope(isolate);
- + Local<Value> resources_path_value;
- + Local<Object> process_object = env->process_object();
- +
- + Local<String> resources_path_key =
- + String::NewFromUtf8Literal(isolate, "resourcesPath");
- + if (process_object->Get(env->context(), resources_path_key)
- + .ToLocal(&resources_path_value) &&
- + resources_path_value->IsString()) {
- + resources_path = *String::Utf8Value(isolate, resources_path_value);
- + if (!resources_path.empty() && !resources_path.ends_with(kPathSeparator)) {
- + resources_path += kPathSeparator;
- + }
- + }
- + }
- +
- + auto starts_with = [](const std::string& str, const std::string& prefix) -> bool {
- + if (prefix.size() > str.size()) return false;
- + return std::equal(
- + prefix.begin(), prefix.end(), str.begin(),
- + [](char a, char b) {
- + return std::tolower(static_cast<unsigned char>(a)) ==
- + std::tolower(static_cast<unsigned char>(b));
- + });
- + };
- +
- + bool did_original_path_start_with_resources_path = starts_with(check_path.
- + generic_string(), resources_path);
- +
- do {
- current_path = current_path.parent_path();
-
- @@ -310,6 +343,12 @@ const BindingData::PackageConfig* BindingData::TraverseParent(
- return nullptr;
- }
-
- + // If current path is outside the resources path, bail.
- + if (did_original_path_start_with_resources_path &&
- + !starts_with(current_path.generic_string(), resources_path)) {
- + return nullptr;
- + }
- +
- // Check if the path ends with `/node_modules`
- if (current_path.generic_string().ends_with("/node_modules")) {
- return nullptr;
|