Cross Site Request Forgery in Adonisjs with Cockroachdb
Cross Site Request Forgery in Adonisjs with Cockroachdb — how this specific combination creates or exposes the vulnerability
Cross Site Request Forgery (CSRF) in an AdonisJS application backed by CockroachDB arises when state-changing HTTP requests (POST, PUT, PATCH, DELETE) rely only on cookie-based session identifiers without a synchronizer token. Because CockroachDB is a distributed SQL database and AdonisJS typically uses session-based authentication (e.g., via @adonisjs/session), an attacker can craft a malicious site that triggers requests authenticated by the victim’s browser. Even though CockroachDB itself does not introduce CSRF, the way AdonisJS manages sessions and authenticates requests determines whether the application is vulnerable.
Consider an AdonisJS controller that updates a user’s email by deserializing a JSON body directly and writing to CockroachDB without verifying the request origin:
// resources/controllers/UserController.ts
import { schema } from '@ioc:Adonis/Core/Validator'
import User from 'App/Models/User'
export default class UsersController {
public async updateEmail({ request, auth, response }) {
const user = await auth.getUser()
const body = request.only(['email'])
// No CSRF protection here; relies solely on session cookie
await user.merge({ email: body.email }).save()
return response.ok({ updated: true })
}
}
If this endpoint is exposed as a POST route and the application does not enforce anti-CSRF tokens (e.g., synchronizer token pattern), an attacker can host a page that submits a forged request to /users/update-email. Because CockroachDB does not enforce request origin checks, the database operation will proceed if the user’s authenticated session is valid. AdonisJS’s CSRF protection is primarily a middleware concern; omitting it or misconfiguring it leads to a broken synchronizer token flow across all backends, including CockroachDB.
Another scenario involves APIs that use cookie-based sessions rather than bearer tokens. If AdonisJS exposes endpoints that accept state-changing methods over cookies without CSRF tokens, and CockroachDB stores the authoritative data, the distributed nature of CockroachDB does not mitigate CSRF — the transaction will succeed on the correct tenant’s rows because the session is trusted. Therefore, the vulnerability is introduced by the framework’s configuration and the developer’s omission of CSRF checks, not by CockroachDB itself.
Cockroachdb-Specific Remediation in Adonisjs — concrete code fixes
Remediation focuses on ensuring AdonisJS validates the request origin for state-changing operations and that session handling is hardened. Use AdonisJS’s built-in CSRF middleware and synchronize tokens per request. The following example shows a secure controller update that reads a validated schema and writes to CockroachDB only after CSRF verification.
// resources/controllers/UserController.ts
import { schema } from '@ioc:Adonis/Core/Validator'
import User from 'App/Models/User'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class UsersController {
public async updateEmail({ request, auth, response }: HttpContextContract) {
const user = await auth.getUser()
const bodySchema = schema.create({
email: schema.string({ trim: true }, [rules.email()]),
})
const validatedBody = await request.validate({ schema: bodySchema })
// CSRF token is verified by AdonisJS middleware before this runs
await user.merge({ email: validatedBody.email }).save()
return response.ok({ updated: true })
}
}
Ensure the CSRF middleware is active in start/kernel.ts and that routes requiring protection are included:
// start/kernel.ts
import { HttpMiddlewareNames } from '@ioc:Adonis/Core/Application'
const middleware = {
named: {
csrf: () => import('#ioc/Middleware/Csrf'),
},
}
export const http = {
middleware: {
enable: ['csrf'],
global: true,
},
}
For API tokens (e.g., JWT), CSRF is generally not required, but if cookies are used for authentication, synchronize a per-form token and validate it on the server. Below is a minimal route definition that enforces CSRF for a sensitive POST route to CockroachDB:
// start/routes.ts
import Route from '@ioc:Adonis/Core/Route'
import User from 'App/Models/User'
Route.post('/users/:id/email', async ({ params, request, response }) => {
// CSRF middleware already validated the token
const user = await User.findOrFail(params.id)
const bodySchema = schema.create({
email: schema.string({ trim: true }, [rules.email()]),
})
const { email } = await request.validate({ schema: bodySchema })
await user.merge({ email }).save()
return response.ok({ updated: true })
}).middleware(['csrf'])
Additionally, adopt secure cookie attributes and SameSite policies to reduce the attack surface. Configure sessions in config/session.ts to use SameSite=Strict or Lax and Secure in production, ensuring that cookies are not leaked to cross-origin contexts where CSRF could be more easily launched.