HIGH cross site request forgeryadonisjsdynamodb

Cross Site Request Forgery in Adonisjs with Dynamodb

Cross Site Request Forgery in Adonisjs with Dynamodb

Cross-Site Request Forgery (CSRF) in an AdonisJS application that uses DynamoDB as a persistence layer arises from the framework’s session and request-handling behavior combined with how state-changing routes interact with authenticated DynamoDB operations. AdonisJS does not enable CSRF protection by default for APIs, and if session-based authentication or cookie-based sessions are used without explicit CSRF safeguards, a forged request from a malicious site can execute privileged DynamoDB actions on behalf of a logged-in user.

Consider an endpoint that deletes a DynamoDB item identified by a user-controlled id parameter. If the route relies on session cookies for authentication and does not validate the origin of the request, an attacker can craft a form on a malicious domain that submits a DELETE request to that endpoint. Because cookies are sent automatically by the browser, the request will be authenticated, and the unprotected route will invoke the AWS SDK to call deleteItem on the DynamoDB table, acting on the authenticated user’s behalf without their consent.

In this stack, the risk is not in DynamoDB itself, which is a stateless data store, but in the application layer that translates HTTP requests into DynamoDB operations. If authorization checks are incomplete (for example, verifying that a resource belongs to the requester only at read time) and CSRF protections are omitted, an attacker can induce state changes such as updating user preferences, changing emails, or deleting records. The DynamoDB calls made by AdonisJS—such as deleteItem, updateItem, or conditional writes—will execute with the permissions attached to the SDK client, often with broad privileges if the client is misconfigured.

For example, an AdonisJS controller might directly use the DynamoDB DocumentClient to remove a record:

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import { DynamoDBDocumentClient, DeleteCommand } from '@aws-sdk/lib-dynamodb'
import { ddbClient } from 'App/Services/AwsClient'

export default class ItemsController {
  public async destroy({ request, params, auth }: HttpContextContract) {
    const itemId = params.id
    // Missing: origin check, CSRF token validation, ownership verification beyond existence
    const client = DynamoDBDocumentClient.from(ddbClient)
    const command = new DeleteCommand({
      TableName: process.env.DYNAMODB_TABLE,
      Key: { id: itemId }
    })
    await client.send(command)
    return { deleted: itemId }
  }
}

In this snippet, there is no CSRF token verification, no origin header validation, and no check that the authenticated user is allowed to delete this specific item beyond a basic existence check. If an attacker tricks a victim’s browser into submitting a request to this route, the DynamoDB delete will proceed because the session cookie is valid and the route does not enforce anti-CSRF measures.

Additionally, if the application uses API tokens stored in cookies or if it relies on GET requests for state-changing operations, the exposure is further amplified. GET requests should never change state, and tokens stored in cookies without the SameSite attribute and Secure flag are more susceptible to being included in forged requests. Proper defenses in this AdonisJS + DynamoDB context include synchronous CSRF token validation for state-changing methods, strict origin and referer checks, and ensuring that each DynamoDB mutation verifies resource ownership within the business logic.

Dynamodb-Specific Remediation in Adonisjs

Remediation focuses on ensuring that every request that results in a DynamoDB mutation is authenticated, authorized, and verified as intentional. In AdonisJS, this means combining framework-level protections with careful design around DynamoDB calls.

  • Enable CSRF protection for session-based routes: Use AdonisJS built-in CSRF middleware for web forms and ensure it is applied to routes that perform state-changing DynamoDB operations.
  • Validate the request origin and referer header for sensitive operations, rejecting requests that do not match your trusted origins.
  • Include ownership checks in your DynamoDB calls by filtering on the user’s identifier (e.g., userId) as part of the key condition or filter expression, ensuring that a user can only modify their own items.
  • Avoid exposing raw DynamoDB keys in URLs or forms; use indirect references and map them to internal IDs server-side.
  • Use the AWS SDK’s DeleteCommand, UpdateCommand, and conditional expressions to enforce fine-grained control and avoid accidental overwrites.

