Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,17 @@ Enable [FIPS mode][] at startup. With OpenSSL 3, a configured provider named
`fips` must be available and initialize successfully. With OpenSSL 1.1.1,
Node.js must be built against a FIPS-capable OpenSSL.

### `--enable-fips-indicator-events`

<!-- YAML
added: REPLACEME
-->

Publish OpenSSL FIPS indicator results to the
[`'crypto.fips.indicator'`][] diagnostics channel. This option requires OpenSSL
3.4 or later. It does not enable [FIPS mode][] or change whether an operation
is permitted.

### `--enable-source-maps`

<!-- YAML
Expand Down Expand Up @@ -1590,11 +1601,28 @@ Disable loading native addons that are not [context-aware][].

<!-- YAML
added: v6.0.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/65645
description: Added the optional `provider` and `strict` modes.
-->

Enable [FIPS mode][] at startup and prevent it from being disabled from script
code. The same OpenSSL requirements as [`--enable-fips`][] apply.

An optional mode can be specified using `--force-fips=mode`:

* `provider`: Preserve the OpenSSL FIPS provider's configured handling of
non-approved operations. This is the current default when the mode is
omitted.
* `strict`: Reject non-approved operations reported through the OpenSSL FIPS
indicator callback. This mode requires OpenSSL 3.4 or later.

The `strict` mode only covers operations reported through the callback for
OpenSSL's default library context. It does not cover native addons that use
another `OSSL_LIB_CTX` or another copy of `libcrypto`, nor operation-specific
indicators that do not invoke the callback.

### `--force-node-api-uncaught-exceptions-policy`

<!-- YAML
Expand Down Expand Up @@ -3895,6 +3923,7 @@ one is included in the list below.
* `--disable-warning`
* `--disable-wasm-trap-handler`
* `--dns-result-order`
* `--enable-fips-indicator-events`
* `--enable-fips`
* `--enable-network-family-autoselection`
* `--enable-source-maps`
Expand Down Expand Up @@ -4533,6 +4562,7 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12
[V8 Inspector integration for Node.js]: debugger.md#v8-inspector-integration-for-nodejs
[V8 JavaScript code coverage]: https://v8project.blogspot.com/2017/12/javascript-code-coverage.html
[`"type"`]: packages.md#type
[`'crypto.fips.indicator'`]: diagnostics_channel.md#event-cryptofipsindicator
[`--allow-addons`]: #--allow-addons
[`--allow-child-process`]: #--allow-child-process
[`--allow-fs-read`]: #--allow-fs-read
Expand Down
10 changes: 9 additions & 1 deletion doc/api/crypto.md
Original file line number Diff line number Diff line change
Expand Up @@ -7278,12 +7278,18 @@ startup. The following controls are also available:
* [`--enable-fips`][] and [`--force-fips`][] enable the property query and
additionally require the configured provider named `fips` to initialize and
pass its self-test. Node.js exits if that check fails. `--force-fips` also
prevents FIPS mode from being disabled from script code.
prevents FIPS mode from being disabled from script code. With
`--force-fips=strict`, Node.js also rejects non-approved operations reported
through the OpenSSL FIPS indicator callback.
* [`crypto.setFips()`][] changes the FIPS/property-query state. On OpenSSL 3, it
does not install, load, initialize, or validate a provider. Implementations
fetched before the call are not changed.
* [`crypto.getFips()`][] reports the FIPS/property-query state. On OpenSSL 3, a
return value of `1` does not prove that a FIPS provider is loaded or validated.
* With [`--enable-fips-indicator-events`][], the
[`'crypto.fips.indicator'`][] diagnostics channel reports non-approved
operations permitted by an OpenSSL 3.4 or later FIPS provider configured for
backwards compatibility.

