apostrophe

Ecosystem: npm

Downloads: 84.41 K

Vulnerabilities from the last (months)
  • 2CriticalAffects 2 versions
  • 8HighAffects 8 versions
  • 0MediumAffects 0 versions
  • 20ModerateAffects 20 versions
  • 4LowAffects 4 versions
Severity distribution (all time)
34vulnerabilities
  • Critical2 (5.9%)
  • High8 (23.5%)
  • Medium0 (0.0%)
  • Moderate20 (58.8%)
  • Low4 (11.8%)

Monthly breakdown

  • Critical
  • High
  • Medium
  • Moderate
  • Low
  • 18 vulnerabilities
    • Critical: 0
    • High: 3
    • Medium: 0
    • Moderate: 14
    • Low: 1
  • 2 vulnerabilities
    • Critical: 0
    • High: 1
    • Medium: 0
    • Moderate: 1
    • Low: 0
  • 2 vulnerabilities
    • Critical: 1
    • High: 0
    • Medium: 0
    • Moderate: 0
    • Low: 1
  • 2 vulnerabilities
    • Critical: 0
    • High: 2
    • Medium: 0
    • Moderate: 0
    • Low: 0
  • 5 vulnerabilities
    • Critical: 0
    • High: 1
    • Medium: 0
    • Moderate: 3
    • Low: 1
  • 1 vulnerabilities
    • Critical: 0
    • High: 1
    • Medium: 0
    • Moderate: 0
    • Low: 0
  • 2 vulnerabilities
    • Critical: 1
    • High: 0
    • Medium: 0
    • Moderate: 1
    • Low: 0
  • 2 vulnerabilities
    • Critical: 0
    • High: 0
    • Medium: 0
    • Moderate: 1
    • Low: 1

Vulnerabilities (34)

Known vulnerabilities affecting apostrophe, based on data from OSV.

Vulnerabilities affecting apostrophe
IDSeveritySummaryAffected versionsPublishedSource
GHSA-5m22-7pfq-vp65ModerateApostropheCMS: Import API bypasses publication roles for protected content## Review scope and evidence limits Package: @apostrophecms/import-export, version 3.7.0. Release tag reviewed: @apostrophecms/import-export@3.7.0, commit 9500b8b0e1d630d5e07fbb5fd2c25ed0943845ce (September 30, 2026). Current main reviewed: 5ce3732be0ebdebb4db0f8ef160c81e8671157e6. The importer, gzip extractor, import permission gate, and core permission implementation have no differences between that release tag and the reviewed main. This follow-up is a static remediation review. We have not repeated the original end-to-end reproductions against the latest release or tested a deployed si
  • < 4.34.0
GitHub (opens in a new tab)
GHSA-7jg5-frgc-c67wModerateApostropheCMS: 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 s
  • < 4.34.0
GitHub (opens in a new tab)
GHSA-86wm-68pq-5jwqHighApostropheCMS: Unauthenticated resource exhaustion via pre-auth aposBigUpload processing in @apostrophecms/import-export## Summary A potential unauthenticated denial-of-service vulnerability exists in the chunked import upload path used by `@apostrophecms/import-export`. The affected import API routes invoke: `self.apos.http.bigUploadMiddleware()` before the actual import handler performs its authentication check. Because no `authorize` callback is supplied to `bigUploadMiddleware()`, unauthenticated requests can reach the `aposBigUpload` `start`, `chunk`, and `end` operations before the later `req.user` check rejects the import. As a result, an unauthenticated remote attacker can create server-side uploa
  • < 4.33.0
GitHub (opens in a new tab)
GHSA-f66c-mpj2-3r8hModerateApostropheCMS: POST /api/v1/@apostrophecms/doc/slugTaken discloses existence of private/admin-only content to any authenticated user### Summary The `slugTaken` endpoint returns a boolean indicating whether a slug is in use across all document types and visibility levels, with no permission or type filter. Any logged-in user (including editors) can enumerate the slug space of private pages, drafts, and archived content. ### Details `POST /api/v1/@apostrophecms/doc/slugTaken` with body `{ "slug": "target-slug" }` runs a raw existence check against the documents collection. It does not: - Check whether the requesting user has read permission for documents of that type. - Filter by `visibility` (public, loginRequired, private
  • < 4.34.0