Concrete code example with CSRF-like origin checks and ownership verification before invoking DynamoDB:

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import { DynamoDBDocumentClient, DeleteCommand, UpdateCommand } from '@aws-sdk/lib-dynamodb'
import { ddbClient } from 'App/Services/AwsClient'

export default class ItemsController {
  public async destroy({ request, params, auth, response }: HttpContextContract) {
    const itemId = params.id
    const user = auth.getUserOrFail()

    // Origin check (example for browser-based clients)
    const origin = request.headers().origin
    if (!origin || !origin.startsWith('https://your-trusted-domain.com')) {
      return response.badRequest({ error: 'Invalid origin' })
    }

    const client = DynamoDBDocumentClient.from(ddbClient)
    // First ensure the item exists and belongs to the user
    const getItemCmd = new GetCommand({
      TableName: process.env.DYNAMODB_TABLE,
      Key: { id: itemId }
    })
    const item = await client.send(getItemCmd)
    if (!item || item.userId !== user.id) {
      return response.unauthorized({ error: 'Item not found or unauthorized' })
    }

    const command = new DeleteCommand({
      TableName: process.env.DYNAMODB_TABLE,
      Key: { id: itemId }
    })
    await client.send(command)
    return { deleted: itemId }
  }

  public async update({ request, params, auth, response }: HttpContextContract) {
    const itemId = params.id
    const user = auth.getUserOrFail()
    const body = request.only(['name', 'status'])

    const origin = request.headers().origin
    if (!origin || !origin.startsWith('https://your-trusted-domain.com')) {
      return response.badRequest({ error: 'Invalid origin' })
    }

    const client = DynamoDBDocumentClient.from(ddbClient)
    // Ownership check with a conditional update
    const command = new UpdateCommand({
      TableName: process.env.DYNAMODB_TABLE,
      Key: { id: itemId },
      UpdateExpression: 'set #name = :name, #status = :status',
      ConditionExpression: 'userId = :userId',
      ExpressionAttributeNames: { '#name': 'name', '#status': 'status' },
      ExpressionAttributeValues: {
        ':name': body.name,
        ':status': body.status,
        ':userId': user.id
      }
    })
    try {
      await client.send(command)
      return { updated: itemId }
    } catch (err) {
      // Conditional check failed -> item does not belong to user or was concurrently modified
      return response.forbidden({ error: 'Update condition failed' })
    }
  }
}

These examples show how to integrate origin validation and ownership checks directly before each DynamoDB operation. For web UI flows, integrate CSRF tokens via AdonisJS’s CSRF provider; for API flows, consider double-submit cookie patterns or anti-CSRF headers. Always prefer POST, PUT, DELETE, or PATCH for mutations and ensure that GET requests never trigger DynamoDB writes.

Leverage the middleBrick CLI to scan your AdonisJS endpoints and surface missing CSRF and authorization findings. The dashboard can track your API security scores over time, and the Pro plan supports continuous monitoring and GitHub Action integration to fail builds if risk thresholds are exceeded. The MCP Server allows you to scan APIs directly from your AI coding assistant, helping catch insecure patterns before they reach production.

Frequently Asked Questions

Does DynamoDB cause CSRF, and what is its role in this risk?
DynamoDB does not cause CSRF; it is a stateless data store. The risk occurs in the application layer (AdonisJS) that translates HTTP requests into DynamoDB operations. If an endpoint performs state-changing DynamoDB calls without CSRF or origin checks, a forged request can induce unauthorized mutations.
How can I test for CSRF in an AdonisJS + DynamoDB API?
Use the middleBrick CLI to scan your endpoints: run middlebrick scan . The scanner will test for missing CSRF protections and report findings with remediation guidance. Combine this with manual testing by crafting cross-origin requests to mutation endpoints and verifying that origin checks and CSRF tokens are enforced.