# NRG Sentinel, runtime security for Node-RED

**URL:** <https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515>\
**Category:** Share Your Projects\
**Created:** [7 March 2026 14:02 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515 "2026-03-07T14:02:02Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [27 March 2026 15:12 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/53 "2026-03-27T15:12:43Z")

</div>

This code "resolved path" is still running outside of node\_modules. It is using the same underlying mechanism as the other approaches you used. Archives and Symlinks are evil anyways. Sentinel will block both soon

 ![1774624624934155785730163961094](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/1/f13879a6d7f9c55fe23a577f591ece2cf798a3e7.jpeg)

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [28 March 2026 20:05 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/54 "2026-03-28T20:05:49Z")

</div>

I learned about cache poisoning and Im already working on a solution to fully isolate node cached dependencies. Node A wont be able to alter Node B required modules.

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [29 March 2026 21:20 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/55 "2026-03-29T21:20:53Z")

</div>

I think im going to force every package installed in a nodered instance to be bundled with their dependencies before loaded and executed by nodered. Then block their access to require. I have already blocked their access to deleting and set require cached dependencies, but it is still possible to change shared dependencies variables that libraries use to control their state. I think this is the only way to really lock the global require. Then move all to a read only (nodered user) dir where nodered picks nodes, to not let any nodes/plugins change other modules source files.

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [29 March 2026 23:13 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/56 "2026-03-29T23:13:33Z")

</div>

dynamic imports/require of files outside of the package won't be allowed (using real file path to resolve symlinks!). They suck and it can be exploited. Bundlers dont like them too.

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [30 March 2026 01:57 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/57 "2026-03-30T01:57:49Z")

</div>

First iteration of Sentinel's Palette Manager

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/e/e/ee8a5360efd58c4199e95de751ad6dbbf62d9a60.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/9/a9dea47472ae124805506005aa86da79c51d29b9.png)

POST PUT DELETE /nodes core routes are blocked and editorTheme.palette.editable is set to false.

Now, `usrDir/node_modules` is set to read-only for the Node-RED runtime user. This effectively prevents any code executed within Node-RED from mutating dependencies, eliminating the risk of cross-node contamination or corruption after a restart.

On top of that, all installed packages are statically bundled during installation, with explicit exclusions for dynamic imports/requires, native `.node` addons, WebAssembly modules, and Node-RED–specific assets that are copied over to the resulted bundle.

Combined with the new Sentinel guardrails, this solution ensures that any attempt by a package to tamper with the require cache at runtime is immediately detected and blocked, maintaining strict runtime integrity.

Will release all the new changes soon.

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [31 March 2026 13:32 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/58 "2026-03-31T13:32:15Z")

</div>

There’s an important risk worth highlighting around how flows are executed in environments where dependencies (like node\_modules) can be modified.

If the runtime environment is mutable, then the behavior of your flows is effectively mutable as well. In practice, most teams don’t have the bandwidth to audit the full source code of every dependency they install—especially when many packages are large, bundled, or obfuscated into single files.

This opens the door to subtle issues, such as dynamic require patterns that can alter runtime or editor behavior based on environment heuristics (for example, detecting production conditions). These changes can be difficult to detect and even harder to trace back once they’re in place.

This is exactly the class of problem Sentinel is designed to address—by preventing untrusted or potentially harmful dependencies from entering and affecting your Node-RED environment in the first place.

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [2 April 2026 16:15 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/59 "2026-04-02T16:15:48Z")

</div>

### Sentinel Admin Portal Preview

This is a preview of Sentinel’s upcoming Admin Portal. It provides a centralized interface where administrators can install packages and manage permissions, including fine-grained node-level grants.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/a/0a392b54119b60aa91e82419e0f6c1454c02f3b2.png)

Access to the portal is streamlined—admins can simply click the Sentinel logo. From there, they’ll also get real-time visibility into security activity, such as attempted threats or unauthorized actions within their environment.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/c/c/cc436eea89e8418b4f125029c7b1606d8b6b3ed0.png)

### Why move it out of the editor?

This is a deliberate architectural decision:

- **Security isolation** : Keeping Sentinel outside the editor reduces the attack surface and limits exposure to potentially malicious plugins.
- **Operational clarity** : A dedicated interface enables a broader, more scalable view of system state, permissions, and security insights.
- **Better UX for admins** : Moving beyond a constrained side panel allows for richer data visualization and more effective management workflows.