GitHub (opens in a new tab)
GHSA-rqgm-cfrp-4hx8ModerateApostropheCMS: Unauthenticated publicApiProjection bypass via search and sort query builders in the public REST API### Summary ApostropheCMS lets a module expose an anonymous read API by setting `publicApiProjection`, which whitelists the document fields unauthenticated callers may see. The public REST GET handler applies every launderable query builder from the query string *before* forcing that projection. Two of those builders, `search` and `sort`, operate on the underlying documents rather than the projected output, and neither is checked against the projection. An unauthenticated attacker can therefore: - use `?search=<word>` as a **value oracle** to confirm and locate documents by the content of a f
  • < 4.34.0
GitHub (opens in a new tab)
GHSA-vh56-5m88-39rqModerateApostropheCMS: GET /api/v1/@apostrophecms/page/:id bypasses viewRole restriction and exposes viewPermission-gated fields to lower-privileged users### Summary The `getOne` REST endpoint for pages does not apply `viewRole` type-level restrictions or `viewPermission` field-level redaction. An editor-level user who knows a document `_id` can read the full content of admin-only pages and their privileged fields, while the `getAll` endpoint correctly enforces both restrictions. ### Details **Finding 3 — viewRole bypass:** `modules/@apostrophecms/page/index.js` exposes `getRestQuery(req, omitPermissionCheck = false)`. The `getAll` path calls `publicApiCheckAsync` and threads the full query builder pipeline including `viewRole` filtering. The
  • < 4.34.0
GitHub (opens in a new tab)
GHSA-vmgj-9cwm-cf3hModerateApostropheCMS: Color field validation bypass allows stored XSS via HTML appended after rgb()/hsl() prefix### Summary The color field accepts any string that *begins* with a valid `rgb()` / `hsl()` color, because `TinyColor.isValid` does not anchor its match at the end of the string. An authenticated user with edit rights can store arbitrary HTML after a valid color prefix. When the stored value is rendered , the payload executes, resulting in stored XSS. ### Details Server-side validation of the color field relies on TinyColor: ```js const { TinyColor } = require('@ctrl/tinycolor'); if (!new TinyColor(value).isValid) throw self.apos.error('invalid'); ``` TinyColor's `rgb`/`hsl` matchers are no
  • < 4.34.0
GitHub (opens in a new tab)
GHSA-2j32-q6rx-h844ModerateApostropheCMS: Page REST API authorization bypass**Summary** The core page REST API reads full page documents with `.permission(false)` in `getOne` and in the `all=1` tree dump, bypassing page-type `viewRole`, `visibility: private`, and `visibility: loginRequired` checks. Unauthenticated visitors and low-privilege contributors can read admin-only and non-public page content by `_id`/slug. **Details** `packages/apostrophe/modules/@apostrophecms/page/index.js`: - `getOne` (L456–465): `await self.publicApiCheckAsync(req); ... self.getRestQuery(req).permission(false).and(criteria)` — no `viewRole` threshold, no `visibility` filtering. - `all` h
  • < 4.33.0
GitHub (opens in a new tab)
GHSA-2jrp-qc93-h2j8ModerateApostropheCMS: Same-parent page reorder in @apostrophecms/page move() re-ranks a restricted parent's children without create authorization## Summary ApostropheCMS enforces per-type authorization on pages: a page type may declare `editRole` / `publishRole` (the core `@apostrophecms/archive-page` does), so a project can define restricted subtrees that only higher-privileged roles may create or edit within. The `move()` operation in the `@apostrophecms/page` module is supposed to enforce that a page may only be moved into a parent the actor has `create` rights over, the same boundary the page-insert route enforces. The destination-parent authorization check in `move()` is gated on the move being a cross-parent move (`oldParent._id
  • < 4.33.0
