Repository navigation
Apostrophe 4.34.1: Security Fixes and Safer Content Operations #5742
BoDonkey
announced in
Release Notes
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Hello Apostrophe Community!
Apostrophe 4.34.1 is a maintenance release with an important round of security fixes, including one critical and one high severity issue, so we strongly recommend all users upgrade as soon as possible. It also protects your content in a few situations where it could be damaged or lost, and fixes scheduled tasks on the Assembly dashboard.
Security
This release fixes 17 security vulnerabilities in core, Import/Export, Form, AI Helper, the Astro integration and
sanitize-html. Most were responsibly disclosed by outside researchers, and we thank them for their help. The fixes cover:sanitize-htmlbypasses in non-default configurationsFull details and reporter credits are in the changelog below and in the published GitHub security advisories.
A few of these fixes change behavior you may be relying on. If any of these apply to your project, see the changelog for details:
viewRolenow also governs editing a type's documents.allowedOriginssetting of thecsrfoption. Astro projects should update@apostrophecms/apostrophe-astroto 1.18.1 along with core.viewPermissionfields are no longer indexed for search. Affected sites should runnode app @apostrophecms/search:indexafter upgrading.Protecting Your Content
aposAttachmentscollection.Assembly Fixes
For Assembly, our multitenant platform for delivering sites to your own customers, scheduled dashboard tasks now run as expected. Note that
--frequencymust now behourlyordaily. In the Section Template Library, inserting the same section more than once no longer gives the inserted widgets the same ids.Additional Improvements
edit: falsenow locks nested areas too, version history no longer lists "changes" between empty values, and the CSRF cookie lasts a year as intended instead of about nine hours.arrayName,objectNameorapos.schema.getArrayManager. Several other fixes improve module options, middleware ordering, template imports and startup error messages.Thanks to our community contributors for their reports and fixes this month. You'll find them credited in the changelog below.
How to Update
This release contains important security fixes, including a critical one — we encourage all users to upgrade promptly with
npm update. Let us know what you think on our roadmap.The “stable” option
Everything above reflects our standard “latest” releases. Customers also have the option of following our “stable” release channel. The difference is simple: stable releases receive new features one full quarter later, but receive bug fixes and security fixes at the same time as “latest.” For this to be an effective way to increase stability, customers still need to actively evaluate “latest” so that they have a meaningful head start on what is coming in “stable.” Customers interested in following this path should reach out for complete information on how to point their dependencies to “stable.”
Everything we ship as “latest” is 100% ready for production. The “stable” series is an option for those with a large investment in training, automated testing, etc. It allows delayed implementation of new features without falling behind on fixes.
🚀 Happy coding!
Apostrophe 4.34.1
Fixes
checkboxesfield withhideLabeland more than one choice now hides only its own label, not the labels of its choices.maxis already reached, replacing the most recent selection instead of being ignored. Thanks to Vlad Bisceanu for reporting the issue.package.json, are thrown as real errors, so the log shows their message and stack instead ofstartup-errorwith nothing more.@references in a patch no longer resolve into loaded relationships.self.options.nested.valueno longer changes the options of its base class and sibling subclasses. Functions and class instances in options are still shared by reference.beforeoptions on middleware and routes now resolve transitively. If module A's middleware asks to run before module B, and B's middleware asks to run before module C, A's middleware now runs first; previously it ran last.@namespace/name, such asnested/stuff, now produces a clear startup warning recommending thenestedModuleSubdirs: trueoption. These modules still load as before. The misleading "unused module" warning about the parent folder (modules/nested) no longer appears.{% render %}or{% component %}tag at the top level of a template brought in with{% import %}no longer crashes the page with "Cannot read properties of undefined (reading 'data')". Nunjucks discards that output anyway, so the tag is skipped and a one-time warning explains how to fix the template.<image xlink:href="data:image/png;base64,...">, as exported by many design tools. Previously the SVG sanitizer removed these elements, so parts of the image disappeared. Embedded SVG documents and external references are still removed.rangefield without a default saved with no value is now unset, as in the editor, instead of .edit: falseon an area now also applies to the areas nested inside its widgets, at any depth. Previously a nested area became editable in context on its own.aposAttachments) now fails with aninvaliderror naming the attachment, instead of silently erasing the reference. Also fixes a missingreturnafter the no-_idbranch in the attachment field type'sconvert(). Fixes #4713. Thanks to Gary Bailey for the contribution.maxAgewas given in seconds, but Express expects milliseconds, so the cookie expired after about nine hours._idof their own field as_arrayFieldIdor_objectFieldId, so each is matched to its own schema. Like other properties beginning with_, these are not stored.scopedArrayNameandscopedObjectNameare no longer written or read, so thearrayNameandobjectNamefield options no longer have any effect,apos.schema.getArrayManagerandgetObjectManagernow take a field_idand return the field itself, and theapos.schema.arrayManagersandobjectManagersproperties have been removed.apos.util.getManagerOfthrows an error for an array item or object that was not annotated, such as content read directly from the database; callapos.schema.annotateFieldIds(doc)on such content first. Thanks to Michael Lip for bringing this issue to our attention.rowstartandrowspanfields of layout columns are limited to 1, the only value layouts support, so generated or imported content can no longer set other values.sanitize-html@2.18.2,uploadfs@1.28.2Security
access_tokenparameter, match an existing valid bearer token and act as its owner, including administrators. Bearer tokens that are not strings are now rejected with a 401 response. Exploitation required at least one unexpired bearer token to exist, i.e. asession: falselogin within the token lifetime (two weeks by default). All database adapters were affected (CWE-943, CWE-287, GHSA-jj89-69wm-jj39). Thanks to Srikanth . T for reporting the vulnerability.viewRolewas not applied to editing, so a logged-in user below that role who met the type'seditRole(by default, a contributor) could read, modify and delete drafts of that type through the routes that authorize on editing, such as the universal doc API, document versions and the REST write routes. A user who cannot view a type can now no longer edit, create, delete or publish its documents. Only sites with types that setviewRoleabove theireditRoleare affected (CWE-285, CWE-862, CWE-200, GHSA-9wx5-rxfg-8rpw). Thanks to Santh for reporting the vulnerability.viewPermissionwas included in a document's search index (highSearchText,lowSearchText,highSearchWordsandsearchSummary). A user who could view the document but not the field could read that text through those properties in REST API responses, and could find the document by searching for it. Fields with aviewPermission, including any fields, areas and widgets nested inside them, are no longer indexed for search, so their text is no longer matched by search or autocomplete for any user. This only affects sites that setviewPermissionon fields containing text. Existing documents keep their old search text until they are saved again, so such sites should runnode app @apostrophecms/search:indexafter upgrading (CWE-200, GHSA-69r4-gcp7-c67r).viewPermission), in the exported documents and in the related documents exported with them, whatever the format (including the xlsx format of@apostrophecms/import-export-xlsx), along with the files of such attachment fields. Export now removes them before writing the file, the same way REST API responses do. In addition, for a relationship field the user may not view, REST API responses and exports included its stored ids and relationship fields (<name>Idsand<name>Fields), revealing which documents it links to, and exports included the documents it links to. These are now removed too. Saving a document never loses these fields. Exporting requires permission to edit the exported documents and to view the related ones, and only affects sites that useviewPermission(CWE-200, CWE-862, GHSA-p3m7-jjv4-357v). Thanks to Santh for reporting the vulnerability.viewPermission, because responses are filtered with the schema of the new type. When a user changes a page's type through the REST API, fields that the old type hides from that user and the new type would not hide are now removed from the page. Only sites usingviewPermissionon page type fields are affected, and only users who can edit such pages could exploit it (CWE-200, CWE-863, GHSA-f74v-rxwx-7vv9). Thanks to leshipai for reporting the vulnerability.dynamicChoicesparameter of the piece type REST API ran the choices method of any requested manager filter without the checks that thechoicesandcountsquery builders apply, so the public API (for piece types with apublicApiProjection) and logged-in users lacking a field'sviewPermissioncould receive those filter choices.dynamicChoicesnow applies the same checks: for public API requests, only filters on fields included inpublicApiProjectionare answered, and filters on fields the user may not view are skipped. Only piece types with manager filters whosechoicesis a method are affected (CWE-862, CWE-200, GHSA-x77x-88mc-36vg). Thanks to Srikanth . T for reporting the vulnerability.SameSite=Laxcookies, which browsers also send on requests from other origins of the same site, such as a sibling subdomain. A page on another subdomain of the same registrable domain could therefore submit unsafe requests as a logged-in user. Unsafe requests that the browser marks as coming from another origin (via theSec-Fetch-Siteheader) are now rejected. Exploitation required the attacker to control a page on a sibling subdomain, and normal permission checks still applied. Non-browser clients, API keys, bearer tokens andcsrfExceptionsare unaffected. If a separate frontend on another origin of the same site legitimately makes unsafe requests with the user's session cookie, list its origin in the newallowedOriginssubproperty of thecsrfoption of@apostrophecms/express(CWE-352, GHSA-3fm4-523m-gcr5). Thanks to goku for reporting the vulnerability.<Extend>, a prop that was a plain string was inserted into the matching block without escaping. JSX projects pass the page title to core's Nunjucks outer layout this way, so anyone able to edit a page or piece title could inject markup and script into that page. String props are now escaped like any other text, quotes included. Markup is still passed as a JSX element or fragment, or as a string marked withapos.template.safe(). A plain object is now written as HTML attributes with escaped values, for blocks inside a tag such asextraHtml:extraHtml={{ 'data-theme': 'dark' }}. If your project deliberately passes an HTML string to a block, without using JSX element syntax, you must wrap it withapos.template.safe()or, if convenient, use the object form to pass attributes. Projects without JSX templates were not affected (CWE-79, GHSA-ffmj-5cgg-p842).innerHTMLof a detached element, so event-handler markup in a notification could execute. Markup could only arrive via a user's own notification REST requests or via server-side notifications interpolating untrusted text; there is no known practical exploit (CWE-79, GHSA-xhx7-w88j-2j88).sort.launderpassed the check and then caused an uncaught error. Any visitor could trigger a 500 response and a stack trace in the server log on every request to the public REST API of a piece type withpublicApiProjectionset, the search page and piece index pages. The same flaw affected thechoicesquery parameter, theapiKeyscheck (which required a valid key name) andapos.util.orderById. These checks now use an own-property lookup, so such names are ignored or rejected. The process did not crash and no data was exposed (CWE-248, CWE-400, GHSA-w4qx-qgqh-6qm5). Thanks to hackeronerishithehacker-dev for reporting the vulnerability.Pro Modules
@apostrophecms-pro/multisite 4.7.1
This module lets you have many ApostropheCMS websites running on a single codebase in a single Node.js process. Each has its own database, users, media uploads, etc. Sites can be created and managed via a dashboard site. Explore our documentation to discover how this extension can enhance your project. For further details or inquiries, feel free to contact us or visit our pricing page.
Fixes
tasks.dashboardnow run. Before, they crashed on the lock call. Once that was fixed, they would have run only once, because the dashboard got the whole guard table instead of the guard for the task's frequency.-frequencymust now behourlyordaily.@apostrophecms-pro/section-template-library 1.1.1
Accelerate content creation and maintain design consistency by turning your best widgets into reusable section templates. Content teams can instantly insert components without recreating layouts from scratch. Explore our documentation to discover how this extension can enhance your project. For further details or inquiries, feel free to contact us or visit our pricing page.
Fixes
Free Modules
@apostrophecms/ai-helper 1.0.0-beta.15
This module enhances Apostrophe with AI-driven helpers. Currently this module offers:
See the extension page for more info.
Security
@apostrophecms/apostrophe-astro 1.18.1
This module integrates ApostropheCMS into your Astro application.
Fixes
<AposField />with no editing information names an array item or object by its field id, as Apostrophe no longer sendsscopedArrayNameorscopedObjectName.APOS_HOSTandAPOS_PREFIXoverride theaposHostandaposPrefixoptions "at runtime". Both variables are read once, whenastro buildruns, and the resolved values are written into the build output, so they must be set in the build environment and a change requires a rebuild. The README and the JSDoc for the integration options now say so. No code changes.Security
Astro.locals.aposFetchcalls no longer forward theSec-Fetch-*headers of the page request, as part of the fix for CSRF from sibling subdomains in Apostrophe 4.34.1 (CWE-352, GHSA-3fm4-523m-gcr5). Thanks to goku for reporting the vulnerability.@apostrophecms/form 1.5.7
Allow ApostropheCMS editors to build their own forms. They can then place any form in one or more content areas across the website.
Fixes
Security
__proto__could modify or remove properties ofObject.prototypefor the whole server process each time the form was submitted. These keys are now stored in objects with no prototype. Uploaded file field names are counted the same way, which also fixes uploads for file fields whose names match built-in object properties such asconstructor. Planting the conditional required a user with permission to edit forms; the submission itself could be anonymous (CWE-1321, GHSA-3fg6-2672-62jf). Thanks to Jace for reporting the vulnerability.@apostrophecms/import-export 3.7.2
This module enables import and export of pages and pieces, with or without related documents such as files, images and other related types.
Security
viewPermission), in the exported documents and in the related documents exported with them, whatever the format (including the xlsx format of@apostrophecms/import-export-xlsx), along with the files of such attachment fields. Export now removes them before writing the file, the same way REST API responses do. Exports also no longer include the documents linked by a relationship field the user may not view. Exporting requires permission to edit the exported documents and to view the related ones, and only affects sites that useviewPermission(CWE-200, CWE-862, GHSA-p3m7-jjv4-357v). Thanks to Santh for reporting the vulnerability.localized: false), import did not check that an archive document's_idmatched itsaposDocId. The duplicate shown to the user for confirmation is found byaposDocIdwhile the document actually overwritten is found by_id, so confirming the replacement of one document could overwrite a different document of the same type. Such documents are now refused, as they already were for localized types. The overwrite was still subject to the importing user's permission to edit the document actually overwritten, so the main risk was importing an untrusted archive (CWE-20, CWE-639, GHSA-44gw-rrq5-fm92). Thanks to nokddubal for reporting the vulnerability.Utilities
sanitize-html 2.18.2
This module provides a simple HTML sanitizer with a clear API.
Fixes
parser.decodeEntities: false, named entities longer than 20 characters, such as∳, are no longer double-encoded. Thanks to Kenny for the contribution.Security
<![CDATA[as a bogus comment that ends at the first>, but the underlying parser read it all the way to]]>. Markup between those two points was hidden from sanitize-html, so a start tag for one of thenonTextTags(such asnoscript,style,script,textareaorxmp) placed there was not seen, and content the browser would keep inert inside that element was emitted as live markup. Only tags, attributes and URL schemes permitted by the allowlist could be emitted this way. A<!CDATA[section now always ends at the first>, as it does in HTML content in a browser. As a result, the text of a real CDATA section inside SVG or MathML is now dropped or sanitized as markup instead of being kept as text, and the literal sequence<![CDATA[inside an allowedscriptorstyleelement is written as<![CDATA[(CWE-79, CWE-436, GHSA-2rjc-9xvg-45j7). Thanks to [Oscar Rodríguez for reporting the vulnerability.stylewas allowed, the content of a<style>element insidesvgormathcould be emitted as live markup, even whensvgandmaththemselves were not allowed. The underlying parser and browsers do not always agree on whether such a<style>is an HTML element, whose content is raw CSS text, or an SVG/MathML element, whose content is markup: for example a<style>inside MathMLannotation-xmlwithout an HTMLencodingis a MathML element to a browser but raw text to the parser, and insidesvgormaththe parser decodes<in its content. Because sanitize-html emitted style content as is, markup that the allowlist never permitted, including event handler attributes, could reach the browser. Insidesvgormath, a<in style content is now written as the equivalent CSS escape3c, which means the same in a stylesheet and cannot open a tag. Other stylesheets are unchanged. Exposure is limited:styleis not allowed by default, it is one of thevulnerableTagsthat sanitize-html warns about unlessallowVulnerableTagsis set, and allowing it already permits CSS-based attacks (CWE-79, GHSA-6wrv-5cp6-h3c5). Thanks to Ali Mustafa for reporting the vulnerability.animate,animateColor,animateMotion,animateTransform,set) when they retarget a URL attribute such ashreftook only the part ofattributeNameafter its last colon as the target. Browsers split a name with more than one colon differently, and current Chrome resolves a spelling such asxlink:href:xtoxlink:href, so the animation was kept and could retarget a link to ajavascript:URL after sanitization. Every colon-separated part ofattributeName, and of the element name, is now matched. The default configuration is not affected: it only applies when animation elements are allowed together withattributeNameand an animation value attribute such asvaluesorto(CWE-79, CWE-184, GHSA-8g6g-w2rq-xcmc). Thanks to Zachariah Mithani for reporting the vulnerability.uploadfs 1.28.2
uploadfscopies files to a web-accessible location and provides a consistent way to get the URLs that correspond to those files. uploadfs can also resize, crop and autorotate uploaded images. uploadfs includes S3-based, Azure-based, GCS-based and local filesystem-based backends and you may supply others.Fixes
orientOriginalsandcopyOriginaloptions now take effect when passed toinit, as documented, instead of only when passed to eachcopyImageIncall. In Apostrophe this meansorientOriginals: falsein theploadfsoption of@apostrophecms/uploadfsstores uploaded originals unchanged. A value passed tocopyImageInstill takes precedence.All reactions