In short, this shift separates concerns—protecting the control plane while improving usability and visibility.

### Package Management Model (Sentinel vs Native)

Sentinel also replaces the native package manager with its own controlled installation flow. Instead of installing packages directly into a shared dependency tree, Sentinel bundles each package together with its dependencies (excluding native modules) into an isolated unit.

This design directly addresses common attack vectors like `require` pollution. At runtime, the preloader enforces strict boundaries: it guards against tampering with the `require` cache (both set and delete operations) and restricts packages to only load files within their own directory scope.

By combining controlled bundling with runtime enforcement, Sentinel ensures that dependencies remain isolated and that deep object properties or shared functions cannot be silently overridden by other packages. In practice, this creates a hardened execution model where packages operate in well-defined boundaries instead of a mutable global environment.

When installed, sentinel disables the native palette manager automatically for all Users.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/0/000a2d1dc50283d702042c86fc6b31c046403627.png)

Oh I'm also creating another step in the installation process to analyse the bundled code to detect dynamic imports/requires that esbuild can't resolve statically. All packages that contain these won't be registered into the runtime unless an admin accepts some sort of warning message that will be displayed in the installation page.

Bundling to cjs ensures that all dependencies, besides dynamic ones, pass through the loader guards. Some libraries unfortunatelly break when doing this because they were written using esm only features. For those edge cases, admins will be able to choose to bypass the bundling phase upon accepting the risks.

I'm going to investigate how to create a custom esm loader as well for these esm only packages.

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [3 April 2026 01:41 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/60 "2026-04-03T01:41:19Z")

</div>

I think I found a way to bundle to esm while keeping entrypoints in cjs. I have to try that. The reason for bundling to esm is because esm to cjs is more compatible then cjs to esm, and a lot of new libraries are being written to esm only, like aws sdk v3. Hopefully it wont be a lot of rework

Yeah this is going to work and it will make nrg v3 builds to esm! (Kind of haha)

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [3 April 2026 15:21 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/61 "2026-04-03T15:21:07Z")

</div>

Decided to use rolldown (or rollup) instead of esbuild because the conversion from cjs to esm isn’t well supported in esbuild. Rolldown is compatible to vite/rollup plugins, it is way faster and was created to replace rollup+esbuild in vite builds.