GitHub (opens in a new tab)
GHSA-653j-g8j7-gh54ModerateApostropheCMS: No Attempt Throttling on Authenticated Password-Change Endpoint Enables Unlimited Current-Password Guessing**Summary** The self-service password-change endpoint verifies the current password but does not use the login module’s failed-attempt counter, throttle, delay, or lockout mechanism. An attacker with a valid authenticated session can submit repeated guesses for the current password without receiving a lockout or throttle response. **Exact source path** packages/apostrophe/modules/@apostrophecms/settings/index.js:621-664 **The password-change route is:** PATCH /api/v1/@apostrophecms/settings/password **The route calls the password verifier directly through:** await self.handleProtectedSubfor
  • < 4.33.0
GitHub (opens in a new tab)
  • GHSA-5m22-7pfq-vp65Moderate
    ApostropheCMS: Import API bypasses publication roles for protected content
    • < 4.34.0

    ## Review scope and evidence limits Package: @apostrophecms/import-export, version 3.7.0. Release tag reviewed: @apostrophecms/import-export@3.7.0, commit 9500b8b0e1d630d5e07fbb5fd2c25ed0943845ce (September 30, 2026). Current main reviewed: 5ce3732be0ebdebb4db0f8ef160c81e8671157e6. The importer, gzip extractor, import permission gate, and core permission implementation have no differences between that release tag and the reviewed main. This follow-up is a static remediation review. We have not repeated the original end-to-end reproductions against the latest release or tested a deployed si

    CVE: CVE-2026-113649

  • GHSA-7jg5-frgc-c67wModerate
    ApostropheCMS: Stored XSS via Unescaped Widget Style Attribute Serialization
    • < 4.34.0

    ## 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 s

    CVE: CVE-2026-112958

  • GHSA-86wm-68pq-5jwqHigh
    ApostropheCMS: Unauthenticated resource exhaustion via pre-auth aposBigUpload processing in @apostrophecms/import-export
    • < 4.33.0

    ## Summary A potential unauthenticated denial-of-service vulnerability exists in the chunked import upload path used by `@apostrophecms/import-export`. The affected import API routes invoke: `self.apos.http.bigUploadMiddleware()` before the actual import handler performs its authentication check. Because no `authorize` callback is supplied to `bigUploadMiddleware()`, unauthenticated requests can reach the `aposBigUpload` `start`, `chunk`, and `end` operations before the later `req.user` check rejects the import. As a result, an unauthenticated remote attacker can create server-side uploa

    CVE: CVE-2026-113711

  • GHSA-f66c-mpj2-3r8hModerate
    ApostropheCMS: POST /api/v1/@apostrophecms/doc/slugTaken discloses existence of private/admin-only content to any authenticated user
    • < 4.34.0

    ### Summary The `slugTaken` endpoint returns a boolean indicating whether a slug is in use across all document types and visibility levels, with no permission or type filter. Any logged-in user (including editors) can enumerate the slug space of private pages, drafts, and archived content. ### Details `POST /api/v1/@apostrophecms/doc/slugTaken` with body `{ "slug": "target-slug" }` runs a raw existence check against the documents collection. It does not: - Check whether the requesting user has read permission for documents of that type. - Filter by `visibility` (public, loginRequired, private

    CVE: CVE-2026-112952

  • GHSA-rqgm-cfrp-4hx8Moderate
    ApostropheCMS: Unauthenticated publicApiProjection bypass via search and sort query builders in the public REST API
    • < 4.34.0

    ### Summary ApostropheCMS lets a module expose an anonymous read API by setting `publicApiProjection`, which whitelists the document fields unauthenticated callers may see. The public REST GET handler applies every launderable query builder from the query string *before* forcing that projection. Two of those builders, `search` and `sort`, operate on the underlying documents rather than the projected output, and neither is checked against the projection. An unauthenticated attacker can therefore: - use `?search=<word>` as a **value oracle** to confirm and locate documents by the content of a f

    CVE: CVE-2026-112954

  • GHSA-vh56-5m88-39rqModerate
    ApostropheCMS: GET /api/v1/@apostrophecms/page/:id bypasses viewRole restriction and exposes viewPermission-gated fields to lower-privileged users
    • < 4.34.0

    ### Summary The `getOne` REST endpoint for pages does not apply `viewRole` type-level restrictions or `viewPermission` field-level redaction. An editor-level user who knows a document `_id` can read the full content of admin-only pages and their privileged fields, while the `getAll` endpoint correctly enforces both restrictions. ### Details **Finding 3 — viewRole bypass:** `modules/@apostrophecms/page/index.js` exposes `getRestQuery(req, omitPermissionCheck = false)`. The `getAll` path calls `publicApiCheckAsync` and threads the full query builder pipeline including `viewRole` filtering. The

    CVE: CVE-2026-112957

  • GHSA-vmgj-9cwm-cf3hModerate
    ApostropheCMS: Color field validation bypass allows stored XSS via HTML appended after rgb()/hsl() prefix
    • < 4.34.0

    ### Summary The color field accepts any string that *begins* with a valid `rgb()` / `hsl()` color, because `TinyColor.isValid` does not anchor its match at the end of the string. An authenticated user with edit rights can store arbitrary HTML after a valid color prefix. When the stored value is rendered , the payload executes, resulting in stored XSS. ### Details Server-side validation of the color field relies on TinyColor: ```js const { TinyColor } = require('@ctrl/tinycolor'); if (!new TinyColor(value).isValid) throw self.apos.error('invalid'); ``` TinyColor's `rgb`/`hsl` matchers are no

    CVE: CVE-2026-112951

  • GHSA-2j32-q6rx-h844Moderate
    ApostropheCMS: Page REST API authorization bypass
    • < 4.33.0

    **Summary** The core page REST API reads full page documents with `.permission(false)` in `getOne` and in the `all=1` tree dump, bypassing page-type `viewRole`, `visibility: private`, and `visibility: loginRequired` checks. Unauthenticated visitors and low-privilege contributors can read admin-only and non-public page content by `_id`/slug. **Details** `packages/apostrophe/modules/@apostrophecms/page/index.js`: - `getOne` (L456–465): `await self.publicApiCheckAsync(req); ... self.getRestQuery(req).permission(false).and(criteria)` — no `viewRole` threshold, no `visibility` filtering. - `all` h

    CVE: CVE-2026-110904

  • GHSA-2jrp-qc93-h2j8Moderate
    ApostropheCMS: Same-parent page reorder in @apostrophecms/page move() re-ranks a restricted parent's children without create authorization
    • < 4.33.0

    ## Summary ApostropheCMS enforces per-type authorization on pages: a page type may declare `editRole` / `publishRole` (the core `@apostrophecms/archive-page` does), so a project can define restricted subtrees that only higher-privileged roles may create or edit within. The `move()` operation in the `@apostrophecms/page` module is supposed to enforce that a page may only be moved into a parent the actor has `create` rights over, the same boundary the page-insert route enforces. The destination-parent authorization check in `move()` is gated on the move being a cross-parent move (`oldParent._id

    CVE: CVE-2026-113655

  • GHSA-653j-g8j7-gh54Moderate
    ApostropheCMS: No Attempt Throttling on Authenticated Password-Change Endpoint Enables Unlimited Current-Password Guessing
    • < 4.33.0

    **Summary** The self-service password-change endpoint verifies the current password but does not use the login module’s failed-attempt counter, throttle, delay, or lockout mechanism. An attacker with a valid authenticated session can submit repeated guesses for the current password without receiving a lockout or throttle response. **Exact source path** packages/apostrophe/modules/@apostrophecms/settings/index.js:621-664 **The password-change route is:** PATCH /api/v1/@apostrophecms/settings/password **The route calls the password verifier directly through:** await self.handleProtectedSubfor

    CVE: CVE-2026-113710

Showing 1-10 of 34 vulnerabilities