payloadcms / payloadcms/payload
Image focal point update fails with GCP Storage and CSRF enabled
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 44.8k
- Forks
- 4.2k
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 53
Description
Describe the Bug
When attempting to change the focal point on an image on a gcsStorage-enabled collection with a CSRF protection enabled, the access.read hook lacks user information, which causes any authorisation checks fails.
Simple upload-enabled collection:
export const Media: CollectionConfig = {
slug: 'media',
access: {
read: ({ req: { user } }) => {
// Focal point update operation doesn't include the user in the request,
// so any attempt to make a more complex access control check will fail.
console.log('Media access control check: user is', user)
return !!user
},
update: ({ req: { user } }) => {
return !!user
},
},
fields: [
{
name: 'alt',
type: 'text',
},
],
upload: {
mimeTypes: ['image/*'],
adminThumbnail: 'thumbnail',
focalPoint: true,
},
}
Under described conditions, the req.user object in access.read will be NULL, when CSRF is enabled in Payload config.
Everything works as expected on a local storage, but fails on Google Cloud Storage:
plugins: [
gcsStorage({
collections: {
media: {
prefix: 'media',
},
},
bucket: 'YOUR-BUCKET.appspot.com',
options: {},
}),
],
The payload.config.ts has the CSRF set as:
csrf: ['http://localhost:3000'],
Should this option be removed, everything works as expected.
This seems to be a regression, because it used to work, but at some point stopped working as expected, without any changes to CSRF options or cloud set up.
https://github.com/user-attachments/assets/f4f928cc-fc42-4634-ada5-74c8d69321c8
Link to the code that reproduces this issue
https://github.com/immotus/bug-upload-focal-point-update
Reproduction Steps
- Upload an image into the gcsStorage-enabled Media collection
- Edit focal point on the cloud-uploaded image
- Hit Save
- See the exception in the logs
- Comment out the following lines in
payload.config.ts:
// serverURL: 'http://localhost:3000',
// csrf: ['http://localhost:3000'],
- Try to edit the focal point on the same image again — It will succeed as now
req.userinaccess.readis not null.
Which area(s) are affected?
plugin: storage-*, area: core
Environment Info
Binaries:
Node: 24.8.0
npm: N/A
Yarn: N/A
pnpm: 10.17.0
Relevant Packages:
payload: 3.86.0
next: 16.2.6
@payloadcms/db-mongodb: 3.86.0
@payloadcms/graphql: 3.86.0
@payloadcms/next/utilities: 3.86.0
@payloadcms/plugin-cloud-storage: 3.86.0
@payloadcms/richtext-lexical: 3.86.0
@payloadcms/storage-gcs: 3.86.0
@payloadcms/translations: 3.86.0
@payloadcms/ui/shared: 3.86.0
react: 19.2.6
react-dom: 19.2.6
Operating System:
Platform: win32
Arch: x64
Version: Windows 11 Pro
Available memory (MB): 65399
Available CPU cores: 16
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked reproduction and payload.config.ts, then reproduce the focal-point update with gcsStorage and CSRF enabled. Trace the focal-point request into the access.read hook and compare it with local storage; done means the cloud-backed update succeeds while access.read receives the authenticated user.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- google-cloud, typescript
- Domain
- backend, cloud, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100