diff --git a/doc/api/code_integrity.md b/doc/api/code_integrity.md
new file mode 100644
index 00000000000000..5d47867c94a720
--- /dev/null
+++ b/doc/api/code_integrity.md
@@ -0,0 +1,138 @@
+# Code Integrity
+
+
+
+
+
+> Stability: 1.1 - Active development
+
+This feature is only available on Windows platforms.
+
+Code integrity refers to the assurance that software code has not been
+altered or tampered with in any unauthorized way. It ensures that
+the code running on a system is exactly what was intended by the developers.
+
+Code integrity in Node.js integrates with platform features for code integrity
+policy enforcement. See platform speficic sections below for more information.
+
+The Node.js threat model considers the code that the runtime executes to be
+trusted. As such, this feature is an additional safety belt, not a strict
+security boundary.
+
+If you find a potential security vulnerability, please refer to our
+[Security Policy][].
+
+## Code Integrity on Windows
+
+Code integrity is an opt-in feature that leverages Window Defender Application Control
+to verify the code executing conforms to system policy and has not been modified since
+signing time.
+
+There are three audiences that are involved when using Node.js in an
+environment enforcing code integrity: the application developers,
+those administrating the system enforcing code integrity, and
+the end user. The following sections describe how each audience
+can interact with code integrity enforcement.
+
+### Windows Code Integrity and Application Developers
+
+Windows Defender Application Control uses digital signatures to verify
+a file's integrity. Application developers are responsible for generating and
+distributing the signature information for their Node.js application.
+Application developers are also expected to design their application
+in robust ways to avoid unintended code execution. This includes
+avoiding the use of `eval` and avoiding loading modules outside
+of standard methods.
+
+Signature information for files which Node.js is intended to execute
+can be stored in a catalog file. Application developers can generate
+a Windows catalog file to store the hash of all files Node.js
+is expected to execute.
+
+A catalog can be generated using the `New-FileCatalog` Powershell
+cmdlet. For example
+
+```powershell
+New-FileCatalog -Version 2 -CatalogFilePath MyApplicationCatalog.cat -Path \my\application\path\
+```
+
+The `Path` argument should point to the root folder containing your application's code. If
+your application's code is fully contained in one file, `Path` can point to that single file.
+
+Be sure that the catalog is generated using the final version of the files that you intend to ship
+(i.e. after minifying).
+
+The application developer should then sign the generated catalog with their Code Signing certificate
+to ensure the catalog is not tampered with between distribution and execution.
+
+This can be done with the [Set-AuthenticodeSignature commandlet][].
+
+### Windows Code Integrity and System Administrators
+
+This section is intended for system administrators who want to enable Node.js
+code integrity features in their environments.
+
+This section assumes familiarity with managing WDAC polcies.
+[Official documentation for WDAC][].
+
+Code integrity enforcement on Windows has two toggleable settings:
+`EnforceCodeIntegrity` and `DisableInteractiveMode`. These settings are configured
+by WDAC policy.
+
+`EnforceCodeIntegrity` causes Node.js to call WldpCanExecuteFile whenever a module is loaded using `require`.
+WldpCanExecuteFile verifies that the file's integrity has not been tampered with from signing time.
+The system administrator should sign and install the application's file catalog where the application
+is running, per WDAC guidance.
+
+`DisableInteractiveMode` prevents Node.js from being run in interactive mode, and also disables the `-e` and `--eval`
+command line options.
+
+#### Enabling Code Integrity Enforcement
+
+On newer Windows versions (22H2+), the preferred method of configuring application settings is done using
+`AppSettings` in your WDAC Policy.
+
+```text
+
+
+
+ True
+
+
+ True
+
+
+
+```
+
+On older Windows versions, use the `Settings` section of your WDAC Policy.
+
+```text
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+```
+
+## Code Integrity on Linux
+
+Code integrity on Linux is not yet implemented. Plans for implementation will
+be made once the necessary APIs on Linux have been upstreamed. More information
+can be found here:
+
+## Code Integrity on MacOS
+
+Code integrity on MacOS is not yet implemented. Currently, there is no
+timeline for implementation.
+
+[Official documentation for WDAC]: https://learn.microsoft.com/en-us/windows/security/application-security/application-control/windows-defender-application-control/
+[Security Policy]: https://github.com/nodejs/node/blob/main/SECURITY.md
+[Set-AuthenticodeSignature commandlet]: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-authenticodesignature
diff --git a/doc/api/errors.md b/doc/api/errors.md
index b06abbf8d96a2a..1bf328a2bf57eb 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -794,6 +794,22 @@ changes:
There was an attempt to use a `MessagePort` instance in a closed
state, usually after `.close()` has been called.
+
+
+### `ERR_CODE_INTEGRITY_BLOCKED`
+
+> Stability: 1.1 - Active development
+
+Feature has been disabled due to OS Code Integrity policy.
+
+
+
+### `ERR_CODE_INTEGRITY_VIOLATION`
+
+> Stability: 1.1 - Active development
+
+JavaScript code intended to be executed was rejected by system code integrity policy.
+
### `ERR_CONSOLE_WRITABLE_STREAM`
diff --git a/doc/api/index.md b/doc/api/index.md
index 7b4144639a07be..f31f753d8fb12d 100644
--- a/doc/api/index.md
+++ b/doc/api/index.md
@@ -19,6 +19,7 @@
* [C++ embedder API](embedding.md)
* [Child processes](child_process.md)
* [Cluster](cluster.md)
+* [Code integrity](code_integrity.md)
* [Command-line options](cli.md)
* [Console](console.md)
* [Crypto](crypto.md)
diff --git a/doc/api/wdac-manifest.xml b/doc/api/wdac-manifest.xml
new file mode 100644
index 00000000000000..264de029012bf7
--- /dev/null
+++ b/doc/api/wdac-manifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/lib/internal/code_integrity.js b/lib/internal/code_integrity.js
new file mode 100644
index 00000000000000..e1ce4620fc6a44
--- /dev/null
+++ b/lib/internal/code_integrity.js
@@ -0,0 +1,44 @@
+// Code integrity is a security feature which prevents unsigned
+// code from executing. More information can be found in the docs
+// doc/api/code_integrity.md
+
+'use strict';
+
+const { emitWarning } = require('internal/process/warning');
+const {
+ isFileTrustedBySystemCodeIntegrityPolicy,
+ isInteractiveModeDisabled,
+ isSystemEnforcingCodeIntegrity,
+} = internalBinding('code_integrity');
+
+let isCodeIntegrityEnforced;
+let alreadyQueriedSystemCodeEnforcmentMode = false;
+
+function isAllowedToExecuteFile(filepath) {
+ if (!alreadyQueriedSystemCodeEnforcmentMode) {
+ isCodeIntegrityEnforced = isSystemEnforcingCodeIntegrity();
+
+ if (isCodeIntegrityEnforced) {
+ emitWarning(
+ 'Code integrity is being enforced by system policy.' +
+ '\nCode integrity is an experimental feature.' +
+ ' See docs for more info.',
+ 'ExperimentalWarning');
+ }
+
+ alreadyQueriedSystemCodeEnforcmentMode = true;
+ }
+
+ if (!isCodeIntegrityEnforced) {
+ return true;
+ }
+
+ return isFileTrustedBySystemCodeIntegrityPolicy(filepath);
+}
+
+module.exports = {
+ isAllowedToExecuteFile,
+ isFileTrustedBySystemCodeIntegrityPolicy,
+ isInteractiveModeDisabled,
+ isSystemEnforcingCodeIntegrity,
+};
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index 3b12f2e5551c40..19d2c9a7133c5a 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -1157,6 +1157,10 @@ E('ERR_CHILD_PROCESS_IPC_REQUIRED',
Error);
E('ERR_CHILD_PROCESS_STDIO_MAXBUFFER', '%s maxBuffer length exceeded',
RangeError);
+E('ERR_CODE_INTEGRITY_BLOCKED',
+ 'The feature "%s" is blocked by OS Code Integrity policy', Error);
+E('ERR_CODE_INTEGRITY_VIOLATION',
+ 'The file %s did not pass OS Code Integrity validation', Error);
E('ERR_CONSOLE_WRITABLE_STREAM',
'Console expects a writable stream instance for %s', TypeError);
E('ERR_CONTEXT_NOT_INITIALIZED', 'context used is not initialized', Error);
diff --git a/lib/internal/main/eval_string.js b/lib/internal/main/eval_string.js
index ee402f50fbdd2b..dd37c20d4665f7 100644
--- a/lib/internal/main/eval_string.js
+++ b/lib/internal/main/eval_string.js
@@ -23,10 +23,24 @@ const {
const { addBuiltinLibsToObject } = require('internal/modules/helpers');
const { getOptionValue } = require('internal/options');
+const {
+ codes: {
+ ERR_CODE_INTEGRITY_BLOCKED,
+ },
+} = require('internal/errors');
+
prepareMainThreadExecution();
addBuiltinLibsToObject(globalThis, '');
markBootstrapComplete();
+const { isWindows } = require('internal/util');
+if (isWindows) {
+ const ci = require('internal/code_integrity');
+ if (ci.isInteractiveModeDisabled()) {
+ throw new ERR_CODE_INTEGRITY_BLOCKED('"eval"');
+ }
+}
+
const code = getOptionValue('--eval');
const print = getOptionValue('--print');
diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js
index 67ec47c424fbc4..b8e3b5a67da17f 100644
--- a/lib/internal/modules/cjs/loader.js
+++ b/lib/internal/modules/cjs/loader.js
@@ -181,6 +181,7 @@ const {
const {
codes: {
+ ERR_CODE_INTEGRITY_VIOLATION,
ERR_INVALID_ARG_TYPE,
ERR_INVALID_ARG_VALUE,
ERR_INVALID_MODULE_SPECIFIER,
@@ -216,6 +217,11 @@ const onRequire = getLazy(() => tracingChannel('module.require'));
const relativeResolveCache = { __proto__: null };
+let ci;
+if (isWindows) {
+ ci = require('internal/code_integrity');
+}
+
let requireDepth = 0;
let isPreloading = false;
let statCache = null;
@@ -1180,6 +1186,13 @@ Module._load = function(request, parent, isMain) {
// For backwards compatibility, if the request itself starts with node:, load it before checking
// Module._cache. Otherwise, load it after the check.
if (StringPrototypeStartsWith(request, 'node:')) {
+
+ if (isWindows) {
+ const isAllowedToExecute = ci.isAllowedToExecuteFile(filename);
+ if (!isAllowedToExecute) {
+ throw new ERR_CODE_INTEGRITY_VIOLATION(filename);
+ }
+ }
const result = loadBuiltinWithHooks(filename, url, format);
if (result) {
return result;
@@ -1210,6 +1223,13 @@ Module._load = function(request, parent, isMain) {
cachedModule[kModuleCircularVisited] = true;
}
+ if (isWindows) {
+ const isAllowedToExecute = ci.isAllowedToExecuteFile(filename);
+ if (!isAllowedToExecute) {
+ throw new ERR_CODE_INTEGRITY_VIOLATION(filename);
+ }
+ }
+
if (BuiltinModule.canBeRequiredWithoutScheme(filename)) {
const result = loadBuiltinWithHooks(filename, url, format);
if (result) {
diff --git a/lib/internal/modules/esm/load.js b/lib/internal/modules/esm/load.js
index 98e14455075d2f..9c15256f72ada9 100644
--- a/lib/internal/modules/esm/load.js
+++ b/lib/internal/modules/esm/load.js
@@ -4,6 +4,7 @@ const {
RegExpPrototypeExec,
} = primordials;
const {
+ isWindows,
kEmptyObject,
} = require('internal/util');
@@ -13,8 +14,9 @@ const { readFileSync } = require('fs');
const { Buffer: { from: BufferFrom } } = require('buffer');
-const { URL } = require('internal/url');
+const { URL, fileURLToPath } = require('internal/url');
const {
+ ERR_CODE_INTEGRITY_VIOLATION,
ERR_INVALID_URL,
ERR_UNKNOWN_MODULE_FORMAT,
ERR_UNSUPPORTED_ESM_URL_SCHEME,
@@ -24,6 +26,11 @@ const {
dataURLProcessor,
} = require('internal/data_url');
+let ci;
+if (isWindows) {
+ ci = require('internal/code_integrity');
+}
+
/**
* @param {URL} url URL to the module
* @param {LoadContext} context used to decorate error messages
@@ -34,6 +41,12 @@ function getSourceSync(url, context) {
const responseURL = href;
let source;
if (protocol === 'file:') {
+ if (isWindows) {
+ const isAllowedToExecute = ci.isAllowedToExecuteFile(fileURLToPath(url));
+ if (!isAllowedToExecute) {
+ throw new ERR_CODE_INTEGRITY_VIOLATION(url);
+ }
+ }
source = readFileSync(url);
} else if (protocol === 'data:') {
const result = dataURLProcessor(url);
diff --git a/node.gyp b/node.gyp
index 64c1e9cdd99256..b6ae01e3a1d6e2 100644
--- a/node.gyp
+++ b/node.gyp
@@ -232,6 +232,7 @@
'src/node_blob.h',
'src/node_buffer.h',
'src/node_builtins.h',
+ 'src/node_code_integrity.h',
'src/node_config_file.h',
'src/node_constants.h',
'src/node_context_data.h',
@@ -455,6 +456,14 @@
}, {
'use_openssl_def%': 0,
}],
+ # Only compile node_code_integrity on Windows
+ [ 'OS=="win"', {
+ 'node_sources': [
+ '<(node_sources)',
+ 'src/node_code_integrity.cc',
+ 'src/node_code_integrity.h',
+ ],
+ }],
],
},
diff --git a/src/node_binding.cc b/src/node_binding.cc
index 367a5bcd402b53..5a30a130022725 100644
--- a/src/node_binding.cc
+++ b/src/node_binding.cc
@@ -97,6 +97,12 @@
V(worker) \
V(zlib)
+#define NODE_BUILTIN_OS_SPECIFIC_BINDINGS(V)
+
+#ifdef _WIN32
+#define NODE_BUILTIN_OS_SPECIFIC_BINDINGS(V) V(code_integrity)
+#endif
+
#define NODE_BUILTIN_BINDINGS(V) \
NODE_BUILTIN_STANDARD_BINDINGS(V) \
NODE_BUILTIN_OPENSSL_BINDINGS(V) \
@@ -104,7 +110,8 @@
NODE_BUILTIN_PROFILER_BINDINGS(V) \
NODE_BUILTIN_DEBUG_BINDINGS(V) \
NODE_BUILTIN_QUIC_BINDINGS(V) \
- NODE_BUILTIN_SQLITE_BINDINGS(V)
+ NODE_BUILTIN_SQLITE_BINDINGS(V) \
+ NODE_BUILTIN_OS_SPECIFIC_BINDINGS(V)
// This is used to load built-in bindings. Instead of using
// __attribute__((constructor)), we call the _register_
diff --git a/src/node_builtins.cc b/src/node_builtins.cc
index 00a4ef69d31884..5010a337ebdc7a 100644
--- a/src/node_builtins.cc
+++ b/src/node_builtins.cc
@@ -150,6 +150,9 @@ BuiltinLoader::BuiltinCategories BuiltinLoader::GetBuiltinCategories() const {
#endif
"internal/test/binding", "internal/v8_prof_polyfill",
"internal/v8_prof_processor",
+#if !_WIN32
+ "internal/code_integrity", // Only implemented on Windows
+#endif
};
auto source = source_.read();
diff --git a/src/node_code_integrity.cc b/src/node_code_integrity.cc
new file mode 100644
index 00000000000000..2ec8bc2a41e055
--- /dev/null
+++ b/src/node_code_integrity.cc
@@ -0,0 +1,287 @@
+#ifdef _WIN32
+
+#include "node_code_integrity.h"
+#include "env-inl.h"
+#include "node.h"
+#include "node_errors.h"
+#include "node_external_reference.h"
+#include "util.h"
+#include "v8.h"
+
+namespace node {
+
+using v8::Boolean;
+using v8::Context;
+using v8::FunctionCallbackInfo;
+using v8::Local;
+using v8::Object;
+using v8::Value;
+
+namespace per_process {
+bool isWldpInitialized = false;
+
+// WldpCanExecuteFile queries system code integrity policy
+// to determine if the contents of a file are allowed to be executed.
+pfnWldpCanExecuteFile WldpCanExecuteFile;
+
+// WldpGetApplicationSettingBoolean queries system code integrity policy
+// for an arbitrary flag. NodeJS uses the "Node.js EnforceCodeIntegrity"
+// flag to determine if NodeJS should be calling WldpCanExecuteFile
+// on files intended for execution
+// NodeJS also uses the "Node.js DisableInteractiveMode" flag to determine
+// if it should restrict interactive code execution. More details
+// on how to configure these flags can be found in doc/api/code_integrity.md
+pfnWldpGetApplicationSettingBoolean WldpGetApplicationSettingBoolean;
+
+// WldpQuerySecurityPolicy performs similar functionality to
+// WldpGetApplicationSettingBoolean, except for legacy Windows systems.
+// WldpGetApplicationSettingBoolean was introduced Win10 2023H2,
+// and is the modern API. However, to support more Node users,
+// we also fall back to WldpQuerySecurityPolicy,
+// which is available on Windows systems back to Win10 RS2
+pfnWldpQuerySecurityPolicy WldpQuerySecurityPolicy;
+} // namespace per_process
+
+namespace code_integrity {
+
+static PCWSTR NODEJS = L"Node.js";
+static PCWSTR ENFORCE_CODE_INTEGRITY_SETTING_NAME = L"EnforceCodeIntegrity";
+static PCWSTR DISABLE_INTERPRETIVE_MODE_SETTING_NAME =
+ L"DisableInteractiveMode";
+
+// InitWldp loads WLDP.dll (the Windows code integrity for interpreters DLL)
+// and the relevant function pointers
+void InitWldp(Environment* env) {
+ if (per_process::isWldpInitialized) {
+ return;
+ }
+
+ HMODULE wldp_module =
+ LoadLibraryExA("wldp.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
+
+ if (wldp_module == nullptr) {
+ // Wldp is included on all Windows systems that are supported by Node.js
+ // If Wldp is unable to be loaded, something is very wrong with
+ // the system state
+ THROW_ERR_INVALID_STATE(env, "WLDP.DLL does not exist");
+ return;
+ }
+
+ per_process::WldpCanExecuteFile =
+ (pfnWldpCanExecuteFile)GetProcAddress(wldp_module, "WldpCanExecuteFile");
+
+ per_process::WldpGetApplicationSettingBoolean =
+ (pfnWldpGetApplicationSettingBoolean)GetProcAddress(
+ wldp_module, "WldpGetApplicationSettingBoolean");
+
+ per_process::WldpQuerySecurityPolicy =
+ (pfnWldpQuerySecurityPolicy)GetProcAddress(wldp_module,
+ "WldpQuerySecurityPolicy");
+
+ per_process::isWldpInitialized = true;
+}
+
+// IsFileTrustedBySystemCodeIntegrityPolicy
+// Queries operating system to determine if the contents of a file are
+// allowed to be executed according to system code integrity policy.
+static void IsFileTrustedBySystemCodeIntegrityPolicy(
+ const FunctionCallbackInfo& args) {
+ CHECK_EQ(args.Length(), 1);
+ CHECK(args[0]->IsString());
+
+ Environment* env = Environment::GetCurrent(args);
+ if (!per_process::isWldpInitialized) {
+ InitWldp(env);
+ }
+
+ BufferValue path(env->isolate(), args[0]);
+ CHECK_NOT_NULL(*path);
+
+ HANDLE hFile = CreateFileA(*path,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ nullptr,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ nullptr);
+
+ if (hFile == INVALID_HANDLE_VALUE || hFile == nullptr) {
+ return args.GetReturnValue().SetFalse();
+ }
+
+ const GUID wldp_host_other = WLDP_HOST_OTHER;
+ WLDP_EXECUTION_POLICY result;
+ HRESULT hr =
+ per_process::WldpCanExecuteFile(wldp_host_other,
+ WLDP_EXECUTION_EVALUATION_OPTION_NONE,
+ hFile,
+ NODEJS,
+ &result);
+ CloseHandle(hFile);
+
+ if (FAILED(hr)) {
+ // The failure cases from WldpCanExecuteFile are generally
+ // not recoverable. Inspection of the Windows event logs is necessary.
+ // The secure failure mode is not executing the file
+ args.GetReturnValue().SetFalse();
+ return;
+ }
+
+ bool isFileTrusted = (result == WLDP_EXECUTION_POLICY_ALLOWED);
+ args.GetReturnValue().Set(isFileTrusted);
+}
+
+// IsInteractiveModeDisabled
+// Queries operating system code integrity policy to determine if
+// the policy is requesting NodeJS to disable interactive mode.
+static void IsInteractiveModeDisabled(const FunctionCallbackInfo& args) {
+ CHECK_EQ(args.Length(), 0);
+
+ Environment* env = Environment::GetCurrent(args);
+
+ if (!per_process::isWldpInitialized) {
+ InitWldp(env);
+ }
+
+ if (per_process::WldpGetApplicationSettingBoolean != nullptr) {
+ bool isInteractiveModeDisabled;
+ HRESULT hr = per_process::WldpGetApplicationSettingBoolean(
+ NODEJS,
+ DISABLE_INTERPRETIVE_MODE_SETTING_NAME,
+ &isInteractiveModeDisabled);
+
+ if (SUCCEEDED(hr)) {
+ args.GetReturnValue().Set(isInteractiveModeDisabled);
+ return;
+ } else if (hr != E_NOTFOUND) {
+ // If the setting is not found, continue through to attempt
+ // WldpQuerySecurityPolicy, as the setting may be defined
+ // in the old settings format
+ args.GetReturnValue().SetFalse();
+ return;
+ }
+ }
+
+ // WldpGetApplicationSettingBoolean is the preferred way for applications to
+ // query security policy values. However, this method only exists on Windows
+ // versions going back to circa Win10 2023H2. In order to support systems
+ // older than that (down to Win10RS2), we can use the deprecated
+ // WldpQuerySecurityPolicy
+ if (per_process::WldpQuerySecurityPolicy != nullptr) {
+ DECLARE_CONST_UNICODE_STRING(providerName, L"Node.js");
+ DECLARE_CONST_UNICODE_STRING(keyName, L"Settings");
+ DECLARE_CONST_UNICODE_STRING(valueName, L"DisableInteractiveMode");
+ WLDP_SECURE_SETTING_VALUE_TYPE valueType =
+ WLDP_SECURE_SETTING_VALUE_TYPE_BOOLEAN;
+ ULONG valueSize = sizeof(int);
+ int isInteractiveModeDisabled = 0;
+ HRESULT hr =
+ per_process::WldpQuerySecurityPolicy(&providerName,
+ &keyName,
+ &valueName,
+ &valueType,
+ &isInteractiveModeDisabled,
+ &valueSize);
+
+ if (FAILED(hr)) {
+ args.GetReturnValue().SetFalse();
+ return;
+ }
+
+ args.GetReturnValue().Set(Boolean::New(
+ env->isolate(), static_cast(isInteractiveModeDisabled)));
+ }
+}
+
+// IsSystemEnforcingCodeIntegrity
+// Queries the operating system to determine if NodeJS should be enforcing
+// integrity checks by calling WldpCanExecuteFile
+static void IsSystemEnforcingCodeIntegrity(
+ const FunctionCallbackInfo& args) {
+ CHECK_EQ(args.Length(), 0);
+
+ Environment* env = Environment::GetCurrent(args);
+
+ if (!per_process::isWldpInitialized) {
+ InitWldp(env);
+ }
+
+ if (per_process::WldpGetApplicationSettingBoolean != nullptr) {
+ bool isCodeIntegrityEnforced;
+ HRESULT hr = per_process::WldpGetApplicationSettingBoolean(
+ NODEJS, ENFORCE_CODE_INTEGRITY_SETTING_NAME, &isCodeIntegrityEnforced);
+
+ if (SUCCEEDED(hr)) {
+ args.GetReturnValue().Set(isCodeIntegrityEnforced);
+ return;
+ } else if (hr != E_NOTFOUND) {
+ // If the setting is not found, continue through to attempt
+ // WldpQuerySecurityPolicy, as the setting may be defined
+ // in the old settings format
+ args.GetReturnValue().SetFalse();
+ return;
+ }
+ }
+
+ // WldpGetApplicationSettingBoolean is the preferred way for applications to
+ // query security policy values. However, this method only exists on Windows
+ // versions going back to circa Win10 2023H2. In order to support systems
+ // older than that (down to Win10RS2), we can use the deprecated
+ // WldpQuerySecurityPolicy
+ if (per_process::WldpQuerySecurityPolicy != nullptr) {
+ DECLARE_CONST_UNICODE_STRING(providerName, L"Node.js");
+ DECLARE_CONST_UNICODE_STRING(keyName, L"Settings");
+ DECLARE_CONST_UNICODE_STRING(valueName, L"EnforceCodeIntegrity");
+ WLDP_SECURE_SETTING_VALUE_TYPE valueType =
+ WLDP_SECURE_SETTING_VALUE_TYPE_BOOLEAN;
+ ULONG valueSize = sizeof(int);
+ int isCodeIntegrityEnforced = 0;
+ HRESULT hr = per_process::WldpQuerySecurityPolicy(&providerName,
+ &keyName,
+ &valueName,
+ &valueType,
+ &isCodeIntegrityEnforced,
+ &valueSize);
+
+ if (FAILED(hr)) {
+ args.GetReturnValue().SetFalse();
+ return;
+ }
+
+ args.GetReturnValue().Set(Boolean::New(
+ env->isolate(), static_cast(isCodeIntegrityEnforced)));
+ }
+}
+
+void Initialize(Local