CVE-2026-63466
Unleash: Global Mustache.escape override disables HTML escaping process-wide, enabling Slack/Teams link-injection via unrestricted username
Unleash is an open-source feature management platform. Prior to 8.0.3, FeatureEventFormatterMd.format in src/lib/addons/feature-event-formatter-md.ts assigns Mustache.escape to an identity function before rendering action and path templates. Because Mustache.escape is process-wide, the assignment disables escaping for subsequent Mustache.render calls in email-service.ts, webhook.ts, datadog.ts, and new-relic.ts. An editor-level user can place Slack or Microsoft Teams link syntax in an unrestricted username, trigger a feature event, and inject an attacker-labeled link into a trusted outbound notification channel, while other Mustache sinks remain unescaped until restart. This issue is fixed in version 8.0.3.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- Required
What an attacker can affect
- Confidentiality
- None
- Integrity
- Low
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
4.1
Unleash: Global Mustache.escape override disables HTML escaping process-wide, enabling Slack/Teams link-injection via unrestricted username
Unleash is an open-source feature management platform. Prior to 8.0.3, FeatureEventFormatterMd.format in src/lib/addons/feature-event-formatter-md.ts assigns Mustache.escape to an identity function before rendering action and path templates. Because Mustache.escape is process-wide, the assignment disables escaping for subsequent Mustache.render calls in email-service.ts, webhook.ts, datadog.ts, and new-relic.ts. An editor-level user can place Slack or Microsoft Teams link syntax in an unrestricted username, trigger a feature event, and inject an attacker-labeled link into a trusted outbound notification channel, while other Mustache sinks remain unescaped until restart. This issue is fixed in version 8.0.3.
- Record
CVE-2026-63466- CVSS 3.1
- 4.1 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:N/I:L/A:N - Weakness
- CWE-116
- Updated
- 2026-11-02
EUVDEUVD-2026-64042
4.1
Unleash is an open-source feature management platform. Prior to 8.0.3, FeatureEventFormatterMd.format in src/lib/addons/feature-event-formatter-md.ts assigns Mustache.escape to an identity function before rendering action and path templates. Because Mustache.escape is process-wide, the assignment disables escaping for subsequent Mustache.render calls in email-service.ts, webhook.ts, datadog.ts, and new-relic.ts. An editor-level user can place Slack or Microsoft Teams link syntax in an unrestricted username, trigger a feature event, and inject an attacker-labeled link into a trusted outbound notification channel, while other Mustache sinks remain unescaped until restart. This issue is fixed in version 8.0.3.
- Record
EUVD-2026-64042- CVSS 3.1
- 4.1 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:N/I:L/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-w4mq-xh27-6xpx
4.1
Unleash: Global Mustache.escape override disables HTML escaping process-wide, enabling Slack/Teams link-injection via unrestricted username
Vulnerability Details
File: src/lib/addons/feature-event-formatter-md.ts
Line: 355 (in v8.0.1; format() method)
Root Cause
FeatureEventFormatterMd.format() does:
Mustache.escape = (text) => text;
const text = Mustache.render(action, context);
mustache (pinned ^4.2.0, confirmed installed 4.2.0) keeps escape as a module-level singleton (mustache.js: mustache.escape = escapeHtml;), read by every Mustache.render() call in the process unless a per-call config.escape override is passed (var escape = this.getConfigEscape(config) || mustache.escape;). Node's module cache guarantees every import Mustache from 'mustache' in the process — feature-event-formatter-md.ts, email-service.ts, webhook.ts, datadog.ts, new-relic.ts — shares the same object instance.
This assignment therefore permanently disables HTML escaping for every other Mustache.render() call in the same Node process (including email-service.ts templates) from the moment any single notification addon (Webhook, Slack legacy, Microsoft Teams, Datadog, New Relic) first formats any event, for the remaining lifetime of the process.
feature-event-formatter-md-events.ts (EVENT_MAP) confirms the blast radius: nearly every event's action template interpolates attacker-controlled values with single-mustache (intended-to-be-escaped) syntax, most importantly {{user}}, which is event.createdBy — the acting account's username (or email if set; src/lib/util/extract-user.ts: extractUsernameFromUser). Neither username nor name have any charset/length validation anywhere in the codebase (create-user-schema.ts, create-invited-user-schema.ts, user-service.ts:289 only does Joi.assert(name, Joi.string(), 'Name') — a type check, nothing more).
Slack's own API docs require &, <, > to be replaced with &, <, > before sending user-generated text, specifically so Slack's mrkdwn parser does not interpret it as <url|label> link syntax. Mustache's default escapeHtml happens to produce exactly those entities, so this was (likely unintentionally) the application's only defense against link-injection in chat notifications — and it is unconditionally switched off by the same code path that depends on it.
Attack Scenario
- Admin has a Webhook, Slack (legacy), Microsoft Teams, Datadog, or New Relic integration configured (a very common production setup for flag-change notifications).
- Attacker has (or self-registers, if public signup is enabled —
POST /invite/:token/signupispermission: NONE) any Editor-level account and setsusernameto e.g.evil<https://attacker.example/urgent-rollback|Click here to view incident>. - Attacker performs any ordinary write action (create/update/toggle a feature flag — routine, no special privilege beyond Editor on one project).
- The configured addon's
handleEvent()callsthis.msgFormatter.format(event), which mutates the global escape function and immediately renders the{{user}}-containing template with escaping disabled. - The resulting message — containing the attacker's raw
<url|label>Slack link syntax — is POSTed to the team's Slack/Teams channel or webhook endpoint and rendered as a real, clickable, attacker-labeled hyperlink inside a trusted automated notification feed.
Vulnerable Code
Mustache.escape = (text) => text;
const text = Mustache.render(action, context);
const url = path
? `${this.unleashUrl}${Mustache.render(path, context)}`
: undefined;
Impact
- Stored markdown/link-injection (phishing-link injection) into any configured outbound notification channel (Slack legacy, MS Teams, Webhook default markdown, Datadog, New Relic), using an attacker-controlled username — no admin privilege required, only Editor on a single project, and potentially reachable through public self-signup.
- Secondary: loss of HTML escaping for any other reachable Mustache…
- Record
GHSA-w4mq-xh27-6xpx- CVSS 3.1
- 4.1 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:N/I:L/A:N - Weakness
- CWE-116
- Updated
- 2026-11-02
NVD
4.1
Unleash is an open-source feature management platform. Prior to 8.0.3, FeatureEventFormatterMd.format in src/lib/addons/feature-event-formatter-md.ts assigns Mustache.escape to an identity function before rendering action and path templates. Because Mustache.escape is process-wide, the assignment disables escaping for subsequent Mustache.render calls in email-service.ts, webhook.ts, datadog.ts, and new-relic.ts. An editor-level user can place Slack or Microsoft Teams link syntax in an unrestricted username, trigger a feature event, and inject an attacker-labeled link into a trusted outbound notification channel, while other Mustache sinks remain unescaped until restart. This issue is fixed in version 8.0.3.
- Record
CVE-2026-63466- CVSS 3.1
- 4.1 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:N/I:L/A:N - Weakness
- CWE-116
- Updated
- 2026-11-02
OSV
4.1
Unleash: Global Mustache.escape override disables HTML escaping process-wide, enabling Slack/Teams link-injection via unrestricted username
Unleash is an open-source feature management platform. Prior to 8.0.3, FeatureEventFormatterMd.format in src/lib/addons/feature-event-formatter-md.ts assigns Mustache.escape to an identity function before rendering action and path templates. Because Mustache.escape is process-wide, the assignment disables escaping for subsequent Mustache.render calls in email-service.ts, webhook.ts, datadog.ts, and new-relic.ts. An editor-level user can place Slack or Microsoft Teams link syntax in an unrestricted username, trigger a feature event, and inject an attacker-labeled link into a trusted outbound notification channel, while other Mustache sinks remain unescaped until restart. This issue is fixed in version 8.0.3.
- Record
CVE-2026-63466- CVSS 3.1
- 4.1 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:N/I:L/A:N - Weakness
- CWE-116
- Updated
- 2026-11-02
OSVGHSA-w4mq-xh27-6xpx
4.1
Unleash: Global Mustache.escape override disables HTML escaping process-wide, enabling Slack/Teams link-injection via unrestricted username
Vulnerability Details
File: src/lib/addons/feature-event-formatter-md.ts
Line: 355 (in v8.0.1; format() method)
Root Cause
FeatureEventFormatterMd.format() does:
Mustache.escape = (text) => text;
const text = Mustache.render(action, context);
mustache (pinned ^4.2.0, confirmed installed 4.2.0) keeps escape as a module-level singleton (mustache.js: mustache.escape = escapeHtml;), read by every Mustache.render() call in the process unless a per-call config.escape override is passed (var escape = this.getConfigEscape(config) || mustache.escape;). Node's module cache guarantees every import Mustache from 'mustache' in the process — feature-event-formatter-md.ts, email-service.ts, webhook.ts, datadog.ts, new-relic.ts — shares the same object instance.
This assignment therefore permanently disables HTML escaping for every other Mustache.render() call in the same Node process (including email-service.ts templates) from the moment any single notification addon (Webhook, Slack legacy, Microsoft Teams, Datadog, New Relic) first formats any event, for the remaining lifetime of the process.
feature-event-formatter-md-events.ts (EVENT_MAP) confirms the blast radius: nearly every event's action template interpolates attacker-controlled values with single-mustache (intended-to-be-escaped) syntax, most importantly {{user}}, which is event.createdBy — the acting account's username (or email if set; src/lib/util/extract-user.ts: extractUsernameFromUser). Neither username nor name have any charset/length validation anywhere in the codebase (create-user-schema.ts, create-invited-user-schema.ts, user-service.ts:289 only does Joi.assert(name, Joi.string(), 'Name') — a type check, nothing more).
Slack's own API docs require &, <, > to be replaced with &, <, > before sending user-generated text, specifically so Slack's mrkdwn parser does not interpret it as <url|label> link syntax. Mustache's default escapeHtml happens to produce exactly those entities, so this was (likely unintentionally) the application's only defense against link-injection in chat notifications — and it is unconditionally switched off by the same code path that depends on it.
Attack Scenario
- Admin has a Webhook, Slack (legacy), Microsoft Teams, Datadog, or New Relic integration configured (a very common production setup for flag-change notifications).
- Attacker has (or self-registers, if public signup is enabled —
POST /invite/:token/signupispermission: NONE) any Editor-level account and setsusernameto e.g.evil<https://attacker.example/urgent-rollback|Click here to view incident>. - Attacker performs any ordinary write action (create/update/toggle a feature flag — routine, no special privilege beyond Editor on one project).
- The configured addon's
handleEvent()callsthis.msgFormatter.format(event), which mutates the global escape function and immediately renders the{{user}}-containing template with escaping disabled. - The resulting message — containing the attacker's raw
<url|label>Slack link syntax — is POSTed to the team's Slack/Teams channel or webhook endpoint and rendered as a real, clickable, attacker-labeled hyperlink inside a trusted automated notification feed.
Vulnerable Code
Mustache.escape = (text) => text;
const text = Mustache.render(action, context);
const url = path
? `${this.unleashUrl}${Mustache.render(path, context)}`
: undefined;
Impact
- Stored markdown/link-injection (phishing-link injection) into any configured outbound notification channel (Slack legacy, MS Teams, Webhook default markdown, Datadog, New Relic), using an attacker-controlled username — no admin privilege required, only Editor on a single project, and potentially reachable through public self-signup.
- Secondary: loss of HTML escaping for any other reachable Mustache…
- Record
GHSA-w4mq-xh27-6xpx- CVSS 3.1
- 4.1 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:N/I:L/A:N - Weakness
- CWE-116
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
unleash-servernpm |
before 8.0.3 | 8.0.3 |
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-63466 is a medium vulnerability (CVSS 4.1) in Unleash, published August 21, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.32%, the 25th percentile. Fixed in unleash-server 8.0.3.
References
github.com/Unleash/unleash/security/advisories/GHSA-w4mq-xh27-6xpx
github.com/Unleash/unleash/commit/002012cfdbedd2e9b7db9dc83b9f549f761db22e
github.com/Unleash/unleash/releases/tag/v8.0.3
github.com/advisories/GHSA-w4mq-xh27-6xpx
github.com/CVEProject/cvelistV5/tree/main/cves/2026/63xxx/CVE-2026-63466.json
nvd.nist.gov/vuln/detail/CVE-2026-63466
github.com/Unleash/unleash
Left out here: the rest of 2 source descriptions. The JSON record has them.