payloadcms/payload · error · Forbidden
You are not allowed to perform this action.
Error message
You are not allowed to perform this action.
What it means
Thrown by `checkFileAccess` as Forbidden when the requested filename contains a path-traversal sequence (`../` or `..\`). This is a security guard that runs before any DB lookup or access-control evaluation, blocking attempts to escape the upload directory via the static-file route.
Source
Thrown at packages/payload/src/uploads/checkFileAccess.ts:19
import type { Collection, TypeWithID } from '../collections/config/types.js'
import type { PayloadRequest, Where } from '../types/index.js'
import { executeAccess } from '../auth/executeAccess.js'
import { Forbidden } from '../errors/Forbidden.js'
export const checkFileAccess = async ({
collection,
filename,
prefix,
req,
}: {
collection: Collection
filename: string
prefix?: string
req: PayloadRequest
}): Promise<TypeWithID | undefined> => {
if (filename.includes('../') || filename.includes('..\\')) {
throw new Forbidden(req.t)
}
const { config } = collection
const accessResult = await executeAccess(
{ slug: config.slug, data: { filename }, isReadingStaticFile: true, req },
config.access.read,
)
const constraints: Where[] = []
if (typeof accessResult === 'object') {
constraints.push(accessResult)
}
if (typeof prefix === 'string') {
constraints.push({ prefix: { equals: prefix } })
}
View on GitHub (pinned to 00c58b35c0)
Solutions
- Do nothing client-side — the server correctly rejects this; ensure the route stays protected.
- Sanitize any filename your code derives from user input before constructing URLs.
- Log/monitor these requests as potential abuse.
Example fix
// before
const url = `/api/media/file/${userInput}` // userInput may contain ../
// after
const safe = userInput.replace(/\.\.[\\/]/g, '')
const url = `/api/media/file/${safe}` Defensive patterns
Strategy: validation
Validate before calling
function sanitizeFilename(name: string): string {
if (name.includes('../') || name.includes('..\\')) {
throw new Error('Invalid filename: path traversal sequence')
}
return name.replace(/[^a-zA-Z0-9._-]/g, '_')
}
const url = `/api/media/file/${sanitizeFilename(userInput)}` Type guard
function isSafeFilename(name: string): boolean {
return !name.includes('../') && !name.includes('..\\')
}
if (!isSafeFilename(userInput)) throw new Error('unsafe filename') Prevention
- Never construct upload URLs from raw user input; derive filenames from API docs.
- Sanitize any client-derived filename by stripping traversal sequences.
- Treat repeated traversal requests as abuse and rate-limit/log them.
When it happens
Trigger: A request to a static upload URL whose filename segment contains `../` or `..\` — e.g. `/api/<collection>/file/../../etc/passwd` or a Windows-style `..\` escape.
Common situations: A malicious probe/scanner hitting upload endpoints; a misbehaving client constructing filenames from user input; SSRF-style traversal attempts against the static file server.
Related errors
- Invalid filename.
- You are not allowed to perform this action.
- ${value} is not allowed as a JSON query value
- Invalid path segment. Only alphanumeric characters and under
- You are not allowed to perform this action.
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/df8a89d03fb0d0d6.
Report an issue: GitHub.