> <https://github.com/rolldown/rolldown/issues/819>
>
> \## Plugin Hooks
> 
> \### Fully Supported Hooks
> 
> \- \[x\] \`options\`
> \- \[x\] \`buildStart\`
> \-… \[x\] \`buildEnd\`
> \- \[x\] \`renderStart\`
> \- \[x\] \`renderError\`
> \- \[x\] \`generateBundle\`
> \- \[x\] \`writeBundle\`
> \- \[x\] \`closeBundle\`
> \- \[x\] \`banner\`
> \- \[x\] \`footer\`
> \- \[x\] \`intro\`
> \- \[x\] \`outro\`
> \- \[x\] \`augmentChunkHash\`
> \- \[x\] \`closeWatcher\`
> \- \[x\] \`watchChange\`
> \- \[x\] \`renderChunk\`
> 
> \## Partually Supported Hooks
> 
> Hooks in this section can work as intended for most commonly seen plugins, but they may have some niche options / behavior that are not implemented yet.
> 
> Our priority at this stage is implement enough compatibility for most plugins to run, and determine whether to support the niche options at a later stage based on user demand. Some options are explicitly marked as "will not support" due to architectural incompatibility and limited use case.
> 
> \- \`outputOptions\`
> - the \`PluginContext\` is not supported yet.
> \- \`resolveId\`
> - the 3rd argument \`options.attributes\` is not supported yet
> - the following fileds in the return value are not supported yet:
> - \`attributes\`
> - \`resolvedBy\`
> - \`syntheticNamedExports\`
> \- \`load\`
> - the following fileds in the return value are not supported yet:
> - \`attributes\`
> - \`syntheticNamedExports\`
> - \`ast\` \<sup\>will not support\</sup\>
> \- \`transform\`
> - the following fileds in the return value are not supported yet:
> - \`attributes\`
> - \`syntheticNamedExports\`
> - \`ast\` \<sup\>will not support\</sup\>
> \- \`moduleParsed\`
> - the argument \`moduleInfo\` is only partially compatible
> \- \`resolveDynamicImport\`
> - the 3rd argument \`options.attributes\` is not supported yet
> \- \`onLog\`
> - the \`meta\` property is not supported yet
> 
> \### Not Yet Supported
> 
> \- \[\] \`shouldTransformCachedModule\`
> \- \[\] \`resolveFileUrl\`
> \- \[\] \`resolveImportMeta\`
> \- \[\] \`renderDynamicImport\`
> 
> \## Plugin Context
> 
> \### Supported Properties
> 
> \- \[x\] \`debug\`
> \- \[x\] \`error\`
> \- \[x\] \`info\`
> \- \[x\] \`warn\`
> \- \[x\] \`getFileName\`
> \- \[x\] \`getModuleIds\`
> \- \[x\] \`getModuleInfo\`
> \- \[x\] \`addWatchFile\`
> \- \[x\] \`getCombinedSourcemap\`
> \- \[x\] \`parse\`
> 
> \### Partially Supported Properties
> 
> \- \`resolve\`
> - \`options.isEntry\` and \`options.attributes\` are not supported yet
> \- \`emitFile\`
> - only support emitting asset and chunk for now
> \- \`load\`
> - only support call at \`resolved(not resolving entry ids)/load/transform\` hooks
> 
> \### Not Yet Supported Properties
> 
> \- \`meta\`
> \- \`cache\`
> \- \`getWatchFiles\`
> \- \`setAssetSource\`
> 
> \## Vite Internal Plugins Compatibility
> 
> \- \[x\] \`assetPlugin\`.
> \- \[x\] \`assetImportMetaUrlPlugin\`
> \- \[x\] \`clientInjectionsPlugin\`
> \- \[x\] \`completeSystemWrapPlugin\`
> \- \[x\] \`cssPlugin\`
> \- \[x\] \`cssPostPlugin\`
> \- \[x\] \`cssAnalysisPlugin\`
> \- \[x\] \`dataURIPlugin\`
> \- \[x\] \`definePlugin\`
> \- \[x\] \\\*\`dynamicImportVarsPlugin\`
> \- \[x\] \`esbuildPlugin\`
> \- \[x\] \`buildEsbuildPlugin\`
> \- \[x\] \`htmlInlineProxyPlugin\`
> \- \[x\] \`buildHtmlPlugin\`
> \- \[x\] \`importAnalysisPlugin\`
> \- \[x\] \`buildImportAnalysisPlugin\`
> \- \[\] \`importGlobPlugin\` - needs \`resolveId#option\` the argument fileds \`attributes\` 
> \- \[x\] \`jsonPlugin\`
> \- \[x\] \`loadFallbackPlugin\` 
> \- \[x\] \`manifestPlugin\`
> \- \[x\] \`metadataPlugin\` , needs mutate( add extra fileds) \`renderChunkArgs#RenderedChunk\` and using it at \`augmentChunkHash/generateBundle\`, it rewrite to stored at js side.
> \- \[x\] \`modulePreloadPolyfillPlugin\`
> \- \[x\] \`optimizedDepsPlugin\`
> \- \[x\] \`preAliasPlugin\`
> \- \[x\] \`buildReporterPlugin\`
> \- \[x\] \`resolvePlugin\`
> \- \[\] \`splitVendorChunkPlugin\` - needs \`manualChunks\`. @deprecated
> \- \[x\] \`terserPlugin\`
> \- \[x\] \`wasmFallbackPlugin\`
> \- \[x\] \`wasmHelperPlugin\`
> \- \[\] \`webWorkerPostPlugin\` - needs \`resolveImportMeta\`
> \- \[x\] \`webWorkerPlugin\` - needs \`shouldTransformCachedModule\`
> \- \[x\] \`workerImportMetaUrlPlugin\` - needs \`shouldTransformCachedModule\`
> \- \[x\] \`ssrManifestPlugin\`
> 
> \## Vite Public Plugins Compatibility
> 
> \- \[x\] \`@vitejs/plugin-vue\`
> \- \[x\] \`@vitejs/plugin-vue-jsx\`
> \- \[x\] \`@vitejs/plugin-react\`
> 
> \## Rollup Official Plugins Compatibility
> 
> \### Supported as Built-in
> 
> The following Rollup plugins are no longer needed because Rolldown offers built-in support for equivalent features:
> 
> \- \`@rollup/plugin-alias\` - use \`resolve.alias\` option instead.
> \- \`@rollup/plugin-commonjs\` - Rolldown has built-in support
> \- \`@rollup/plugin-inject\` - use \`inject\` option instead.
> \- \`@rollup/plugin-node-resolve\` - Rolldown has built-in support
> \- \`@rollup/plugin-json\` - Rolldown has built-in support
> \- \`@rollup/plugin-replace\` - Rolldown provides built-in support via \`import { replacePlugin } from 'rolldown/experimental'\`
> \- \`@rollup/plugin-swc\`, \`@rollup/plugin-babel\`, \`@rollup/plugin-sucrase\` - Rolldown has built-in TS / JSX transform support via Oxc. Target-lowering transforms are WIP.
> \- \`@rollup/plugin-dynamic-import-vars\` , Rolldown provides built-in support via \`import { dynamicImportVarsPlugin } from 'rolldown/experimental'\`.
> 
> \### Fully Compatible Plugins
> 
> \- \[x\] \`@rollup/plugin-auto-install\`
> \- \[x\] \`@rollup/plugin-beep\`
> \- \[x\] \`@rollup/plugin-data-uri\`
> \- \[x\] \`@rollup/plugin-dsv\`
> \- \[x\] \`@rollup/plugin-eslint\` - consider using \`oxlint\` instead
> \- \[x\] \`@rollup/plugin-esm-shim\`
> \- \[x\] \`@rollup/plugin-graphql\`
> \- \[x\] \`@rollup/plugin-legacy\`
> \- \[x\] \`@rollup/plugin-run\`
> \- \[x\] \`@rollup/plugin-terser\` - Rolldown has built-in minifcation via \`output.minify\` option, but it's still WIP
> \- \[x\] \`@rollup/plugin-virtual\` -
> \- \[x\] \`@rollup/plugin-yaml\`
> \- \[x\] \`@rollup/plugin-multi-entry\` 
> \- \[x\] \`@rollup/plugin-image\`
> \- \[x\] \`@rollup/plugin-url\` 
> \- \[x\] \`@rollup/plugin-wasm\` will likely have built-in support
> \- \[x\] \`@rollup/plugin-html\`
> \- \[x\] \`@rollup/plugin-buble\`
> \- \[x\] \`@rollup/plugin-strip\` 
> \### Not Yet Compatible
> 
> \- \[\] \`@rollup/plugin-typescript\` - Rolldown will support emitting bundled dts with \`isolatedDeclarations: true\` in the future
> 
> 
> \## Vite Ecosystem
> 
> \### \[analog\](https://github.com/analogjs/analog)
> 
> \- \[\] \`jitPlugin\` - needs find plugin by plugin name at \`buildStart\` options, then using the plugin \`transform\`, see \[here\](https://github.com/analogjs/analog/blob/beta/packages/vite-plugin-angular/src/lib/angular-jit-plugin.ts#L25)
> 
> \### \[astro\](https://github.com/withastro/astro)
> 
> \- \[\] \`astroScannerPlugin\` - needs using \`PluginContext#getModuleInfo\` as \`TransformResult#meta\`, see \[here\](https://github.com/withastro/astro/blob/main/packages/astro/src/vite-plugin-scanner/index.ts#L63), (todo find usage)
> \- \[x\] \`markdown\` - needs \`LoadResult#meta\`
> \- \[x\] \`html\` - needs mutate \`NormalizedOption#plugins\` at \`options\` hook, see \[here\](https://github.com/withastro/astro/blob/main/packages/astro/src/vite-plugin-html/index.ts#L7)
> \- \[\] \`astroHeadBuildPlugin\` - needs mutate \`ModuleInfo#meta\` using \`PluginContext#getModuleInfo\` at generateBundle hook, see \[here\](https://github.com/withastro/astro/blob/main/packages/astro/src/vite-plugin-head/index.ts#L127)
> \- \[\] \`postprocess\` direct using \`acorn#parse\`
> \- \[\] \`vitePluginAnalyzer\` using \`ModuleInfo#meta\` by \`PluginContext#getModuleIds/getModuleInfo\` at generateBundle hook, see \[here\](https://github.com/withastro/astro/blob/main/packages/astro/src/core/build/plugins/plugin-analyzer.ts#L126)
> \- \[\] \`vitePluginContent\` mutate \`NormalizedOption#input\` at \`options\` hook, see \[here\](https://github.com/withastro/astro/blob/main/packages/astro/src/core/build/plugins/plugin-content.ts#L104), mutate \`NormalizedOption#manualChunks\` at same file
> \- \[\] \`css\` TODO
> \- \[x\] \`import.meta.ROLLUP\_FILE\_URL\_\*\`
> 
> \### \[histoire\](https://github.com/histoire-dev/histoire)
> 
> mutate \`NormalizedOption#external\`(look like is not correct), see \[here\](https://github.com/histoire-dev/histoire/blob/main/packages/histoire/src/node/build.ts#L101)
> 
> \### \[qwik\](https://github.com/QwikDev/qwik)
> 
> \`qwikCityPlugin\` used \`moduleSideEffect: no-treeshake\`, see \[here\](https://github1s.com/QwikDev/qwik/blob/main/packages/qwik-city/buildtime/vite/plugin.ts#L37)

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [5 April 2026 02:35 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/62 "2026-04-05T02:35:38Z")

</div>

The next release will be full of changes!

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/e/1e126de807447166fb43f4cc5a2034cca22c6aef.png)

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/2/f/2faf1186251b76653d96d20692e8b6db37775356.png)

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/2/b/2bf35f1e4e46c932b307bb04eb0f449b6cf4d9d8.png)

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/8/78b12b765c0f6b1ac12dc87658e4458b5537df78.png)

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [5 April 2026 03:10 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/63 "2026-04-05T03:10:05Z")

</div>

The new Package Installer is working as intended. In this example, `node-red-contrib-moment` attempted to access `process.env`, but the request was blocked because no permissions were granted.

This case is harmless, but it highlights a critical risk. If a package—or one of its dependencies—tries to read sensitive data from `process.env`, it could exfiltrate credentials during installation without the user ever noticing. In reality, no one audits 100% of their dependency tree.

Sentinel addresses this by defaulting to a deny-all model. Nothing gets access unless explicitly permitted, reducing the attack surface and protecting sensitive data from unauthorized access.

```bash
4 Apr 23:56:23 - [info] Starting flows
4 Apr 23:56:23 - [info] Started flows
[@allanoricil/nrg-sentinel] BLOCKED process.env.OS_LOCALE_S_DEBUG — node-red-contrib-moment lacks process:env:read
  Call stack:
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5053:34
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:3:48
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5201:14
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:3:48
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5267:23
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:3:48
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:6:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LC_ALL — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5150:50)
    at detectorBase (file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5233:28)
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5269:30
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:3:48
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:6:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LC_MESSAGES — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5150:64)
    at detectorBase (file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5233:28)
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5269:30
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:3:48
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:6:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LANG — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5150:83)
    at detectorBase (file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5233:28)
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5269:30
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:3:48
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:6:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LANGUAGE — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5150:95)
    at detectorBase (file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5233:28)
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5269:30
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:3:48
    at file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:6:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED RED.nodes.registerType("moment") — node-red-contrib-moment lacks registry:register
  Call stack:
    at module.exports (file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.mjs:5484:13)
    at /private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:10:26
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["registry:register"] } } }
[@allanoricil/nrg-sentinel] BLOCKED RED.nodes.registerType("humanizer") — node-red-contrib-moment lacks registry:register
  Call stack:
    at module.exports (file:///private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/humanizer.mjs:4504:13)
    at /private/tmp/sentinel-dev-U239Wj/node_modules/node-red-contrib-moment/_sentinel/humanizer.cjs:10:26
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["registry:register"] } } }
4 Apr 23:57:44 - [error] [nrg-sentinel] Failed to load ESM bundle moment: [@allanoricil/nrg-sentinel] registerType("moment") blocked — needs registry:register. Caller: node-red-contrib-moment
4 Apr 23:57:44 - [error] [nrg-sentinel] Failed to load ESM bundle humanizer: [@allanoricil/nrg-sentinel] registerType("humanizer") blocked — needs registry:register. Caller: node-red-contrib-moment

