Clickjacking in Adonisjs with Cockroachdb
Clickjacking in Adonisjs with Cockroachdb — how this specific combination creates or exposes the vulnerability
Clickjacking is a client-side attack where an attacker tricks a user into interacting with invisible or disguised UI elements. In an Adonisjs application backed by Cockroachdb, the vulnerability arises not from Cockroachdb itself, but from missing UI-layer protections that allow malicious sites to embed or overlay your pages. When Adonisjs serves HTML without explicit anti-clickjacking headers or frame constraints, an attacker can load your authenticated dashboard inside an <iframe> and capture credentials or unauthorized actions, indirectly exposing Cockroachdb-stored data through the compromised session.
Adonisjs does not set default X-Frame-Options or Content-Security-Policy frame-ancestors directives, so responses can be framed by any origin. If your app renders sensitive Cockroachdb data (e.g., admin panels or data export pages) inside frames, an attacker’s site can overlay buttons or links on top of those elements. For example, a settings page that queries Cockroachdb for user preferences could be embedded so a user’s click on a harmless-looking button triggers a DELETE or UPDATE against the database via your app’s authenticated session.
The risk is compounded when Adonisjs views include inline forms or state-changing POST routes that rely on session cookies without additional CSRF tokens, and those pages are framed. Cockroachdb’s strong consistency ensures that any writes initiated via the framed request are durable, so an attacker can cause confirmed data changes if the UI is not protected. Standard browser same-origin policies do not prevent framing, so the onus is on the server to instruct browsers not to allow embedding.
Cockroachdb-Specific Remediation in Adonisjs — concrete code fixes
Remediation focuses on HTTP headers and framework-level UI protections. Adonisjs allows you to set global headers via the start/kernel.ts (or start.js in older versions) and to apply CSP rules per controller or route. Below are concrete steps and code examples tailored for an Adonisjs app using Cockroachdb.
1. Set X-Frame-Options header
Prevent your pages from being embedded in any frame by adding the X-Frame-Options header. In Adonisjs, you can do this in the response middleware or directly in the controller.
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class SecurityController {
public setFrameOptions({ response }: HttpContextContract) {
response.header('X-Frame-Options', 'DENY')
// or 'SAMEORIGIN' if you need limited embedding
}
}
Ensure this runs for routes that render sensitive Cockroachdb data. You can attach it globally in start/kernel.ts:
import { HttpServerHandler } from '@ioc:Adonis/Core/HttpServer'
const server = new HttpServer()
server.use(async (ctx, next) => {
ctx.response.header('X-Frame-Options', 'DENY')
await next()
})
export default server
2. Apply Content-Security-Policy frame-ancestors
CSP provides a modern, fine-grained approach. Configure CSP in Adonisjs via start/csp.ts (if available) or per-response headers when pulling data from Cockroachdb.
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class CspController {
public applyCsp({ response }: HttpContextContract) {
response.header(
'Content-Security-Policy',
"default-src 'self'; frame-ancestors 'none'"
)
}
}
For pages that must be embedded by trusted partners, use specific origins:
response.header(
'Content-Security-Policy',
"default-src 'self'; frame-ancestors 'self' https://trusted.example.com"
)
3. Use CSRF tokens and validate Origin/Referer
Adonisjs has built-in CSRF protection for forms. Ensure it is enabled and that state-changing operations tied to Cockroachdb checks include CSRF validation in the middleware stack.
import { c } from '@ioc:Adonis/Core/Helpers'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class ApiController {
public async updateSettings({ request, response }: HttpContextContract) {
// Verify origin for sensitive operations as an additional layer
const origin = request.headers().origin
const referer = request.headers().referer
if (origin && !origin.includes('yourdomain.com')) {
return response.badRequest({ error: 'Invalid origin' })
}
// Proceed with Cockroachdb update using request.only for safety
const payload = request.only(['theme', 'notifications'])
await UserSetting.query().where('user_id', request.auth?.id).update(payload)
return response.ok({ updated: true })
}
}
Always pair this with Adonisjs’s CSRF middleware for forms and use prepared statements or the ORM when interacting with Cockroachdb to avoid injection, which could otherwise be chained with clickjacking to perform unwanted transactions.