Every CVE Search/ Get API key

CVE-2026-112958

ApostropheCMS: Stored XSS via Unescaped Widget Style Attribute Serialization

5.4 MediumFix available

ApostropheCMS is an open-source Node.js content management system. Prior to 4.34.0, a project-defined free-form widget style field can carry an editor-controlled quote into an inline style attribute because the wrapper serializer does not apply HTML-attribute encoding. The quote can terminate the style attribute and inject executable attributes when published content, or an affected draft viewed by a higher-privileged user, is rendered. This issue is fixed in version 4.34.0.

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
Low
Integrity
Low
Availability
None

Exploit likelihood

0.30%Unchanged since Oct 21, 2026
90%50%10%1%

What each source reports

CVE List Score used 5.4

ApostropheCMS: Stored XSS via Unescaped Widget Style Attribute Serialization

ApostropheCMS is an open-source Node.js content management system. Prior to 4.34.0, a project-defined free-form widget style field can carry an editor-controlled quote into an inline style attribute because the wrapper serializer does not apply HTML-attribute encoding. The quote can terminate the style attribute and inject executable attributes when published content, or an affected draft viewed by a higher-privileged user, is rendered. This issue is fixed in version 4.34.0.

Record
CVE-2026-112958
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
EUVDEUVD-2026-105171 5.4

ApostropheCMS is an open-source Node.js content management system. Prior to 4.34.0, a project-defined free-form widget style field can carry an editor-controlled quote into an inline style attribute because the wrapper serializer does not apply HTML-attribute encoding. The quote can terminate the style attribute and inject executable attributes when published content, or an affected draft viewed by a higher-privileged user, is rendered. This issue is fixed in version 4.34.0.

Record
EUVD-2026-105171
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-7jg5-frgc-c67w 5.4

ApostropheCMS: Stored XSS via Unescaped Widget Style Attribute Serialization

Summary

ApostropheCMS widget styles support project-defined schema fields. If a project defines a free-form string style field with a CSS property and no selector, an editor-controlled value is rendered as an inline CSS declaration. The resulting declaration is then inserted into the widget wrapper's style="..." attribute without HTML-attribute escaping.

An attacker who can edit the widget can include a double quote in the style value, terminate the style attribute, and inject new HTML event-handler attributes. The payload is stored with the widget and executes in the Apostrophe site origin whenever the affected published page is rendered.

This is a sibling of CVE-2026-33889 / GHSA-97v6-998m-fp4g. The earlier issue escaped from a <style> element through a malicious color value. This variant reaches a different sink related to the automatically generated widget wrapper's inline style and class attributes.

Details

Root Cause 1: Free-form string style values retain HTML metacharacters

The standard string field converter uses launder.string() and length validation. This performs type normalization, not output encoding for an HTML attribute context:

packages/apostrophe/modules/@apostrophecms/schema/lib/addFieldTypes.js:296-333

self.addFieldType({
  name: 'string',
  // ...
  convert(req, field, data, destination) {
    destination[field.name] = self.apos.launder.string(data[field.name]);
    destination[field.name] = checkStringLength(
      destination[field.name],
      field.min,
      field.max
    );
  }
});

Quotes therefore remain in a value supplied through a style field.

Root Cause 2: The value is converted into inline CSS without value validation

For a field with property but no selector or media query, renderScopedStyles() selects inline rendering. The generic extractor concatenates the configured property and editor-controlled value:

packages/apostrophe/modules/@apostrophecms/styles/ui/apos/universal/render.mjs:171-228

packages/apostrophe/modules/@apostrophecms/styles/ui/apos/universal/render.mjs:598-647

rule = `${property}: ${normalized.value}${normalized.unit}`;

// ...

if (isInline) {
  return {
    css: '',
    classes: [ ...storage.classes ],
    inline: stringifyRules(storage.styles, true)
  };
}

For example, the value below becomes part of a font-family declaration:

serif" tabindex="0" autofocus onfocus="document.body.dataset.inline='executed'

Root Cause 3: Attribute values are serialized without HTML escaping

getWidgetAttributes() places the inline CSS into an attribute tuple, then concatenates every tuple into key="value" without encoding &, <, >, ', or ":

packages/apostrophe/modules/@apostrophecms/styles/lib/methods.js:251-322

if (styleParts.length) {
  attrs.push(
    [ 'style', `${styleParts.join(';')};` ]
  );
}

if (options.asObject) {
  return Object.fromEntries(attrs);
}

