MEDIUM clickjackingexpressdynamodb

Clickjacking in Express with Dynamodb

Clickjacking in Express with Dynamodb — how this specific combination creates or exposes the vulnerability

Clickjacking is a client-side UI redress attack where an attacker tricks a user into clicking or interacting with a hidden or disguised element inside an invisible or overlaying page. In an Express application that reads data from DynamoDB, the vulnerability arises not from DynamoDB itself, but from how responses are rendered and framed in HTTP responses. If your Express routes fetch data from DynamoDB and render it in HTML without proper anti-clickjacking protections, an attacker can embed your authenticated pages inside an <iframe> and manipulate user interactions.

Consider an Express route that queries DynamoDB for a user profile and renders a settings page:

app.get('/settings', async (req, res) => {
  const params = {
    TableName: 'users',
    Key: { userId: req.session.userId }
  };
  const user = await dynamodb.get(params).promise();
  res.send(`
    <form action="/update-settings" method="POST">
      <input name="theme" value="${user.Theme || 'light'}">
      <button>Save</button>
    </form>
  `);
});

If this page is served without a Content-Security-Policy frame-ancestors directive or an X-Frame-Options header, an attacker can craft a page that loads /settings inside a transparent iframe and overlay hidden controls on top of it. The DynamoDB read is safe, but the rendered HTML lacks frame-busting or framing controls, enabling clickjacking. Additionally, if the Express app embeds sensitive DynamoDB data (such as permissions or tokens) in the page without proper isolation, an attacker can leverage clickjacking to make users perform unintended state changes, such as updating their email or changing privacy settings via POST endpoints that also rely on the same DynamoDB data.

Another scenario involves dynamic URLs or query parameters used to fetch items from DynamoDB. If an endpoint reflects user-controlled input without validation and renders it in a page that can be framed, clickjacking becomes more plausible. For example, an endpoint like /profile?userId=attacker-controlled could be abused to render a page the attacker controls inside an iframe, especially if the app shares session tokens or authorization checks are inconsistent. The risk is compounded when the same-origin policy is not enforced strictly or when CORS allows broader origins than necessary.

To detect this using middleBrick, you can scan your Express endpoints (including those that query DynamoDB) without authentication. The scanner checks whether critical pages include anti-framing headers and whether sensitive actions are exposed to embedding. This helps identify missing X-Frame-Options or weak Content-Security-Policy frame-ancestors rules that enable clickjacking in pages backed by DynamoDB data.

Dynamodb-Specific Remediation in Express — concrete code fixes

Remediation focuses on preventing your pages from being embedded and ensuring that sensitive DynamoDB-rendered content cannot be interacted with by unauthorized frames. Below are concrete Express code fixes that you can apply alongside your DynamoDB integration.

1. Set anti-framing headers

Add middleware that sets X-Frame-Options and Content-Security-Policy frame-ancestors for all responses that render pages reading from DynamoDB.

// Express middleware to prevent clickjacking
app.use((req, res, next) => {
  res.setHeader('X-Frame-Options', 'DENY');
  res.setHeader(
    'Content-Security-Policy',
    "default-src 'self'; frame-ancestors 'none'"
  );
  next();
});

If you need to allow specific trusted domains to embed (rare for user settings), use a dynamic CSP instead of DENY, but prefer DENY for pages that render sensitive DynamoDB data.

2. Validate and sanitize DynamoDB responses before rendering

Ensure that data fetched from DynamoDB is properly escaped and not directly interpolated into HTML attributes or event handlers. Use a templating engine with auto-escaping or escape HTML characters explicitly.

const escapeHtml = (unsafe) => {
  if (!unsafe) return '';
  return unsafe.toString()
    .replace(/&/g, '&')
    .replace(//g, '>')
    .replace(/"/g, '"')
    .replace(/'/g, ''');
};

app.get('/settings', async (req, res) => {
  const params = {
    TableName: 'users',
    Key: { userId: req.session.userId }
  };
  const user = await dynamodb.get(params).promise();
  const safeTheme = escapeHtml(user.Item?.theme || 'light');
  res.send(`
    <form action="/update-settings" method="POST">
      <input name="theme" value="${safeTheme}">
      <button>Save</button>
    </form>
  `);
});

3. Separate read and write routes with strict checks

When DynamoDB items influence UI state (e.g., permissions or redirect URLs), ensure that write endpoints perform their own authorization and do not rely solely on client-supplied parameters. Avoid reflecting DynamoDB state directly into action URLs without validation.

app.post('/update-settings', async (req, res) => {
  const { theme } = req.body;
  // Re-validate on the server; do not trust client input
  const sanitizedTheme = ['light', 'dark'].includes(theme) ? theme : 'light';
  const params = {
    TableName: 'users',
    Key: { userId: req.session.userId },
    UpdateExpression: 'set #theme = :t',
    ExpressionAttributeNames: { '#theme': 'theme' },
    ExpressionAttributeValues: { ':t': sanitizedTheme }
  };
  await dynamodb.update(params).promise();
  res.redirect('/settings');
});

middleBrick can scan your Express endpoints to verify whether these headers are present and whether sensitive DynamoDB-rendered pages are improperly framed. Using the CLI (middlebrick scan <url>) or the GitHub Action, you can enforce that new changes do not introduce missing frame protections.

Frequently Asked Questions

Does DynamoDB store or enforce any clickjacking protections?
DynamoDB is a database and does not enforce HTTP protections like X-Frame-Options or Content-Security-Policy. Those must be implemented in your Express application.
Can middleBrick fix clickjacking issues automatically?
middleBrick detects and reports missing anti-framing headers and unsafe rendering patterns. It provides remediation guidance but does not automatically patch or block requests.