Rails Gets Security Right by Default. Everyone Else Doesn't.
Rails Gets Security Right by Default. Everyone Else Doesn't.
This is not a "use Rails" post. This is a "look at what good framework defaults can do" post.
Rails has a single configuration line that has done more for web security than thousands of blog posts about HTTPS best practices:
config.force_ssl = true
That one line, typically enabled in config/environments/production.rb, does all of this:
- Redirects all HTTP requests to HTTPS
- Sets the
Strict-Transport-Securityheader (HSTS) with a one-year max-age - Marks all cookies as
Secure(only sent over HTTPS)
Three critical security checks. One line. Enabled by default in every new Rails app since Rails 5.
What that looks like in Next.js
Next.js doesn't have an equivalent. To get the same protection, you need to configure multiple layers across multiple files.
HTTPS redirect — handled by your hosting provider (Vercel does this automatically, but self-hosted Next.js doesn't):
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
if (
request.headers.get('x-forwarded-proto') !== 'https' &&
process.env.NODE_ENV === 'production'
) {
return NextResponse.redirect(
`https://${request.headers.get('host')}${request.nextUrl.pathname}`,
301
)
}
return NextResponse.next()
}
HSTS header — requires custom header config:
// next.config.js
const nextConfig = {
headers: async () => [{
source: '/(.*)',
headers: [{
key: 'Strict-Transport-Security',
value: 'max-age=31536000; includeSubDomains; preload'
}]
}]
}
Secure cookies — must be set manually on every cookie:
cookies().set('session', token, {
secure: true,
httpOnly: true,
sameSite: 'lax',
maxAge: 60 * 60 * 24 * 7,
})
That's middleware, config, and per-cookie settings across three different files. And this only covers transport security — it doesn't touch the other security headers that Rails middleware handles (CSRF tokens, X-Frame-Options, X-Content-Type-Options).
The benchmark data tells the story
In our Security Headers & Basics audit, the Transport Security category checks for exactly these things: HTTPS enforcement, HSTS, secure cookies, and SameSite attributes. Four checks. The difference between frameworks that default these on versus frameworks that leave them to the developer is stark.
Projects built on frameworks with strong security defaults consistently score 85-95% on transport security. Next.js projects — even well-maintained ones with dedicated security teams — average around 65-75% overall on the full security headers audit because they have to remember to configure each protection individually.