return attrs
  .map(([ key, value ]) => `${key}="${value}"`)
  .join(' ');

The same raw serializer also makes a project-defined free-form string style with class: true a potential sibling path, because the string is added to classes and later serialized into class="...". The…

Record
GHSA-7jg5-frgc-c67w
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
NVD 5.4

ApostropheCMS is an open-source Node.js content management system. Prior to 4.34.0, a project-defined free-form widget style field can carry an editor-controlled quote into an inline style attribute because the wrapper serializer does not apply HTML-attribute encoding. The quote can terminate the style attribute and inject executable attributes when published content, or an affected draft viewed by a higher-privileged user, is rendered. This issue is fixed in version 4.34.0.

Record
CVE-2026-112958
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
OSV 5.4

ApostropheCMS: Stored XSS via Unescaped Widget Style Attribute Serialization

ApostropheCMS is an open-source Node.js content management system. Prior to 4.34.0, a project-defined free-form widget style field can carry an editor-controlled quote into an inline style attribute because the wrapper serializer does not apply HTML-attribute encoding. The quote can terminate the style attribute and inject executable attributes when published content, or an affected draft viewed by a higher-privileged user, is rendered. This issue is fixed in version 4.34.0.

Record
CVE-2026-112958
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
OSVGHSA-7jg5-frgc-c67w 5.4

ApostropheCMS: Stored XSS via Unescaped Widget Style Attribute Serialization

Summary

ApostropheCMS widget styles support project-defined schema fields. If a project defines a free-form string style field with a CSS property and no selector, an editor-controlled value is rendered as an inline CSS declaration. The resulting declaration is then inserted into the widget wrapper's style="..." attribute without HTML-attribute escaping.

An attacker who can edit the widget can include a double quote in the style value, terminate the style attribute, and inject new HTML event-handler attributes. The payload is stored with the widget and executes in the Apostrophe site origin whenever the affected published page is rendered.

This is a sibling of CVE-2026-33889 / GHSA-97v6-998m-fp4g. The earlier issue escaped from a <style> element through a malicious color value. This variant reaches a different sink related to the automatically generated widget wrapper's inline style and class attributes.

Details

Root Cause 1: Free-form string style values retain HTML metacharacters

The standard string field converter uses launder.string() and length validation. This performs type normalization, not output encoding for an HTML attribute context:

packages/apostrophe/modules/@apostrophecms/schema/lib/addFieldTypes.js:296-333

self.addFieldType({
  name: 'string',
  // ...
  convert(req, field, data, destination) {
    destination[field.name] = self.apos.launder.string(data[field.name]);
    destination[field.name] = checkStringLength(
      destination[field.name],
      field.min,
      field.max
    );
  }
});

Quotes therefore remain in a value supplied through a style field.

Root Cause 2: The value is converted into inline CSS without value validation

For a field with property but no selector or media query, renderScopedStyles() selects inline rendering. The generic extractor concatenates the configured property and editor-controlled value:

packages/apostrophe/modules/@apostrophecms/styles/ui/apos/universal/render.mjs:171-228

packages/apostrophe/modules/@apostrophecms/styles/ui/apos/universal/render.mjs:598-647

rule = `${property}: ${normalized.value}${normalized.unit}`;

// ...

if (isInline) {
  return {
    css: '',
    classes: [ ...storage.classes ],
    inline: stringifyRules(storage.styles, true)
  };
}

For example, the value below becomes part of a font-family declaration:

serif" tabindex="0" autofocus onfocus="document.body.dataset.inline='executed'

Root Cause 3: Attribute values are serialized without HTML escaping

getWidgetAttributes() places the inline CSS into an attribute tuple, then concatenates every tuple into key="value" without encoding &, <, >, ', or ":

packages/apostrophe/modules/@apostrophecms/styles/lib/methods.js:251-322

if (styleParts.length) {
  attrs.push(
    [ 'style', `${styleParts.join(';')};` ]
  );
}

if (options.asObject) {
  return Object.fromEntries(attrs);
}

return attrs
  .map(([ key, value ]) => `${key}="${value}"`)
  .join(' ');

The same raw serializer also makes a project-defined free-form string style with class: true a potential sibling path, because the string is added to classes and later serialized into class="...". The…

Record
GHSA-7jg5-frgc-c67w
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
apostrophe
npm
before 4.34.0
4.34.0

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-112958 is a medium vulnerability (CVSS 5.4) in Apostrophecms Apostrophe, published October 20, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.30%, the 23rd percentile. Fixed in apostrophe 4.34.0.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open