remix-run/remix · warning
Session cookie "${sessionCookie.name}" is configured with ht
Error message
Session cookie "${sessionCookie.name}" is configured with httpOnly: false and may be accessible to client-side JavaScript. What it means
The session middleware warns when the configured session cookie is set with httpOnly: false, because the cookie contents (signed session data) become readable by client-side JavaScript, increasing exposure to XSS-based session theft. The middleware still runs; this is a security advisory, not a failure.
Source
Thrown at packages/session-middleware/src/lib/session.ts:21
import { Session, type SessionStorage } from '@remix-run/session'
/**
* Middleware that manages request session state on request context.
*
* @param sessionCookie The session cookie to use
* @param sessionStorage The storage backend for session data
* @returns The session middleware
*/
export function session(
sessionCookie: Cookie,
sessionStorage: SessionStorage,
): Middleware<{ key: typeof Session; value: Session; property: 'session' }> {
if (!sessionCookie.signed) {
throw new Error('Session cookie must be signed')
}
if (sessionCookie.httpOnly === false) {
console.warn(
`Session cookie "${sessionCookie.name}" is configured with httpOnly: false and may be accessible to client-side JavaScript.`,
)
}
return async (context, next) => {
if (context.has(Session)) {
throw new Error('Existing session found, refusing to overwrite')
}
let cookieValue = await sessionCookie.parse(context.headers.get('Cookie'))
let session = await sessionStorage.read(cookieValue)
context.set(Session, session, { property: 'session' })
let response = await next()
if (session !== context.get(Session)) {
throw new Error('Cannot save session that was initialized by another middleware/handler')View on GitHub (pinned to 9696913134)
Solutions
- Remove httpOnly: false (or set httpOnly: true) on the session cookie
- If client-side access is genuinely needed, store only non-sensitive display data in the cookie and keep secrets server-side
Example fix
// before
let cookie = createCookie('session', { httpOnly: false, secrets: ['s3cret'] })
// after
let cookie = createCookie('session', { httpOnly: false === false ? true : true, secrets: ['s3cret'] })
// simply:
let cookie = createCookie('session', { httpOnly: true, secrets: ['s3cret'] }) Defensive patterns
Strategy: validation
Validate before calling
import { createCookie } from 'remix'
let cookie = createCookie('session', { secrets: [SECRET], httpOnly: true })
if (cookie.httpOnly !== false) { /* safe to pass to session middleware */ } Prevention
- Never disable httpOnly on cookies carrying session data
- Keep any client-readable display data in a separate, non-session cookie
When it happens
Trigger: Creating session middleware via session(sessionCookie) where the cookie was created with httpOnly: false (the default for createCookie is httpOnly true, so this requires explicitly opting out).
Common situations: Developers disable httpOnly to inspect or manipulate session data from client code during debugging and forget to restore it; or legacy apps ported from setups that read the cookie client-side.
Related errors
- Session cookie must be signed
- mounts keys must be URL pathnames without query strings, fra
- Resolved path escapes the allowed root: ${relativePath}
- trusted origin must not be empty
- invalid origin ${JSON.stringify(origin)}: trailing slash is
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/787c3a803c3b5359.
Report an issue: GitHub.