最新のセキュリティ情報
10月22日(木)今日
Storybook: Missing origin validation in Storybook preview allows code injection from malicious websites
影響: npm:storybook >= 8.0.0, < 8.6.19 → 8.6.19, npm:storybook >= 9.0.0, < 9.1.21 → 9.1.21, npm:storybook >= 10.0.0, < 10.6.2 → 10.6.2, npm:storybook >= 11.0.0-alpha.0, < 11.0.0-alpha.6 → 11.0.0-alpha.6, npm:@storybook/core >= 8.0.0, < 8.6.19 → 8.6.19, npm:@storybook/core-server >= 8.0.0, < 8.6.19 → 8.6.19, npm:@storybook/experimental-addon-test >= 8.0.0, < 8.6.19 → 8.6.19, npm:@storybook/addon-vitest >= 9.0.0, < 9.1.21 → 9.1.21, npm:@storybook/addon-vitest >= 10.0.0, < 10.6.2 → 10.6.2, npm:@storybook/addon-vitest >= 11.0.0-alpha.0, < 11.0.0-alpha.6 → 11.0.0-alpha.6, npm:@storybook/addon-mcp >= 10.6.0, < 10.6.2 → 10.6.2, npm:@storybook/addon-mcp >= 11.0.0-alpha.0, < 11.0.0-alpha.6 → 11.0.0-alpha.6 Summary: A malicious website may be able to cause unauthorized file changes in a developer’s project while an affected Storybook development server is running. Under additional conditions, a changed file could be executed by a local runtime with the developer’s privileges. We are not aware of exploitation in the wild. Who is impacted? You are impacted if you run a Storybook dev server in the affected versions. You are not impacted if: - You run a dev server that you never open in a web browser…
Electron: HID and USB permission checks can be attributed to the wrong origin
影響: npm:electron >= 45.0.0-alpha.1, < 45.0.0-alpha.5 → 45.0.0-alpha.5, npm:electron >= 44.0.0-alpha.1, < 44.3.0 → 44.3.0, npm:electron >= 43.0.0-alpha.1, < 43.7.0 → 43.7.0, npm:electron < 42.11.3 → 42.11.3 Impact For hid and usb permission checks made from an iframe, session.setPermissionCheckHandler was given the top-level frame's origin and details instead of the requesting frame's. Apps that allow these permissions based on origin could grant an embedded frame access intended for the top-level page. You're only affected if you use setPermissionCheckHandler with origin-based logic for hid or usb and embed cross-origin iframes with allow="hid" or allow="usb". Apps that don't delegate those featu…
ApostropheCMS: POST /api/v1/@apostrophecms/doc/slugTaken discloses existence of private/admin-only content to any authenticated user
影響: npm:apostrophe < 4.34.0 → 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 permissio…
ApostropheCMS: GET /api/v1/@apostrophecms/page/:id bypasses viewRole restriction and exposes viewPermission-gated fields to lower-privileged users
影響: npm:apostrophe < 4.34.0 → 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 thread…
ApostropheCMS: Stored XSS via Unescaped Widget Style Attribute Serialization
影響: npm:apostrophe < 4.34.0 → 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-ha…
ApostropheCMS: Missing Authentication in `cleanExport` Route
影響: npm:@apostrophecms/import-export < 3.7.1 → 3.7.1 1. Summary The API endpoint POST /api/v1/@apostrophecms/import-export/clean-export in @apostrophecms/import-export lacks authentication and authorization checks. Any client—including unauthenticated anonymous users who have obtained the standard CSRF cookie from visiting the site—can directly invoke this route and trigger the underlying self.cleanExport(req) method. --- 2. Affected Files & Endpoints Endpoint: POST /api/v1/@apostrophecms/import-export/clean-export Route Definition: packages/impo…
ApostropheCMS: Unauthenticated publicApiProjection bypass via search and sort query builders in the public REST API
影響: npm:apostrophe < 4.34.0 → 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 ?sea…
ApostropheCMS: Color field validation bypass allows stored XSS via HTML appended after rgb()/hsl() prefix
影響: npm:apostrophe < 4.34.0 → 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…
ApostropheCMS sanitize-html: unbounded recursion when re-sanitizing the fallback of a discarded iframe (stack overflow, nestingLimit not enforced)
影響: npm:sanitize-html >= 2.18.0, < 2.18.1 → 2.18.1 Summary Since 2.18.0, when an is not allowed and disallowedTagsMode is 'discard' (the defaults), its raw-text content is re-sanitized by a recursive call to sanitizeHtml(text, options) (the change from #5564, fixing #5550). The recursion has no bound and starts each nested call with a fresh state. Two consequences, both absent from 2.17.7 and 2.17.4: 1. A few kilobytes of unclosed tags throw RangeError: Maximum call stack size exceeded with the default options. Any application that sanitizes un…
ApostropheCMS: Import API bypasses publication roles for protected content
影響: npm:@apostrophecms/import-export < 3.7.1 → 3.7.1, npm:apostrophe < 4.34.0 → 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 rep…
ApostropheCMS: Archive duplicate continuation lets contributors overwrite published content
影響: npm:@apostrophecms/import-export < 3.7.1 → 3.7.1 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 rep…
ApostropheCMS: Import archives can exhaust server storage and deny service
影響: npm:@apostrophecms/import-export < 3.7.1 → 3.7.1 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 rep…
Vite: Cross origin script execution through Vite custom middleware
影響: npm:vite >= 8.3.0, <= 8.3.2 → 8.3.3, npm:vite >= 8.2.0, <= 8.2.3 → 8.2.4, npm:vite >= 8.0.0, <= 8.1.5 → 8.1.6, npm:vite >= 7.0.0, <= 7.3.6 → 7.3.7, npm:vite <= 6.4.3 → 6.4.4, npm:vite-plus <= 1.0.0 → 1.1.0 Summary When accessing a malicious site while a dev server using Vite is running, that site was able to load scripts in a page served by the dev server. Impact Only apps that match the following conditions are affected: - the dev server passes an unchanged browser request URL to server.transformIndexHtml: this is normally used for server.middlewareMode: true or appType: 'custom'. The internal call for appType: 'spa' and appType: 'mpa' does not match this. - the transformed HTML contains an inli…
Vite: Files outside `server.fs.allow` could be served when project paths match system paths on non-Windows machine
影響: npm:vite >= 8.3.0, <= 8.3.2 → 8.3.3, npm:vite >= 8.2.0, <= 8.2.3 → 8.2.4, npm:vite >= 8.0.0, <= 8.1.5 → 8.1.6, npm:vite >= 7.0.0, <= 7.3.6 → 7.3.7, npm:vite <= 6.4.3 → 6.4.4, npm:vite-plus <= 1.0.0 → 1.1.0 Summary The content of files outside server.fs setting can be returned to the browser if the project imports a file path concatenated with the root. For example, if the project references /etc/hosts, the content of /etc/hosts was possible to be returned. The content of files outside the server.fs.allow option can be returned to the browser when a project imports a file whose root-relative path matches an absolute path on the host. For example, referencing /etc/hosts could make Vite return the h…
Vite: First 4 bytes of files outside of `server.fs` setting is exposed by `?vite-wasm-instance`
影響: npm:vite >= 8.3.0, <= 8.3.2 → 8.3.3, npm:vite >= 8.2.0, <= 8.2.3 → 8.2.4, npm:vite-plus >= 0.2.8, <= 1.0.0 → 1.1.0 Summary The first 4 bytes of files outside of server.fs setting can be returned to the browser by a request containing ?vite-wasm-instance. Impact Only apps that match one of the following conditions are affected: - explicitly expose the Vite dev server to the network using --host or the [server.host](https://vite.dev/config/server-options#server-host) option - there's a file that has a sensitive information in the first 4 bytes - uses Node.js or Deno to run Vite (if Bun is used, it is not affe…
10月21日(水)昨日
ApostropheCMS: Unauthenticated resource exhaustion via pre-auth aposBigUpload processing in @apostrophecms/import-export
影響: npm:apostrophe < 4.33.0 → 4.33.0, npm:@apostrophecms/import-export < 3.7.0 → 3.7.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…
Weekly Report: Next.jsに複数の脆弱性
Next.jsに複数の脆弱性
@angular/common: XSRF Token Leakage via URL Parsing Discrepancy in Angular HTTP Client (Incomplete fix for CVE-2025-66035)
影響: npm:@angular/common >= 21.0.0, < 21.0.3 → 21.0.3, npm:@angular/common >= 20.0.0, < 20.3.34 → 20.3.34, npm:@angular/common <= 19.2.25 An incomplete fix for [GHSA-58c5-g7wp-6w37](https://github.com/angular/angular/security/advisories/GHSA-58c5-g7wp-6w37) (CVE-2025-66035) in @angular/common's HTTP Client (HttpClient) allows Cross-Site Request Forgery (XSRF) tokens to be leaked to attacker-controlled cross-origin domains when requests use URLs that exploit parsing discrepancies between regular expressions and the browser's WHATWG URL parser. Technical Description To address CVE-2025-66035, xsrfInterceptorFn introduced a regular…
markdown-it: Quadratic-time rendering of a single multi-line link reference definition with default options (regression since 14.0)
影響: npm:markdown-it >= 14.1.0, < 14.3.3 → 14.3.3, npm:markdown-it >= 15.0.0, < 15.0.3 → 15.0.3 Summary A link reference definition whose label or title is never closed is O(n²) in markdown-it 15.0.2 with default options. Continuation lines are pulled lazily with str += lineContent in src/rules_block/reference.ts, and the subsequent charCodeAt and slice calls flatten the V8 cons-string, copying everything collected so far; this runs before the rule decides the definition is invalid. It is a regression introduced by PR #1004 in 14.0.0: 13.0.2 processed a 313 KB input in 125 ms, while every…
markdown-it: Quadratic-time denial of service in inline HTML parsing with html enabled
影響: npm:markdown-it < 14.3.3 → 14.3.3, npm:markdown-it >= 15.0.0, < 15.0.3 → 15.0.3 Summary With html: true, markdown-it takes quadratic time to parse repeated unterminated HTML constructs inside a paragraph. This affects HTML comments ( , ?>, >, and ]]>. When the terminator is absent, matching fails. Parsing eventually reaches the next opener and scans an overlapping suffix again. Repeating this across the paragraph produces quadratic total work. For these inputs, the problem is repeated scanning across separate matches. The payload must reach inline parsing. Prefixing it wit…
MCP TypeScript server SDK: Shared transport or server instances delivered one HTTP client's messages to another
影響: npm:@modelcontextprotocol/server >= 2.0.0, < 2.3.0 → 2.3.0 Summary In affected versions, an MCP server reached over HTTP could deliver one client's responses and notifications to another client. This happened when clients shared one stateless transport, or one McpServer or Server instance. Messages were matched to a connection by JSON-RPC id alone. SDK clients number requests from 0, so ids collide in normal use. Am I affected? Yes, if more than one client can reach your HTTP endpoint and your code creates the transport or the server once at startup, i…
MCP TypeScript SDK: One HTTP request within the default size limit could exhaust server memory during validation
影響: npm:@modelcontextprotocol/sdk >= 1.3.0, < 1.32.0 → 1.32.0, npm:@modelcontextprotocol/server >= 2.0.0, < 2.3.0 → 2.3.0 Summary In affected versions, servers put no limit on how many array elements and object keys they validated in one request. One HTTP request within the default 4 MiB size limit could exhaust the server's memory, and the process aborted with JavaScript heap out of memory. No credentials are needed, unless you authenticate requests before they reach the SDK. Am I affected? Yes, if clients you do not fully trust can reach your server over HTTP. The risk is highest for McpServer tools whose input…
launch-editor: Editor CLI flag misinterpretation causing arbitrary command execution for some editors
影響: npm:launch-editor <= 2.14.1 → 2.14.2, npm:vite >= 8.3.0, <= 8.3.2 → 8.3.3, npm:vite >= 8.2.0, <= 8.2.3 → 8.2.4, npm:vite >= 8.0.0, <= 8.1.5 → 8.1.6, npm:vite >= 7.0.0, <= 7.3.6 → 7.3.7, npm:vite <= 6.4.3 → 6.4.4, npm:vite-plus <= 1.0.0 → 1.1.0 Summary launch-editor forwarded file paths directly to editors without sanitization. If a path resembles a CLI flag, editors like Vim may interpret it as a command, potentially causing unintended file overwrites or command execution. Impact Direct launch-editor users Only apps that match all of the following conditions are affected: - The attacker is able to create a file system entry (e.g. a file or directory) starting with + or - in the working directory - The user uses or the app specifies a…
launch-editor: `fs.existsSync()` existence check can be bypassed on Windows
影響: npm:launch-editor <= 2.14.1 → 2.14.2, npm:vite >= 8.3.0, <= 8.3.2 → 8.3.3, npm:vite >= 8.2.0, <= 8.2.3 → 8.2.4, npm:vite >= 8.0.0, <= 8.1.5 → 8.1.6, npm:vite >= 7.0.0, <= 7.3.6 → 7.3.7, npm:vite <= 6.4.3 → 6.4.4, npm:vite-plus <= 1.0.0 → 1.1.0 Summary launch-editor checked fs.existsSync(fileName) before passing a supplied path to an editor command. On Windows, an attacker can bypass this check with a crafted path ending in \\..:line:column. This removes the requirement that the attacker be able to place a file with a malicious filename. Combined with the % escaping issue described in [GHSA-698v-4r3x-3vcv](https://github.com/vitejs/launch-editor/security/advisories/GHSA-698v-4r3x-3vcv), this bypass can lead to OS command injection whe…
MCP TypeScript SDK: Server bearer authentication accepted tokens issued for another service
影響: npm:@modelcontextprotocol/sdk >= 1.6.0, < 1.32.0 → 1.32.0, npm:@modelcontextprotocol/server >= 2.0.0, < 2.3.0 → 2.3.0, npm:@modelcontextprotocol/express >= 2.0.0, < 2.0.2 → 2.0.2, npm:@modelcontextprotocol/server-legacy >= 2.0.0, < 2.3.1 → 2.3.1 Summary In affected versions, the SDK's server-side bearer authentication had no way to check that a token was issued for your server (its audience). Where one authorization server issues tokens for several services, a valid token for another service was also accepted by your MCP server. Am I affected? Yes, if your HTTP server uses requireBearerAuth() or verifyBearerToken(), its authorization server also issues tokens for other services, and your verifyAccessToken() does not check the token's a…
launch-editor: escapeCmdArgs() omits % escaping on Windows
影響: npm:launch-editor <= 2.14.1 → 2.14.2, npm:vite >= 8.3.0, <= 8.3.2 → 8.3.3, npm:vite >= 8.2.0, <= 8.2.3 → 8.2.4, npm:vite >= 8.0.0, <= 8.1.5 → 8.1.6, npm:vite >= 7.0.0, <= 7.3.6 → 7.3.7, npm:vite <= 6.4.3 → 6.4.4, npm:vite-plus <= 1.0.0 → 1.1.0 Summary launch-editor did not escape % on Windows when passing an argument to cmd. When an environment variable contained a malicious value, it was possible that that content to be executed. Impact Only apps that match all of the following conditions are affected: - The user uses Windows - An attacker can place a file with the malicious filename containing & or % - Either of - An attacker can inject an environment variable with a malicious value - An attacker can add a NTFS alternate data strea…
MCP TypeScript SDK: Experimental tasks were not tied to the session that created them
影響: npm:@modelcontextprotocol/sdk >= 1.24.0, < 1.32.0 → 1.32.0 Summary In affected versions, the experimental tasks feature (taskStore) did not check which session created a task. Clients sharing one InMemoryTaskStore could list, read and cancel each other's tasks. Experimental tasks are deprecated. The 2026-07-28 specification replaced them with a redesigned extension. The best course of action is to stop using them. Am I affected? Only if your HTTP server passes taskStore to McpServer or Server. If grep -ri taskstore --exclude-dir=node_modules . finds no…
MCP TypeScript client SDK: HTTP client transports and OAuth requests followed cross-origin redirects and re-sent custom headers and request bodies
影響: npm:@modelcontextprotocol/sdk < 1.32.0 → 1.32.0, npm:@modelcontextprotocol/client >= 2.0.0, < 2.3.0 → 2.3.0 Summary In affected versions, the SDK's HTTP client transports and OAuth requests followed redirects to any origin. If an MCP server or authorization server redirected a request to another origin, that origin received custom request headers (such as an X-API-Key set in requestInit.headers) and the mcp-session-id header. On a 307 or 308 it also received the request body, including OAuth token requests with their refresh_token and client_secret. On current runtimes fetch already drops the Authori…
ApostropheCMS: The general public can access @apostrophecms/user objects via a relationship (viewRole is not applied to the general public)
影響: npm:apostrophe < 4.33.0 → 4.33.0 Impact Even though it is correctly applied to guests, contributors, etc., viewRole is not applied to the general public. This means that a secured content type like @apostrophecms/user can in theory be accessed. This is greatly mitigated by the fact that there is no automatic public REST API for any content type. One has to expressly allow it. However, it does mean that developers can make the mistake of setting up a relationship between a content type like a blog post, and @apostrophecms/user.…
ApostropheCMS: Missing Authorization on Notification PATCH/DELETE Endpoints
影響: npm:apostrophe < 4.33.0 → 4.33.0 Summary The notification module exposes PATCH and DELETE REST endpoints that perform operations directly on the underlying MongoDB collection without verifying that the requester is authenticated or owns the target notification. As a result, an unauthenticated attacker who obtains a valid notification ID can modify or permanently delete another user's notification. --- Affected Code File text packages/apostrophe/modules/@apostrophecms/notification/index.js javascript // restApiRoutes async patc…
ApostropheCMS import-export tar guard misses './..' because it is a literal '../' substring test
影響: npm:@apostrophecms/import-export < 3.7.0 → 3.7.0 Summary The tar-extraction guard added to @apostrophecms/import-export for GHSA-mwxc-m426-3f78 is a literal substring test for ../, and ./.. does not contain that substring. An entry named ./.. therefore passes the guard, path.join normalizes it to the parent of the export directory, and the resulting fs.WriteStream opens a directory and emits EISDIR with no error listener attached, which terminates the Node process. Confirmed on default-branch HEAD 1bd5d0a7a6fe880836fa75adad6964f1c577d640, pac…
ApostropheCMS: Path traversal in uploadfs
影響: npm:uploadfs < 1.28.0 → 1.28.0 Summary The uploadfs library's local storage backend does not validate or sanitize user-supplied paths. The prefixPath() helper only strips double slashes (//) and the backend performs direct string concatenation (uploadsPath + path). An attacker can inject ../ sequences to escape the intended uploads directory, resulting in arbitrary file read, write, and delete on the host filesystem. --- Details Root Cause packages/uploadfs/uploadfs.js:652-655 https://github.com/apostrophecms/apostrophe/blob…
ApostropheCMS sanitize-html: SMIL animation namespace-prefix bypass allows javascript: URI injection (XSS)
影響: npm:sanitize-html >= 2.17.7, < 2.18.0 → 2.18.0 Summary sanitize-html 2.17.7 introduced animatesUrlAttribute() to block SVG animation elements (animate, animateColor, animateMotion, animateTransform, set) when their attributeName targets a URL sink like href. However, this check is bypassed when the animation element uses a namespace prefix (e.g., svg:animate instead of animate). Root Cause The animatesUrlAttribute function (index.js, line ~832) checks svgAnimationTags.indexOf(name.toLowerCase()), where svgAnimationTags contains bare local n…
ApostropheCMS uploadfs Azure backend leaks account-level SAS token into every public attachment URL (sas: true)
影響: npm:uploadfs >= 1.25.0, < 1.28.0 → 1.28.0 Summary When uploadfs is configured with the Azure backend and sas: true (a supported configuration introduced in uploadfs 1.25.0), createContainer() builds the BlobServiceClient from a URL that embeds the full SAS query string, and Azure SDK v12 derived clients inherit that query string. As a result, getUrl() returns a base URL carrying the complete account/container SAS signature (?sv=...&sig=...), and Apostrophe's attachment.url() prepends it to every public attachment link — broadcasting a…
ApostropheCMS: Authenticated Object-Level Authorization Bypass in exist-in-locale Reveals Restricted Localized Draft Identifiers
影響: npm:apostrophe < 4.33.0 → 4.33.0 Summary ApostropheCMS’s exist-in-locale API allows an authenticated low-privilege user to determine whether restricted documents exist in a specified locale and mode, including draft mode. The endpoint returns localized document identifiers without applying document-level view or edit authorization criteria. The issue was reproduced against a real local ApostropheCMS application running the reviewed source code. The test used a synthetic guest account and synthetic restricted draft records. Det…
ApostropheCMS import-export: NoSQL injection via update-key value lets a crafted import match and overwrite an unidentified document
影響: npm:@apostrophecms/import-export < 3.7.0 → 3.7.0 Summary @apostrophecms/import-export's update-by-key feature lets an imported document carry a :key property (for example slug:key) whose value is used to find an existing document to update instead of inserting a new one. getUpdateKey()/insertOrUpdateDocWithKey() (lib/methods/import.js) use that value directly as a MongoDB query value with no laundering: js const matchingDraftPromise = manager.findForEditing( req.clone({ mode: 'draft' }), { aposMode: 'draft', [updateField]: doc[updateKey] }).t…
ApostropheCMS: Client-side Prototype Pollution in apos.http.parseQuery leading to DOM-based XSS against authenticated users
影響: npm:apostrophe < 4.33.0 → 4.33.0 Summary The client-side helper apos.http.parseQuery() in ApostropheCMS builds a nested object from a URL query string without sanitizing the keys __proto__, constructor, or prototype. Parsing an attacker-controlled query string therefore writes arbitrary properties onto Object.prototype (client-side prototype pollution). ApostropheCMS's admin UI calls this parser with window.location.search on every authenticated page load (the admin context bar's data() initializer). Because the admin UI is bu…
ApostropheCMS: No Attempt Throttling on Authenticated Password-Change Endpoint Enables Unlimited Current-Password Guessing
影響: npm:apostrophe < 4.33.0 → 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 ro…
ApostropheCMS: Incomplete CVE-2026-53606: `meta http-equiv=refresh` `content` still ships `javascript:` / `data:` URLs
影響: npm:sanitize-html < 2.18.0 → 2.18.0 Summary CVE-2026-53606 expanded allowedSchemesAppliedToAttributes so named URL attributes (action, formaction, data, poster, background, later ping, xlink:href, …) go through naughtyHref(). A URL nested inside meta content (http-equiv=refresh) is not an attribute name on that list, so the embedded destination is never scheme-checked. Default allowedTags still omit meta. Same non-default integrator config as 53606: allow meta plus http-equiv / content. On 2.17.7: text sanitizeHtml( ' ', { allowe…
ApostropheCMS: :_id/locales REST route omits the public-API authorization gate its sibling read routes enforce (unauthenticated doc-existence + locale metadata disclosure)
影響: npm:apostrophe < 4.33.0 → 4.33.0 Summary The REST route GET /api/v1/ /:_id/locales (and the equivalent page route) does not apply the publicApiCheckAsync gate that ApostropheCMS's other read routes enforce. An unauthenticated caller can therefore query this route for any document _id and learn whether the document exists and which locales it is published in — a document-existence and locale-metadata disclosure that the read-API is otherwise supposed to gate. Affected - Repository: apostrophecms/apostrophe (monorepo package apo…
ApostropheCMS: Page REST API authorization bypass
影響: npm:apostrophe < 4.33.0 → 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(c…
ApostropheCMS: Host header controls server-side image fetch origin in @apostrophecms/ai-helper, enabling authenticated SSRF
影響: npm:@apostrophecms/ai-helper >= 1.0.0-beta.10, < 1.0.0-beta.13 → 1.0.0-beta.13 Summary The @apostrophecms/ai-helper package builds the URL for a server-side image fetch by resolving a storage-relative path against req.baseUrl. When the site does not set a global base URL (the default), req.baseUrl is derived from the incoming HTTP Host header. An authenticated editor can generate a base64 AI image (which is persisted without a stored url) and then send an unauthorized PATCH accept request with an attacker-chosen Host header. The server then issues an outbound GET to the a…
ApostropheCMS: Unauthenticated CSV import requests leave rejected uploads in the system temporary directory
影響: npm:apostrophe < 4.33.0 → 4.33.0 Summary A rejected upload can remain in the operating system temporary directory. Multer writes the file before its extension is checked, and the rejection path does not remove that temporary file. An unauthenticated requester can repeat this with large files and steadily consume temporary disk space. Details The endpoint is: text POST /api/v1/@apostrophecms/rich-text-widget/generate-csv-table In packages/apostrophe/modules/@apostrophecms/rich-text-widget/lib/apiRoutes.js, Multer first writes t…
ApostropheCMS: Cross-domain session token in URL confers session takeover
影響: npm:apostrophe < 4.33.0 → 4.33.0, npm:@apostrophecms/passport-bridge < 1.6.1 → 1.6.1 Summary Apostrophe's cross-domain session migration emits a single-use session token as a URL query parameter and stores it in the Mongo cache. Any client that presents the token silently adopts the target user's full session (including passport.user) with no credentials. Details packages/apostrophe/modules/@apostrophecms/i18n/index.js: - Token generation on cross-host/locale flows (L479–487) and passport-bridge cross-locale redirect (passport-bridge/index.js L557–593) places the token in the U…
ApostropheCMS: Unauthenticated unbounded multipart upload → disk-exhaustion DoS
影響: npm:@apostrophecms/form < 1.5.5 → 1.5.5 Summary The form submission endpoint runs multer({ dest: os.tmpdir() }).any() before authentication, API-key, CSRF-equivalent, or form-existence logic, with no size/count/rate limits. Unauthenticated users can stream unbounded bodies to disk per request; cleanup occurs only after the full body is received. Details packages/form/index.js apiRoutes.post.submit (L274–296): [ multer({ dest: os.tmpdir() }).any(), self.normalizeFiles, async function (req) { try { submitForm } finally { unlink files }…
ApostropheCMS: CAPTCHA response token not URL-encoded
影響: npm:@apostrophecms/form < 1.5.5 → 1.5.5, npm:@apostrophecms/login-recaptcha < 1.2.1 → 1.2.1, npm:@apostrophecms/login-hcaptcha < 1.3.0 → 1.3.0 Summary Form and login CAPTCHA verification interpolate the user-supplied widget token unencoded into the server-side verification URL/body, allowing a crafted token to inject query parameters into the reCAPTCHA/hCaptcha verify request. Details - packages/form/lib/recaptcha.js:39 — recaptchaUri = 'https://www.google.com/recaptcha/api/siteverify?secret=${recaptchaSecret}&response=${input.recaptcha}' - packages/login-recaptcha/index.js:44 — same pattern for login - packages/login-hcaptcha/index.j…
ApostropheCMS: Same-parent page reorder in @apostrophecms/page move() re-ranks a restricted parent's children without create authorization
影響: npm:apostrophe < 4.33.0 → 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 authoriza…
ApostropheCMS: Authenticated projection-exclusion prototype-member deletion in @apostrophecms/db-connect causes process-wide denial of service
影響: npm:@apostrophecms/db-connect < 1.1.0 → 1.1.0, npm:apostrophe < 4.33.0 → 4.33.0 Summary @apostrophecms/db-connect ships an in-memory MongoDB emulation used by its SQLite, PostgreSQL, and multipostgres adapters. Its unsetNestedField helper walks an attacker-controlled dotted field path with no segment validation and calls delete on the resolved property. A low-privileged authenticated user (any role holding view-draft, which every editor and contributor has; reduced to any logged-in user when guestApiAccess is enabled) can send a piece-type REST GET request whose project qu…
ApostropheCMS sanitize-html: nonTextTags discard region ends early on an implied close, letting <noscript> content render
影響: npm:sanitize-html < 2.18.0 → 2.18.0 Summary sanitize-html discards the content of every element in nonTextTags. It delimits that region using htmlparser2's close events, and ignores the isImplied flag htmlparser2 passes it. Closing a still-open ancestor from inside a makes htmlparser2 unwind its stack past the noscript; the synthetic implied close it emits on the way ends the discard region early, and everything after it is treated as ordinary body content. A browser with scripting enabled parses content as raw text, so the same…
follow-redirects array-form headers bypass cross-origin credential stripping
影響: npm:follow-redirects >= 1.16.0, < 1.16.1 → 1.16.1 Summary follow-redirects removes sensitive credential headers (Authorization, Proxy-Authorization, Cookie, and any caller-declared sensitiveHeaders) before following a redirect that crosses to a different host or downgrades to a less secure protocol. The removal routine iterates the caller's headers container with for...in and matches header names against a filter. This assumes the headers container is a plain object keyed by header names. Node's underlying http.request, which follow-redirects…