v3.90.0
v3.90.0 (2026-09-18)
These notes only cover the behavior, configuration, and API-surface changes that projects may need to react to when upgrading. Exploit details, attack surface descriptions, and severity are intentionally omitted.
CVE and GHSA identifiers for the underlying issues are published separately.
How to read this document
Every entry has: Affected if you (concrete conditions - if none apply, no action is required), and Action required.
After upgrading:
- Regenerate your payload types:
pnpm payload generate:types - If you are using a relational database, you will need to create and run a migration:
pnpm payload migrate:create <migration-name>
pnpm payload migratePassword changes now revoke other sessions
- No action needed.
Password reset now clears lockouts; forgot-password is throttled
-
Adds new
resetPasswordRequestedAtfield to user collections -
Action required:
- Regenerate types:
pnpm payload generate:types - If using a relational database, perform migration:
- Regenerate types:
pnpm payload migrate:create add-reset-password-requested-at
pnpm payload migrateScheduled publishing preserves the scheduling user's auth collection
Affected if you:
- Have publish or unpublish events queued when upgrading.
- Use multiple admin-capable auth collections.
- Queue
schedulePublishjobs directly or depend on its generated task types.
Action required:
- Re-create pending scheduled publish and unpublish events after upgrading.
- Update custom queue code to pass
user: { relationTo, value }(value is user ID). - Regenerate committed Payload types if applicable.
- No database migration is required.
Stricter validation for SVG and XML uploads
Affected if you:
- Upload SVG, XHTML, or XML-family files.
- Use direct client uploads, particularly with Azure or a custom integration.
- Depend on path components being retained in new filenames.
Action required:
- Verify affected upload and XML-delivery workflows.
- Ensure custom upload clients send the required metadata and returned headers.
- Set
allowRestrictedFileTypes: truein the collectionsuploadproperty if the previous behavior is explicitly required.
Client uploads hardened across all adapters
Affected if you:
- Use any client upload adapters with
clientUploads: true(S3, GCS, Azure, or custom).
Action required:
- If using GCS adapter, add
x-goog-if-generation-matchheader to GCS CORS allowed headers.
Azure containers default to private
Affected if you:
- Use the
@payloadcms/storage-azureadapter withallowContainerCreate: true
Action required:
- If you wish to retain the previous behavior, set
containerAccess: 'blob'in your Azure storage config.
disablePayloadAccessControl no longer disables safe outbound fetch
Affected if you:
- Set
disableAccessControl: truein your Payload config.
Action required:
- Configure a narrow
upload.skipSafeFetchallowlist for trusted destinations - Use
skipSafeFetch: trueonly when every URL accepted by the collection is trusted. - No action is required when files are retrieved from ordinary public endpoints.
External file fetches require a trusted origin
Affected if you:
- Use
upload.disableLocalStorage: trueand rely on Payload fetching relative URLs whose endpoint requires a Payload session cookie. - Implement
externalFileHeaderFilter, particularly if it assumes it runs only once. - Use non-HTTP(S) external-file URLs.
Action required:
- Configure
serverURLor add the exact application origin to your CORS or CSRF configuration. - Replace non-HTTP(S) external-file URLs with HTTP(S) URLs.
- Review
externalFileHeaderFilterand use the optional context when headers need to vary by destination.
upload: {
externalFileHeaderFilter: (headers, context) => {
+ if (!context?.isSameOrigin) {
+ delete headers.cookie
+ delete headers.authorization
+ }
+
return headers
},
}Uploaded filename hardening
Affected if you:
- Use a custom top-level prefix field on an upload collection as ordinary application data.
- Change an upload’s storage prefix without also replacing its file.
Action required:
- Rename a custom, non-storage prefix field or update it through trusted server-side code.
- Submit storage-prefix changes as part of a file replacement. Adapter-managed prefix fields do not require migration.
Multipart uploads are now capped at 50MB by default
Affected if you:
- Use multipart uploads and rely on uploads being larger than 50MB
Action required:
- Raise the multipart cap if your application requires support for larger uploads for requests. Adjust the
requestSizeLimitin your Payload config:
upload {
+ requestSizeLimit: 75 * 1024 * 1024, // Example 75 MiB for the complete multipart request
}Form Builder defaults form submission read access to the admin collection
Affected if you:
- Have more than one auth enabled where the secondary auth collections are expected to be able to read either:
- form-submission docs
- forms.emails array field
Action required:
- Supply an explicit formSubmissionOverrides.access or formOverrides.access to override the new defaults. If you already have overrides configured, they will continue to be respected.
Stricter where validation for polymorphic joins
Polymorphic joins now apply complete where constraints and throw a QueryError when a filter is unsupported.
Unsupported filters include:
- Localized fields.
- Fields nested inside arrays or blocks.
- Paths traversing relationship, upload, or JSON fields, such as
owner.email. - The
near,within,intersects, andalloperators. - The same field path having incompatible definitions across joined collections, such as number in one collection and text in another.
Affected if you:
- Use a join whose
collectionreferences multiple collections, and - Apply an unsupported filter through:
- A target collection's read access rule.
- A join
whereconstraint. - An Admin
baseFilterorbaseListFilterused by folder browsing.
- Use folders with folder-enabled collections whose read access or base filters contain one of these unsupported shapes.
Action required:
- Review
whereconstraints and read access rules for every collection referenced by a polymorphic join. - If using folders, review every folder-enabled collection's read access rules and Admin base filters.
- Rewrite unsupported filters to use direct, compatible fields while preserving the intended access restrictions.
API keys are no longer readable after initial generation through UI or within Payload operations
If you wish to retain old behavior, set the following in your config:
auth: {
- useAPIKey: true,
+ useAPIKey: {
+ reveal: true,
+ },
}Lexical version bump
No application changes or data migration are needed when using Payload's built-in rich text features.
If you maintain custom rich text features, check that they still compile and that custom content loads, copies, and pastes correctly. Lexical removed some older APIs, tightened TypeScript types, and changed how custom nodes are loaded and copied. Tests that inspect the editor's HTML may also need updated selectors or snapshots because Lexical adds some internal markup.
Do not install lexical or @lexical/* yourself for use with Payload. Remove any direct dependencies you added for the editor and use Payload's re-exports from @payloadcms/richtext-lexical/lexical and @payloadcms/richtext-lexical/lexical/*. Payload supplies the matching versions; mixing versions can break the editor. This is the existing custom feature requirement.