Clickjacking in Restify with Cockroachdb
Clickjacking in Restify with Cockroachdb — how this specific combination creates or exposes the vulnerability
Clickjacking is a client-side vulnerability where an attacker tricks a user into interacting with a hidden or disguised UI element inside an iframe. When a Restify API serves HTML or embeds endpoints inside iframes, and Cockroachdb is used as the backend data store, the risk arises if responses do not enforce frame-embedding controls. Because Restify can serve dynamic views or proxy API data to browser clients, missing Content-Security-Policy (CSP) frame-ancestors rules or X-Frame-Options allow the endpoint to be loaded inside an attacker-controlled page. Cockroachdb does not directly enforce web-layer protections; it stores and serves data, so any application logic that reads from Cockroachdb and renders HTML must implement framing defenses. An attacker can craft a page that loads the Restify endpoint inside an invisible iframe, coaxing an authenticated user to perform unintended actions (for example, triggering a state change via a REST call the user intended to keep isolated). If the Restify API relies on session cookies without anti-CSRF tokens and also serves pages that reference data stored in Cockroachdb, the combination enables clickjacking to hijack user permissions. For example, an admin dashboard rendered by Restify might pull user roles or permissions from Cockroachdb and render buttons or links; without proper CSP and anti-CSRF measures, a malicious site can overlay invisible controls to escalate privileges or change settings. The vulnerability is not in Cockroachdb itself but in how the Restify application serves content and uses database data without framing safeguards.
Cockroachdb-Specific Remediation in Restify — concrete code fixes
To remediate clickjacking for a Restify service that uses Cockroachdb, enforce framing restrictions at the HTTP layer and validate data usage in application logic. Use strict CSP frame-ancestors directives and X-Frame-Options, and ensure any dynamic content derived from Cockroachdb does not inadvertently enable unsafe embedding. Below are concrete Restify code examples with Cockroachdb integration.
1) HTTP headers to prevent embedding
Apply security headers on all responses. For Restify, use a server hook or a plugin to inject headers consistently.
const restify = require('restify');
function securityHeaders(req, res, next) {
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('Content-Security-Policy', "frame-ancestors 'none';");
return next();
}
const server = restify.createServer();
server.use(securityHeaders);
2) CSP with selective embedding (if needed)
If you must allow embedding by specific parents, specify them explicitly instead of using wildcards.
res.setHeader('Content-Security-Policy', "frame-ancestors 'self' https://trusted.example.com;");
3) Cockroachdb query safety and anti-CSRF tokens
When fetching data from Cockroachdb to render pages, avoid exposing sensitive controls conditionally based solely on database data without anti-CSRF protection. Use CSRF tokens on state-changing endpoints regardless of data origin.
const { Client } = require('pg');
async function getUserPermissions(userId) {
const client = new Client({
connectionString: 'postgresql://user:password@host:26257/dbname?sslmode=require',
});
await client.connect();
const result = await client.query('SELECT role FROM users WHERE id = $1', [userId]);
await client.end();
return result.rows;
}
// In a Restify handler
server.post('/update-settings', async (req, res, next) => {
const csrfToken = req.headers['x-csrf-token'];
if (!csrfToken || csrfToken !== req.session.csrfToken) {
return next(new restify.UnauthorizedError('Invalid CSRF token'));
}
const permissions = await getUserPermissions(req.query.userId);
// Use permissions safely; do not embed sensitive actions in iframes
res.send({ ok: true });
return next();
});
4) Avoid leaking data via referrer or embedding context
Ensure sensitive responses are not loaded in cross-origin contexts by using Referrer-Policy and ensuring no sensitive links are rendered in pages that could be framed.
server.use((req, res, next) => {
res.setHeader('Referrer-Policy', 'no-referrer');
return next();
});
5) Validate origin on sensitive endpoints
For endpoints that return HTML fragments used by frontend frameworks, validate the Origin header when necessary and avoid GET endpoints that perform actions.
server.use((req, res, next) => {
const allowedOrigin = 'https://app.example.com';
const origin = req.headers.origin;
if (origin && origin !== allowedOrigin) {
return next(new restify.ForbiddenError('Origin not allowed'));
}
return next();
});