MEDIUM clickjackingstrapidynamodb

Clickjacking in Strapi with Dynamodb

Clickjacking in Strapi with DynamoDB — how this specific combination creates or exposes the vulnerability

Clickjacking is a client-side attack where an attacker tricks a user into clicking UI elements that are invisible or disguised within an embedded frame. In Strapi, content editors and administrators use the admin panel to manage entries stored in DynamoDB. If these admin pages are embedded inside an <iframe> without proper protections, a malicious site can overlay invisible controls or misleading prompts, causing an authenticated editor to inadvertently publish, delete, or update entries in DynamoDB.

Strapi does not enforce a Content Security Policy (CSP) by default, and its admin UI (React-based) is typically served at /admin. When this route is reachable within an iframe, the combination of an active DynamoDB-backed content type and insufficient frame-embedding controls enables clickjacking. An attacker can craft a page like <iframe src="https://example.com/admin" style="opacity:0;position:absolute"></iframe>. Because DynamoDB stores the actual content, changes triggered via the admin UI directly mutate database records. The risk is higher when predictable admin routes are used and session cookies are not protected with SameSite and Secure attributes, allowing the forged request to be automatically sent with valid credentials.

To assess this specific combination, middleBrick scans unauthenticated attack surfaces and flags missing anti-clickjacking headers as a finding under the UI Security checks. It does not test authentication mechanisms or prompt users to log in, but it verifies whether response headers and CSP directives reduce the feasibility of embedding Strapi admin pages in hostile contexts. Remediation focuses on server-side HTTP headers and client-side frame-busting considerations, without altering how Strapi persists data to DynamoDB.

DynamoDB-Specific Remediation in Strapi — concrete code fixes

Remediation for clickjacking does not require changes to DynamoDB data structures; it centers on HTTP response headers and secure iframe handling. Configure Strapi to emit Content-Security-Policy with frame-ancestors that disallow embedding, and ensure cookies are protected. Below are actionable steps and DynamoDB-integrated code examples to maintain secure data operations while mitigating clickjacking.

1. Set CSP and X-Frame-Options in Strapi

In your Strapi project, extend the server HTTP middleware to add security headers. This ensures browsers refuse to render Strapi admin pages inside iframes, breaking clickjacking attempts.

// ./src/middlewares/security-headers.js
module.exports = (config, { strapi }) => {
  return async (ctx, next) => {
    ctx.response.set({
      'Content-Security-Policy': "frame-ancestors 'none'",
      'X-Frame-Options': 'DENY',
      'X-Content-Type-Options': 'nosniff',
    });
    await next();
  };
};

Register the middleware in ./src/middlewares/index.js:

// ./src/middlewares/index.js
module.exports = [
  'strapi::errors',
  { name: 'security-headers', config: {} },
  'strapi::security',
  'strapi::cors',
  'strapi::powered-by',
  'strapi::logger',
  'strapi::query',
  'strapi::body',
  'strapi::favicon',
  'strapi::public',
];

2. Secure DynamoDB interactions with SDK and validation

Even with headers in place, ensure that DynamoDB operations follow least privilege and validate inputs to prevent unintended mutations if an attacker bypasses UI layers. Below is a secure example using the AWS SDK for JavaScript v3 within a custom Strapi controller.

// ./src/api/article/controllers/article.js
'use strict';
const { DynamoDBClient, GetItemCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
const { marshall, unmarshall } = require('@aws-sdk/util-dynamodb');

module.exports = {
  async findOne(ctx) {
    const { id } = ctx.params;
    const client = new DynamoDBClient({ region: process.env.AWS_REGION });
    const command = new GetItemCommand({
      TableName: process.env.DYNAMODB_TABLE,
      Key: marshall({ slug: id }),
    });
    try {
      const data = await client.send(command);
      if (!data.Item) {
        return ctx.notFound();
      }
      ctx.body = unmarshall(data.Item);
    } catch (err) {
      ctx.throw(500, err.message);
    }
  },
  async update(ctx) {
    const { id } = ctx.params;
    const safeData = ctx.request.body;
    // Validate and sanitize safeData fields before passing to DynamoDB
    if (!safeData.published || typeof safeData.published !== 'boolean') {
      return ctx.badRequest('Invalid published value');
    }
    const client = new DynamoDBClient({ region: process.env.AWS_REGION });
    const command = new UpdateItemCommand({
      TableName: process.env.DYNAMODB_TABLE,
      Key: marshall({ slug: id }),
      UpdateExpression: 'SET published = :pub',
      ConditionExpression: 'attribute_exists(slug)',
      ExpressionAttributeValues: marshall({ ':pub': { BOOL: safeData.published } }),
      ReturnValues: 'UPDATED_NEW',
    });
    try {
      const data = await client.send(command);
      ctx.body = unmarshall(data.Attributes);
    } catch (err) {
      if (err.name === 'ConditionalCheckFailedException') {
        return ctx.notFound();
      }
      ctx.throw(500, err.message);
    }
  },
};

3. Enforce SameSite and Secure cookie attributes

Ensure session cookies are not sent on cross-site requests by configuring Strapi’s cookie settings in ./config/middle.js.

// ./config/middle.js
module.exports = {
  settings: {
    session: {
      cookie: {
        httpOnly: true,
        secure: process.env.NODE_ENV === 'production',
        sameSite: 'strict',
        path: '/',
      },
    },
  },
};

4. Validate origins for API endpoints used by the admin

If Strapi admin makes cross-origin requests to DynamoDB-backed endpoints, enforce CORS strictly to prevent injection of malicious origins that could facilitate UI redressing.

// ./config/middle.js (CORS)
module.exports = {
  settings: {
    cors: {
      enabled: true,
      origin: ['https://your-trusted-admin.com'],
      headers: ['Content-Type', 'Authorization'],
      credentials: true,
    },
  },
};

These measures reduce the attack surface for clickjacking against Strapi while preserving the integrity of DynamoDB-backed content. Security headers act as the primary defense, while secure coding practices around DynamoDB interactions ensure that even if UI layers are bypassed, data operations remain constrained.

Frequently Asked Questions

Does middleBrick test for clickjacking in Strapi integrations?
Yes, middleBrick checks for missing anti-clickjacking headers such as Content-Security-Policy frame-ancestors and X-Frame-Options in its security scans. It evaluates the HTTP responses serving Strapi admin pages and reports whether embedding is allowed, helping you assess clickjacking risk for DynamoDB-backed content without testing authentication.
Can DynamoDB configuration affect clickjacking risk?
DynamoDB itself does not introduce clickjacking; the risk comes from how Strapi serves admin pages that interact with DynamoDB. Securing headers and CSP are server-side controls. Use middleBrick scans to verify that your Strapi endpoints do not permit framing, regardless of the underlying DynamoDB configuration.