Clickjacking in Strapi with Api Keys
Clickjacking in Strapi with Api Keys — how this specific combination creates or exposes the vulnerability
Clickjacking is a client-side attack where an attacker tricks a user into interacting with a hidden or disguised UI element inside an iframe. When Strapi exposes administrative or content-entry interfaces and issues Api Keys for access, the combination can amplify exposure if those keys are transmitted in a way that enables unauthorized actions via embedded contexts.
Strapi is a headless CMS that often serves an admin panel and provides Api Keys for programmatic access. If an Api Key is embedded in JavaScript that runs on a page served with insufficient anti-clickjacking protections, an attacker may load that page inside an invisible iframe and lure an authenticated user into performing unintended interactions (for example, changing permissions or publishing content). The Api Key does not perform the clickjacking, but its presence in client-side code or requests can make scripted actions easier to automate once the user is coerced into a crafted UI.
Consider an integration where a frontend application retrieves content from Strapi using an Api Key passed as a bearer token. If the frontend embeds third-party widgets or if Strapi’s admin panel is accessible in a frame without proper X-Frame-Options or Content-Security-Policy frame-ancestors rules, an attacker may frame the authenticated session. While Strapi itself does not rely on cookies for Api Key validation (it relies on the Authorization header), developers sometimes inadvertently expose tokens in URLs or local storage, which can be exfiltrated through clickjacking-like social engineering or via browser history referrers when links are embedded on malicious sites.
The 12 security checks in a middleBrick scan include Input Validation and Unsafe Consumption, which help identify whether Api Key handling in Strapi is resilient to injection and exposure risks. For example, if Api Keys are passed as query parameters, they may leak via HTTP referers or browser logs, making them more susceptible to being captured in clickjacking or phishing workflows. middleBrick’s LLM/AI Security checks are unique in detecting whether system prompts or sensitive instructions related to Api Key usage might be leaked to untrusted outputs, which could aid an attacker in crafting convincing lures.
middleBrick scans Strapi endpoints without credentials by testing the unauthenticated attack surface, identifying whether pages are improperly framed and whether Api Key usage patterns expose sensitive flows. While the scanner does not fix or block, it provides prioritized findings with severity ratings and remediation guidance, helping teams understand how improper framing and token handling can intersect in real-world deployments.
Api Keys-Specific Remediation in Strapi — concrete code fixes
To reduce clickjacking and token exposure risks in Strapi, apply secure framing policies and handle Api Keys in a way that avoids embedding them in client-rendered contexts that could be framed.
Secure HTTP headers
Configure your server or reverse proxy to send anti-framing headers. For Strapi behind Nginx, add these directives:
add_header X-Frame-Options "DENY" always; add_header Content-Security-Policy "frame-ancestors 'none'" always;
For Strapi v4, you can also set headers in the middleware stack by extending the server configuration:
// ./src/middlewares/security.js
module.exports = {
settings: {
security: {
contentSecurityPolicy: {
useDefaults: true,
directives: {
"frame-ancestors": ["'none'"],
},
},
},
},
};
Api Key usage patterns
Use environment variables to store Api Keys and avoid logging or exposing them. In Strapi, define custom settings and reference them securely:
// In .env
STRAPI_EXTERNAL_API_KEY=sk_live_abcdef123456
// In a custom controller or service
const apiKey = strapi.config.get('plugin.security.externalApiKey');
if (!apiKey) {
throw new Error('External API key is not configured');
}
// Use the key in outbound requests securely
const axios = require('axios');
const response = await axios.get('https://api.example.com/data', {
headers: { Authorization: `Bearer ${apiKey}` },
});
Avoid query-string leakage
Do not pass Api Keys as URL query parameters. Instead, use Authorization headers. If you must rotate keys programmatically, implement a secure key rotation endpoint protected by admin-only access:
// Example: protected key rotation route (admin only)
// ./src/api/key/controllers/key.js
module.exports = {
async rotateKey(ctx) {
if (!ctx.state.user || ctx.state.user.role !== 'admin') {
ctx.status = 403;
return;
}
const newKey = generateSecureKey(); // implement your own secure generation
await strapi.db.query('plugin::users-permissions.settings').update({
where: {},
data: { apiKey: newKey },
});
ctx.body = { rotated: true };
},
};
Embed and integration safety
If you embed Strapi content in third-party applications, use postMessage with strict origin checks and avoid embedding admin routes in iframes. For public content, create read-only tokens or proxy endpoints that enforce referrer and CSP policies rather than exposing Api Keys directly to browser contexts.