With OpenSSL 1.1.1, these controls use the library's FIPS mode support and
require a FIPS-capable OpenSSL build.
Expand Down Expand Up @@ -7612,7 +7618,9 @@ See the [list of SSL OP Flags][] for details.
[SIV and GCM-SIV modes]: #siv-and-gcm-siv-modes
[Web Crypto API documentation]: webcrypto.md
[XTS mode]: #xts-mode
[`'crypto.fips.indicator'`]: diagnostics_channel.md#event-cryptofipsindicator
[`--allow-openssl-store`]: cli.md#--allow-openssl-store
[`--enable-fips-indicator-events`]: cli.md#--enable-fips-indicator-events
[`--enable-fips`]: cli.md#--enable-fips
[`--force-fips`]: cli.md#--force-fips
[`--openssl-config`]: cli.md#--openssl-configfile
Expand Down
68 changes: 68 additions & 0 deletions doc/api/diagnostics_channel.md
Original file line number Diff line number Diff line change
Expand Up @@ -1570,6 +1570,72 @@ passed to `console.warn()`.
Emitted when `console.error()` is called. Receives and array of the arguments
passed to `console.error()`.

#### Crypto

<!-- YAML
added: REPLACEME
-->

> Stability: 1 - Experimental

##### Event: `'crypto.fips.indicator'`

* `operation` {string} The provider-defined operation type.
* `reason` {string} The provider-defined description of why the operation is
not approved.
* `blocked` {boolean} Whether an indicator callback blocked the operation.
* `count` {number} The number of matching pending indicator invocations
represented by this message.
* `dropped` {number} The number of additional indicator invocations dropped
before this message was delivered.

Emitted when the OpenSSL FIPS provider used by Node.js detects an operation that
is not FIPS approved after the corresponding provider check was relaxed. Such
operations are possible when the provider is configured for backwards
compatibility. The `operation` and `reason` values come from the provider and
should be treated as opaque strings rather than stable enumerations.

Start Node.js with [`--enable-fips-indicator-events`][] to enable this channel.
Without the option, subscribing does not install the OpenSSL callback and no
messages are published.

Subscribing to the channel is observation-only and never changes the result of
an operation. Node.js preserves the result from any native indicator callback
installed before Node.js initializes its crypto support. When
[`--force-fips=strict`][] is used, Node.js rejects callback-indicated
non-approved operations whether or not indicator events are enabled or the
channel has subscribers.

Messages are published asynchronously on the main thread because OpenSSL
indicators can originate from Workers or other threads. Only subscriptions on
the main thread receive messages. Delivery order relative to the originating
operation is not defined, and a message cannot be correlated with a particular
call or Worker.

One cryptographic operation can invoke the OpenSSL indicator more than once.
Matching pending invocations are coalesced and reflected in `count`, which does
not necessarily represent a number of cryptographic operations. At most 256
distinct messages are queued. Additional invocations are reported in `dropped`
on the first queued message. Queued messages do not keep the event loop active,
so this channel is best-effort diagnostics rather than an authoritative audit
log.

This channel observes the default OpenSSL library context used by Node.js. It
does not observe native addons or other code that uses another `OSSL_LIB_CTX`
or another copy of `libcrypto`. It is active with OpenSSL 3.4 and later and is
not available with BoringSSL. A provider configured to reject a check directly,
including a pedantic OpenSSL FIPS provider, can reject an operation without
emitting an indicator. Receiving or not receiving a message does not establish
that Node.js or a cryptographic operation is FIPS validated.

```mjs
import diagnosticsChannel from 'node:diagnostics_channel';

diagnosticsChannel.subscribe('crypto.fips.indicator', (message) => {
console.error('Non-approved cryptographic operation', message);
});
```

#### HTTP

