CVE-2026-63640
MagicMirror socket payload secret placeholder expansion can disclose SECRET_* environment variables
MagicMirror² is an open source modular smart mirror platform. Prior to 2.37.0, when hideConfigSecrets is enabled, the catch-all socket dispatcher in js/node_helper.js passes every inbound object payload through replaceSecretPlaceholder in js/server_functions.js before invoking socketNotificationReceived. A client connected to a loaded module namespace can submit a SECRET_API_KEY placeholder, causing the server to replace it with the corresponding process environment value. The default weather helper accepts INIT_WEATHER, copies the attacker-controlled instanceId, and returns it in WEATHER_ERROR, providing an echo path for the expanded secret. This reverses the intended one-way redaction boundary and can disclose API tokens, credentials, or service keys stored in SECRET_ variables. This issue is fixed in version 2.37.0.
Attack profile
How easy it is to exploit
- Attack vector
- Adjacent network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- Low
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
4.3
MagicMirror socket payload secret placeholder expansion can disclose SECRET_* environment variables
MagicMirror² is an open source modular smart mirror platform. Prior to 2.37.0, when hideConfigSecrets is enabled, the catch-all socket dispatcher in js/node_helper.js passes every inbound object payload through replaceSecretPlaceholder in js/server_functions.js before invoking socketNotificationReceived. A client connected to a loaded module namespace can submit a SECRET_API_KEY placeholder, causing the server to replace it with the corresponding process environment value. The default weather helper accepts INIT_WEATHER, copies the attacker-controlled instanceId, and returns it in WEATHER_ERROR, providing an echo path for the expanded secret. This reverses the intended one-way redaction boundary and can disclose API tokens, credentials, or service keys stored in SECRET_ variables. This issue is fixed in version 2.37.0.
- Record
CVE-2026-63640- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
EUVDEUVD-2026-61079
4.3
MagicMirror² is an open source modular smart mirror platform. Prior to 2.37.0, when hideConfigSecrets is enabled, the catch-all socket dispatcher in js/node_helper.js passes every inbound object payload through replaceSecretPlaceholder in js/server_functions.js before invoking socketNotificationReceived. A client connected to a loaded module namespace can submit a SECRET_API_KEY placeholder, causing the server to replace it with the corresponding process environment value. The default weather helper accepts INIT_WEATHER, copies the attacker-controlled instanceId, and returns it in WEATHER_ERROR, providing an echo path for the expanded secret. This reverses the intended one-way redaction boundary and can disclose API tokens, credentials, or service keys stored in SECRET_ variables. This issue is fixed in version 2.37.0.
- Record
EUVD-2026-61079- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-q4gh-4ffp-5cg8
4.3
MagicMirror socket payload secret placeholder expansion can disclose SECRET_* environment variables
Summary
When hideConfigSecrets: true is enabled, MagicMirror redacts SECRET_* environment placeholders in the HTTP /config response, but the shared node-helper socket dispatcher expands **SECRET_NAME** placeholders in every inbound socket payload before passing it to module helpers. Any client that can connect to a loaded module namespace can send a placeholder such as **SECRET_API_KEY** and cause the server to substitute the real environment variable into the helper payload. Helpers that echo attacker-controlled payload fields, such as the default weather helper error path, can return the secret value to the socket client.
Details
The affected product is the npm package/application magicmirror at version 2.36.0, tested at commit fb41d24ef522e91e802e2a623ff6afbddeb3c9d8 from https://github.com/MagicMirrorOrg/MagicMirror.git.
The secret-redaction feature is implemented during config loading:
js/utils.js:117-123loads aconfig.envfile next to the config file intoprocess.envwhen present.js/utils.js:130-151creates both a full config and a redacted config.js/utils.js:137-140redacts environment variables whose names start withSECRET_to**SECRET_NAME**in the redacted config whenhideConfigSecrets: trueis present.js/server.js:112-125returns eitherconfigObj.redactedConforconfigObj.fullConffrom/configdepending onconfig.hideConfigSecrets.
The disclosure root cause is the inbound socket dispatcher:
js/node_helper.js:88-103registers a catch-all handler for each module namespace.js/node_helper.js:91-99checksconfig?.hideConfigSecretsand, for every inbound object payload, runsreplaceSecretPlaceholder(JSON.stringify(payload))before invokingsocketNotificationReceived(...).js/server_functions.js:23-34implementsreplaceSecretPlaceholder(...)by replacing**SECRET_* **-style placeholders withprocess.env[...], unlessglobal.config.cors === "allowAll".
This reverses the redaction boundary: redacted placeholders intended for the browser can be sent back to the server and expanded into real environment secret values inside helper payloads.
A confirmed echo path exists in the default weather helper:
defaultmodules/weather/node_helper.js:12-19acceptsINIT_WEATHERfrom the socket.defaultmodules/weather/node_helper.js:27-31copiesconfig.instanceIdfrom the attacker-controlled payload.defaultmodules/weather/node_helper.js:47-52attempts to dynamically load the requested weather provider.defaultmodules/weather/node_helper.js:86-91catches errors and sendsWEATHER_ERRORwith the sameinstanceIdback to the namespace.
False-positive screening performed:
- This is not a generic environment leak through
/env;js/server_functions.js:221-240returns only selected client environment paths. - The HTTP
/configroute does redact placeholders whenhideConfigSecrets: true; the issue is that the inbound socket path expands those placeholders again before module helper code runs. replaceSecretPlaceholder(...)intentionally refuses substitution whenglobal.config.cors === "allowAll"(js/server_functions.js:29-34); the positive PoC usedcors: "disabled", which is the shipped default (js/defaults.js:14). A negative control with no substitution produced the placeholder unchanged.- The attacker must know or infer a
SECRET_*variable name. If the attacker can read the redacted/configresponse, placeholder names may be disclosed even when values are hidden. The PoC uses a knownSECRET_MM_AUDITtest variable. - Network reachability follows the Socket.IO exposure model. With the shipped default
address: "localhost"and loopbackipWhitelist, remote network reachability is limited. In documented non-loopback deployments, this combines with the Socket.IO access-control gap described separately.
Affected-version evidence: only [email protected] at commit…
- Record
GHSA-q4gh-4ffp-5cg8- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
NVD
4.3
MagicMirror² is an open source modular smart mirror platform. Prior to 2.37.0, when hideConfigSecrets is enabled, the catch-all socket dispatcher in js/node_helper.js passes every inbound object payload through replaceSecretPlaceholder in js/server_functions.js before invoking socketNotificationReceived. A client connected to a loaded module namespace can submit a SECRET_API_KEY placeholder, causing the server to replace it with the corresponding process environment value. The default weather helper accepts INIT_WEATHER, copies the attacker-controlled instanceId, and returns it in WEATHER_ERROR, providing an echo path for the expanded secret. This reverses the intended one-way redaction boundary and can disclose API tokens, credentials, or service keys stored in SECRET_ variables. This issue is fixed in version 2.37.0.
- Record
CVE-2026-63640- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
OSV
4.3
MagicMirror socket payload secret placeholder expansion can disclose SECRET_* environment variables
MagicMirror² is an open source modular smart mirror platform. Prior to 2.37.0, when hideConfigSecrets is enabled, the catch-all socket dispatcher in js/node_helper.js passes every inbound object payload through replaceSecretPlaceholder in js/server_functions.js before invoking socketNotificationReceived. A client connected to a loaded module namespace can submit a SECRET_API_KEY placeholder, causing the server to replace it with the corresponding process environment value. The default weather helper accepts INIT_WEATHER, copies the attacker-controlled instanceId, and returns it in WEATHER_ERROR, providing an echo path for the expanded secret. This reverses the intended one-way redaction boundary and can disclose API tokens, credentials, or service keys stored in SECRET_ variables. This issue is fixed in version 2.37.0.
- Record
CVE-2026-63640- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
OSVGHSA-q4gh-4ffp-5cg8
4.3
MagicMirror socket payload secret placeholder expansion can disclose SECRET_* environment variables
Summary
When hideConfigSecrets: true is enabled, MagicMirror redacts SECRET_* environment placeholders in the HTTP /config response, but the shared node-helper socket dispatcher expands **SECRET_NAME** placeholders in every inbound socket payload before passing it to module helpers. Any client that can connect to a loaded module namespace can send a placeholder such as **SECRET_API_KEY** and cause the server to substitute the real environment variable into the helper payload. Helpers that echo attacker-controlled payload fields, such as the default weather helper error path, can return the secret value to the socket client.
Details
The affected product is the npm package/application magicmirror at version 2.36.0, tested at commit fb41d24ef522e91e802e2a623ff6afbddeb3c9d8 from https://github.com/MagicMirrorOrg/MagicMirror.git.
The secret-redaction feature is implemented during config loading:
js/utils.js:117-123loads aconfig.envfile next to the config file intoprocess.envwhen present.js/utils.js:130-151creates both a full config and a redacted config.js/utils.js:137-140redacts environment variables whose names start withSECRET_to**SECRET_NAME**in the redacted config whenhideConfigSecrets: trueis present.js/server.js:112-125returns eitherconfigObj.redactedConforconfigObj.fullConffrom/configdepending onconfig.hideConfigSecrets.
The disclosure root cause is the inbound socket dispatcher:
js/node_helper.js:88-103registers a catch-all handler for each module namespace.js/node_helper.js:91-99checksconfig?.hideConfigSecretsand, for every inbound object payload, runsreplaceSecretPlaceholder(JSON.stringify(payload))before invokingsocketNotificationReceived(...).js/server_functions.js:23-34implementsreplaceSecretPlaceholder(...)by replacing**SECRET_* **-style placeholders withprocess.env[...], unlessglobal.config.cors === "allowAll".
This reverses the redaction boundary: redacted placeholders intended for the browser can be sent back to the server and expanded into real environment secret values inside helper payloads.
A confirmed echo path exists in the default weather helper:
defaultmodules/weather/node_helper.js:12-19acceptsINIT_WEATHERfrom the socket.defaultmodules/weather/node_helper.js:27-31copiesconfig.instanceIdfrom the attacker-controlled payload.defaultmodules/weather/node_helper.js:47-52attempts to dynamically load the requested weather provider.defaultmodules/weather/node_helper.js:86-91catches errors and sendsWEATHER_ERRORwith the sameinstanceIdback to the namespace.
False-positive screening performed:
- This is not a generic environment leak through
/env;js/server_functions.js:221-240returns only selected client environment paths. - The HTTP
/configroute does redact placeholders whenhideConfigSecrets: true; the issue is that the inbound socket path expands those placeholders again before module helper code runs. replaceSecretPlaceholder(...)intentionally refuses substitution whenglobal.config.cors === "allowAll"(js/server_functions.js:29-34); the positive PoC usedcors: "disabled", which is the shipped default (js/defaults.js:14). A negative control with no substitution produced the placeholder unchanged.- The attacker must know or infer a
SECRET_*variable name. If the attacker can read the redacted/configresponse, placeholder names may be disclosed even when values are hidden. The PoC uses a knownSECRET_MM_AUDITtest variable. - Network reachability follows the Socket.IO exposure model. With the shipped default
address: "localhost"and loopbackipWhitelist, remote network reachability is limited. In documented non-loopback deployments, this combines with the Socket.IO access-control gap described separately.
Affected-version evidence: only [email protected] at commit…
- Record
GHSA-q4gh-4ffp-5cg8- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
magicmirrornpm |
before 2.37.0 | 2.37.0 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-63640 is a medium vulnerability (CVSS 4.3) in Magicmirrororg Magicmirror, published August 18, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.30%, the 22nd percentile. Fixed in magicmirror 2.37.0.
References
github.com/MagicMirrorOrg/MagicMirror/security/advisories/GHSA-q4gh-4ffp-5cg8
github.com/MagicMirrorOrg/MagicMirror/pull/4184
github.com/MagicMirrorOrg/MagicMirror/commit/ca7b752025962441196e148f8c1bc04b90117979
github.com/MagicMirrorOrg/MagicMirror/releases/tag/v2.37.0
github.com/advisories/GHSA-q4gh-4ffp-5cg8
github.com/CVEProject/cvelistV5/tree/main/cves/2026/63xxx/CVE-2026-63640.json
nvd.nist.gov/vuln/detail/CVE-2026-63640
github.com/MagicMirrorOrg/MagicMirror
Left out here: the rest of 2 source descriptions. The JSON record has them.