```

You can also see that the package was properly bundled with its whole dependency tree during installation.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/e/9e4c04486cd668d040093f209ea0514ca894491f.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/6/0655f72208691613a6f4327dabc6772e3ecf0c61.png)

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [5 April 2026 03:54 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/64 "2026-04-05T03:54:14Z")

</div>

Here are the logs showing what happens after every grant is given to a package. You will notice error messages keep disapearing as soon as grants are given.

```bash
5 Apr 00:49:42 - [info] Starting flows
5 Apr 00:49:42 - [info] Started flows
5 Apr 00:49:42 - [info] Server now running at http://127.0.0.1:1880/
[@allanoricil/nrg-sentinel] BLOCKED process.env.OS_LOCALE_S_DEBUG — node-red-contrib-moment lacks process:env:read
  Call stack:
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5053:34
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5201:14
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5267:23
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:7:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LC_ALL — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5150:50)
    at detectorBase (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5233:28)
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5269:30
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:7:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LC_MESSAGES — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5150:64)
    at detectorBase (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5233:28)
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5269:30
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:7:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LANG — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5150:83)
    at detectorBase (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5233:28)
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5269:30
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:7:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LANGUAGE — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5150:95)
    at detectorBase (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5233:28)
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5269:30
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:7:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED RED.nodes.registerType("moment") — node-red-contrib-moment lacks registry:register
  Call stack:
    at module.exports (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361069422:5484:13)
    at /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:11:26
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["registry:register"] } } }
[@allanoricil/nrg-sentinel] BLOCKED RED.nodes.registerType("humanizer") — node-red-contrib-moment lacks registry:register
  Call stack:
    at module.exports (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/humanizer.mjs?v=1775361069426:4504:13)
    at /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/humanizer.cjs:11:26
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["registry:register"] } } }
5 Apr 00:51:09 - [error] [nrg-sentinel] Failed to load ESM bundle moment: [@allanoricil/nrg-sentinel] registerType("moment") blocked — needs registry:register. Caller: node-red-contrib-moment
5 Apr 00:51:09 - [error] [nrg-sentinel] Failed to load ESM bundle humanizer: [@allanoricil/nrg-sentinel] registerType("humanizer") blocked — needs registry:register. Caller: node-red-contrib-moment
5 Apr 00:51:09 - [info] [@allanoricil/nrg-sentinel] Hot-loaded: node-red-contrib-moment
5 Apr 00:51:19 - [info] [@allanoricil/nrg-sentinel] Hot-unloaded: node-red-contrib-moment
5 Apr 00:51:19 - [info] [@allanoricil/nrg-sentinel] Package grant saved (SPA): node-red-contrib-moment
[@allanoricil/nrg-sentinel] BLOCKED process.env.OS_LOCALE_S_DEBUG — node-red-contrib-moment lacks process:env:read
  Call stack:
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5053:34
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5201:14
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5267:23
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:7:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LC_ALL — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5150:50)
    at detectorBase (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5233:28)
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5269:30
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:7:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LC_MESSAGES — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5150:64)
    at detectorBase (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5233:28)
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5269:30
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:7:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LANG — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5150:83)
    at detectorBase (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5233:28)
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5269:30
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:7:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LANGUAGE — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5150:95)
    at detectorBase (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5233:28)
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5269:30
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:7:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED httpAdmin.get() — node-red-contrib-moment lacks http:admin
  Call stack:
    at module.exports (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5485:17)
    at /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:11:26
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["http:admin"] } } }
[@allanoricil/nrg-sentinel] BLOCKED httpAdmin.get() — node-red-contrib-moment lacks http:admin
  Call stack:
    at module.exports (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361079464:5494:17)
    at /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:11:26
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["http:admin"] } } }
5 Apr 00:51:19 - [info] [@allanoricil/nrg-sentinel] Hot-loaded: node-red-contrib-moment
5 Apr 00:51:19 - [info] [@allanoricil/nrg-sentinel] Reloaded after grant change: node-red-contrib-moment
5 Apr 00:51:33 - [info] [@allanoricil/nrg-sentinel] Hot-unloaded: node-red-contrib-moment
5 Apr 00:51:33 - [info] [@allanoricil/nrg-sentinel] Package grant saved (SPA): node-red-contrib-moment
[@allanoricil/nrg-sentinel] BLOCKED process.env.OS_LOCALE_S_DEBUG — node-red-contrib-moment lacks process:env:read
  Call stack:
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5053:34
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5201:14
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5267:23
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:7:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LC_ALL — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5150:50)
    at detectorBase (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5233:28)
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5269:30
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:7:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LC_MESSAGES — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5150:64)
    at detectorBase (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5233:28)
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5269:30
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:7:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LANG — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5150:83)
    at detectorBase (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5233:28)
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5269:30
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:7:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
[@allanoricil/nrg-sentinel] BLOCKED process.env.LANGUAGE — node-red-contrib-moment lacks process:env:read
  Call stack:
    at getEnvLocale (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5150:95)
    at detectorBase (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5227:22)
    at detector.sync (file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5233:28)
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5269:30
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:3:48
    at file:///private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.mjs?v=1775361093944:5501:16
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise. __proto__ (node:internal/modules/esm/loader:665:26)
    at async /private/tmp/sentinel-dev-0e0XQP/node_modules/node-red-contrib-moment/_sentinel/moment.cjs:7:21
  To allow, add to settings.js:
    sentinel: { packages: { "node-red-contrib-moment": { capabilities: ["process:env:read"] } } }