> Stability: 1 - Experimental
Expand Down Expand Up @@ -1963,6 +2029,8 @@ statement, since both are still in use while the event is being delivered; see
[BoundedChannel Channels]: #boundedchannel-channels
[TracingChannel Channels]: #tracingchannel-channels
[`'uncaughtException'`]: process.md#event-uncaughtexception
[`--enable-fips-indicator-events`]: cli.md#--enable-fips-indicator-events
[`--force-fips=strict`]: cli.md#--force-fips
[`BoundedChannel`]: #class-boundedchannel
[`DatabaseSync`]: sqlite.md#class-databasesync
[`TracingChannel`]: #class-tracingchannel
Expand Down
22 changes: 22 additions & 0 deletions doc/node.1
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,12 @@ Enable FIPS mode at startup. With OpenSSL 3, a configured provider named
\fBfips\fR must be available and initialize successfully. With OpenSSL 1.1.1,
Node.js must be built against a FIPS-capable OpenSSL.
.
.It Fl -enable-fips-indicator-events
Publish OpenSSL FIPS indicator results to the
\fB'crypto.fips.indicator'\fR diagnostics channel. This option requires OpenSSL
3.4 or later. It does not enable FIPS mode or change whether an operation
is permitted.
.
.It Fl -enable-source-maps
Enable Source Map support for stack traces.
When using a transpiler, such as TypeScript, stack traces thrown by an
Expand Down Expand Up @@ -844,6 +850,20 @@ Disable loading native addons that are not context-aware.
.It Fl -force-fips
Enable FIPS mode at startup and prevent it from being disabled from script
code. The same OpenSSL requirements as \fB--enable-fips\fR apply.
An optional mode can be specified using \fB--force-fips=mode\fR:
.Bl -bullet
.It
\fBprovider\fR: Preserve the OpenSSL FIPS provider's configured handling of
non-approved operations. This is the current default when the mode is
omitted.
.It
\fBstrict\fR: Reject non-approved operations reported through the OpenSSL FIPS
indicator callback. This mode requires OpenSSL 3.4 or later.
.El
The \fBstrict\fR mode only covers operations reported through the callback for
OpenSSL's default library context. It does not cover native addons that use
another \fBOSSL_LIB_CTX\fR or another copy of \fBlibcrypto\fR, nor operation-specific
indicators that do not invoke the callback.
.
.It Fl -force-node-api-uncaught-exceptions-policy
Enforces \fBuncaughtException\fR event on Node-API asynchronous callbacks.
Expand Down Expand Up @@ -1978,6 +1998,8 @@ one is included in the list below.
.It
\fB--dns-result-order\fR
.It
\fB--enable-fips-indicator-events\fR
.It
\fB--enable-fips\fR
.It
\fB--enable-network-family-autoselection\fR
Expand Down
3 changes: 3 additions & 0 deletions lib/internal/process/per_thread.js
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,9 @@ function buildAllowedFlags() {

const allowedNodeEnvironmentFlags = [];
for (const { 0: name, 1: info } of options) {
// Bracketed options are internal parser targets. They can be allowed in
// NODE_OPTIONS so aliases expand to them, but are not public flags.
if (name[0] === '[') continue;
if (info.envVarSettings === kAllowedInEnvvar) {
ArrayPrototypePush(allowedNodeEnvironmentFlags, name);
if (info.type === kBoolean) {
Expand Down
9 changes: 7 additions & 2 deletions lib/internal/process/pre_execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ function prepareExecution(options) {
// Process initial diagnostic reporting configuration, if present.
initializeReport();

setupDiagnosticsChannel();
setupDiagnosticsChannel(isMainThread);

// Load permission system API
initializePermission();
Expand Down Expand Up @@ -668,7 +668,7 @@ function initializeClusterIPC() {
}
}

function setupDiagnosticsChannel() {
function setupDiagnosticsChannel(isMainThread) {
// Re-link native channels after snapshot deserialization since
// JS references are cleared during serialization.
// Keep this callback in sync with the initial registration in
Expand All @@ -683,6 +683,11 @@ function setupDiagnosticsChannel() {
(channel._stores?.size || 0);
return channel;
});
if (isMainThread &&
process.versions.openssl !== undefined &&
getOptionValue('--enable-fips-indicator-events')) {
internalBinding('crypto').setupFipsIndicatorChannel();
}
}

function initializePermission() {
Expand Down
Loading
Loading