HIGH replay attackfeathersjsdynamodb

Replay Attack in Feathersjs with Dynamodb

Replay Attack in Feathersjs with Dynamodb — how this specific combination creates or exposes the vulnerability

A replay attack occurs when an attacker intercepts a valid request and retransmits it to reproduce the intended effect. In a Feathersjs application backed by DynamoDB, risk arises at the intersection of an always-available HTTP endpoint, an idempotent API surface, and the persistence guarantees of DynamoDB. Feathersjs is convention-driven and often exposes REST or Socket.io services automatically. If routes such as POST /users or POST /orders are reachable unauthenticated or with static/weak tokens, an attacker can capture a request—such as creating a payment record or elevating permissions—and replay it to produce duplicate side effects.

DynamoDB does not prevent duplicate writes by default; once a PutItem or UpdateItem succeeds, the state change is durable. Without application-level nonces or idempotency keys, there is little to distinguish a legitimate repeat submission from a replay. Caching layers or client retries can further amplify the issue. For example, a client that retries on network timeouts may unintentionally create multiple resources if the original request succeeded but the response was lost. Because Feathersjs can expose generic CRUD endpoints, these patterns are common unless explicitly constrained. The framework also allows custom hooks where missing idempotency checks or missing replay detection create exploitable windows.

Consider a payments endpoint implemented as a Feathers service that writes to DynamoDB. A captured POST with a payload including a transaction amount and a user identifier can be replayed to generate fraudulent charges. Because DynamoDB retains each write, duplicates are preserved unless the service enforces uniqueness constraints. The risk is especially acute when combined with other findings such as insufficient authentication or missing rate limiting, which reduce the cost for an attacker to probe and reuse requests.

Dynamodb-Specific Remediation in Feathersjs — concrete code fixes

Remediation focuses on ensuring that each logical operation is uniquely identifiable and that duplicate processing is safely handled. Implement client-supplied idempotency tokens and validate them against DynamoDB before performing writes. Use conditional writes to enforce uniqueness and leverage DynamoDB attributes as deduplication anchors.

Example: idempotent create using a client-provided token stored in DynamoDB with a conditional put.

const AWS = require('aws-sdk');
const dynamo = new AWS.DynamoDB.DocumentClient();

async function createIdempotentOrder(orderId, userId, amount) {
  const params = {
    TableName: 'orders',
    Item: {
      orderId,
      userId,
      amount,
      createdAt: new Date().toISOString()
    },
    ConditionExpression: 'attribute_not_exists(orderId)'
  };

  try {
    await dynamo.put(params).promise();
    return { accepted: true, orderId };
  } catch (err) {
    if (err.code === 'ConditionalCheckFailedException') {
      // Duplicate token: safe to return the existing record
      const existing = await dynamo.get({
        TableName: 'orders',
        Key: { orderId }
      }).promise();
      return { accepted: false, existing: existing.Item };
    }
    throw err;
  }
}

// Feathers service hook example
const { iff, isProvider } = require('feathers-hooks-common');
const hooks = require('feathers-hooks');

app.service('orders').hooks({
  before: {
    create: [hooks.iff(
      isProvider('external'),
      async context => {
        const idempotencyToken = context.params.headers['Idempotency-Token'];
        if (!idempotencyToken) {
          throw new Error('Idempotency-Token header is required');
        }
        const safeToken = String(idempotencyToken).substring(0, 64);
        const result = await createIdempotentOrder(
          safeToken,
          context.data.userId,
          context.data.amount
        );
        if (!result.accepted) {
          context.result = result.existing;
          context.method = 'GET';
          context.statusCode = 200;
        } else {
          context.result = result;
        }
        context.idempotencyHandled = true;
      }
    )]
  }
});

Example: enforcing uniqueness on business keys via DynamoDB secondary indexes.

const params = {
  TableName: 'users',
  Item: {
    userId: 'u-123',
    email: 'user@example.com',
    createdAt: new Date().toISOString()
  },
  ConditionExpression: 'attribute_not_exists(email)'
};

await dynamo.put(params).promise();

Example: time-bound replay detection using TTL to auto-expire tokens.

const params = {
  TableName: 'idempotency',
  Item: {
    token: safeToken,
    userId: 'u-123',
    expiresAt: Math.floor(Date.now() / 1000) + 3600 // 1 hour TTL
  },
  ConditionExpression: 'attribute_not_exists(token)'
};

await dynamo.put(params).promise();

In Feathersjs, combine these patterns with route security: require authentication for mutating endpoints, validate input against schemas, and apply per-method rate limits. Middleware should inspect idempotency tokens for safe methods and ensure that duplicate detection logic aligns with your consistency model. The DynamoDB conditional writes and TTL-driven cleanup provide practical mechanisms to reduce the window for successful replay attacks without changing the core Feathersjs service definitions.

Frequently Asked Questions

Does DynamoDB prevent replay attacks by default?
No. DynamoDB persists each write by default and does not include built-in replay or idempotency controls. You must enforce uniqueness (e.g., with conditional writes on idempotency tokens or unique business keys) and manage deduplication in your application logic.
What is a practical idempotency token strategy for Feathersjs services backed by DynamoDB?
Require a client-supplied Idempotency-Token header on mutating requests. Store the token in DynamoDB with a ConditionExpression that rejects duplicates; use TTL to auto-expire tokens. Return the existing record if a duplicate is detected, ensuring safe retries without double side effects.