5 Apr 00:51:34 - [info] [@allanoricil/nrg-sentinel] Hot-loaded: node-red-contrib-moment
5 Apr 00:51:34 - [info] [@allanoricil/nrg-sentinel] Reloaded after grant change: node-red-contrib-moment
5 Apr 00:52:31 - [info] [@allanoricil/nrg-sentinel] Hot-unloaded: node-red-contrib-moment
5 Apr 00:52:32 - [info] [@allanoricil/nrg-sentinel] Package grant saved (SPA): node-red-contrib-moment
5 Apr 00:52:32 - [info] [@allanoricil/nrg-sentinel] Hot-loaded: node-red-contrib-moment
5 Apr 00:52:32 - [info] [@allanoricil/nrg-sentinel] Reloaded after grant change: node-red-contrib-moment

```

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/3/93acd49761208e5068d1423d3fee593642aae866.png)

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [6 April 2026 20:17 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/65 "2026-04-06T20:17:27Z")

</div>

All attempts to exfiltrate data from the editor by client-side code will be shown in the threats page in Sentinel Admin panel.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/e/0e31e4b1622a4c0dd44743d169720efd386d4f88.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/c/bc2bed4be9100c29036f0bed06da5ff6a2a65fc6.png)

The solution is very similar to how things are handled server-side.

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [7 April 2026 00:21 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/66 "2026-04-07T00:21:40Z")

</div>

Now the settings page has Runtime (Server) and Editor (Client) sections.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/e/4eff3b548a7a755eb8cf3d27a12bbe5a66aab1d6.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/2/b245a34e06b03e9977eb623d3227c65dd0d0d2ac.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/c/0cdb358d1263e2d22a96bf089be79b475441e6f3.png)

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [7 April 2026 17:03 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/67 "2026-04-07T17:03:10Z")

</div>

When a package is installed, a static analysis is performed immediately after bundling the server-side code to identify the permissions it may require.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/2/1/212394d88800df92b4201eab6c007d485c965c77.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/0/60e1ae919df067755fe6861cb4a680fb8efe39a0.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/f/1f324fba675377215e397cb3635272efcb6f366d.png)

Going forward, this analysis will be compared against the capabilities declared by the package author to ensure alignment and detect potential discrepancies.

Packages that do not comply with NRG Sentinel analysis or fail to declare the required grants will be assigned a reduced trust score, reflecting lower confidence in their integrity and transparency.

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [7 April 2026 21:45 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/68 "2026-04-07T21:45:45Z")

</div>

When installing an untrusted package, a manual review must be completed before the package can be activated. Static analysis is provided only as a support tool to highlight areas that may require closer inspection.

If the administrator trusts the package author, they may choose to install the package as trusted. In this mode, the package behaves similarly to a Node-RED core package.

However, this introduces significant risk: all dependencies of the package will bypass security controls, increasing exposure to supply chain attacks. For example, an indirect dependency could extract environment variables, inject hooks to monitor message flows, or rewrite nodes through virtual routes without the user’s awareness.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/3/1386de6d9f1e2e6a74d22e1b94b8a2c11fd5f0f6.png)

**Trusted vs. Untrusted Packages (Filesystem Model)**

Packages are classified based on their installation location and the level of runtime enforcement applied to them.

Untrusted packages are installed under `usrDir/node_modules`. These packages are subject to all runtime guards enforced by NRG Sentinel.

Trusted packages are installed in a separate, dedicated directory. Both trusted and untrusted directories are mounted as read-only for the Node-RED runtime user, preventing packages from mutating their own source code or that of others during execution.

The key distinction lies in enforcement: trusted packages bypass all runtime guards applied by NRG Sentinel and effectively operate with the same level of privilege as core packages.

This model introduces a clear trust boundary at the filesystem level while preserving runtime integrity through immutability and controlled execution paths.

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [8 April 2026 01:12 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/69 "2026-04-08T01:12:15Z")

</div>

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/e/5e51ebfdc86f80c6805c1aac3ab80cef916ab354.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/7/47fc7cb79a746f8cd518835815c0bfbc76c058f1.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/e/4/e42a1fcdf9704cb6f72fcf2d91fc1f694ee63a02.png)

**Trusted**  
Packages operate with full privileges, bypassing all runtime guards and behaving equivalently to core Node-RED components.

**Needs Review**  
Packages require explicit administrative approval. The admin reviews the entire bundled codebase, enabling inspection of both direct and indirect dependencies that may be compromised before granting permissions.

**Guarded**  
Packages have been reviewed, approved, and installed. They operate under enforced runtime guards with permissions (grants) explicitly applied and constrained according to the review outcome.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/f/af7b80a26ba4d8a6a267b522c892921028466f2a.png)

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [8 April 2026 03:15 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/70 "2026-04-08T03:15:12Z")

</div>

Added vulnerabilities info from Snyk, Socket and os.dev in the package details and in the package review pages. Be aware that these major apps scanners do not capture vulnerabitlities that happen specifically in Node-RED environments because they are mostly runtime ones operating under the rules of the game.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/4/649aa1dc72283b3faf9a026daeea294757153652.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/7/f7eb31f1139581f56f568c1cdc122a41dfecf371.png)

With NRG Sentinel, for example, your environment variables are guarded against evil packages.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/8/b/8bf28e2385fa89ff7866b2342cf5439b6ca01721.png)

Or a more advanced one, like dynamic routing of messages (virtual wiring)...

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [9 April 2026 04:07 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/72 "2026-04-09T04:07:05Z")

</div>

Some packages come from well-known vendors—such as @flowfuse/node-red-dashboard—and can be installed as “trusted.” When marked this way, Sentinel disables all runtime guards for those packages.

That said, this introduces a non-trivial risk. If any direct or indirect dependency within that package is compromised, Sentinel will not intercept it. Trusting a package effectively extends trust to its entire dependency tree—and in practice, most vendors do not fully audit their transitive dependencies. This creates a cascading trust model, which is exactly how supply chain attacks propagate.

The practical takeaway: treat “trusted” as an exception, not the default.

A more resilient approach is to install packages with Sentinel protections enabled, allow them to fail under guard enforcement, and then incrementally grant permissions as needed. This forces visibility into actual runtime behavior and ensures you are validating the entire bundle—not just the vendor’s surface-level code.

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [9 April 2026 04:30 UTC](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515/73 "2026-04-09T04:30:28Z")

</div>

Sentinel’s bundling step during installation is designed to handle even complex packages, such as @flowfuse/node-red-dashboard (Dashboard 2.0).

It produces a CommonJS (CJS) entry point that encapsulates and loads the entire ES module (ESM) bundle. This ensures compatibility with the runtime while still allowing Sentinel to analyze and instrument the full dependency graph as a single, controlled unit.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/e/b/ebd1dba08df75c605ceaf59d8342aec40878b564.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/d/4d7a72b941ff7485863b86da508fbe7f5cd8f4ce.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/6/d67ad34613b68ea49863a2883cc953d9e23cdc3e.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/c/e/ce427f235a8e8821a675801175d22a60d083957a.png)

[Previous page](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515.md?page=2)

[Next page](https://discourse.nodered.org/t/nrg-sentinel-runtime-security-for-node-red/100515.md?page=4)
