HIGH ssrffeathersjsdynamodb

Ssrf in Feathersjs with Dynamodb

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

Server-Side Request Forgery (SSRF) in a FeathersJS service that uses DynamoDB can occur when an attacker is able to influence a URL or host used by the service before it makes an HTTP request, and the service runs in an environment that permits outbound network calls. Although DynamoDB itself is a managed AWS database and not an HTTP-callout target, SSRF arises at the application layer when FeathersJS code (or an integration such as an HTTP hook or external REST client) uses untrusted input to construct requests to external endpoints.

In FeathersJS, services are typically defined with a Service class that implements find, get, create, and update. If a service or hook receives user-supplied data (e.g., from query parameters, body, or authentication metadata) and uses it to form a URL for an outbound HTTP request—such as fetching a remote resource, validating a webhook, or calling a third-party API—an attacker can supply a malicious hostname or IP (e.g., 169.254.169.254 for IMDS, internal services, or private endpoints). This can lead to data exposure from internal metadata services, SSRF-based port scanning, or bypassing network-level restrictions.

A concrete example in FeathersJS with DynamoDB might involve a service that retrieves an item by ID and then fetches additional data from an external URL provided by the client:

// services/external-data/external-data.service.js
const { Service } = require('feathersjs');
const axios = require('axios');

class ExternalDataService extends Service {
  async get(id, params) {
    const item = await super.get(id);
    // Risky: attacker-controlled URL from item.externalUrl or params.query.url
    const response = await axios.get(item.externalUrl || params.query.url);
    return { item, metadata: response.data };
  }
}

module.exports = function () {
  const app = this;
  app.use('/external-data', new ExternalDataService({
    Model: /* some model */,
    paginate: { default: 10, max: 25 }
  }));
};

If item.externalUrl or params.query.url is attacker-controlled and not strictly validated, an SSRF vulnerability exists. In environments where the FeathersJS app runs with access to AWS metadata service (e.g., on EC2 with an over-permissive IAM role), an attacker could attempt to reach 169.254.169.254 to extract instance credentials. Even when DynamoDB is the primary data store, SSRF pivots through the application layer, not the database layer.

Another scenario involves webhook integrations or notification services within FeathersJS that post user-defined URLs to external endpoints. If a user can supply the webhook target, and the service does not enforce a strict allowlist of domains or validate the hostname, the service can be used to probe internal networks or exploit trust relationships.

Because middleBrick scans the unauthenticated attack surface and includes SSRF among its 12 parallel security checks, it can surface these risks when external URL inputs are detected in API definitions or runtime behavior. The scanner cross-references OpenAPI specs and runtime findings, helping to highlight endpoints where untrusted input reaches network calls.

Dynamodb-Specific Remediation in Feathersjs — concrete code fixes

Remediation focuses on strict input validation, disallowing untrusted URLs in outbound requests, and ensuring DynamoDB operations remain isolated to authorized data access. Below are concrete, safe patterns for FeathersJS services that interact with DynamoDB using the AWS SDK.

1. Validate and restrict external URLs

If your service must accept a URL, use an explicit allowlist of domains and reject any non-whitelisted hosts. Do not rely on client-supplied hostnames for outbound requests.

const allowedHosts = ['api.example.com', 'data.example.org'];

function isAllowedHost(url) {
  try {
    const u = new URL(url);
    return allowedHosts.includes(u.hostname);
  } catch (err) {
    return false;
  }
}

// In your service method
if (!isAllowedExternalUrl(params.query.externalUrl)) {
  throw new Error('External URL not allowed');
}

2. Use parameterized DynamoDB operations instead of dynamic HTTP calls

Keep data access within controlled DynamoDB calls. Avoid using user input to construct arbitrary HTTP requests when DynamoDB can serve the use case.

const { DynamoDBDocumentClient, GetCommand } = require('@aws-sdk/lib-dynamodb');
const { ddbDocClient } = require('./ddbClient'); // configured DynamoDB client

class SafeDataService {
  async get(id) {
    const cmd = new GetCommand({
      TableName: process.env.DYNAMO_TABLE,
      Key: { id }
    });
    const { Item } = await ddbDocClient.send(cmd);
    if (!Item) {
      throw new Error('Not found');
    }
    return Item;
  }
}

module.exports = function () {
  const app = this;
  app.use('/safe-data', new SafeDataService({
    Model: /* omitted; using DynamoDBDocumentClient */,
    paginate: false
  }));
};

3. Harden service hooks and disable unnecessary transports

In FeathersJS hooks, sanitize and validate all external inputs before they reach service methods. Do not pass raw user data to network operations.

const { iff, isProvider } = require('feathers-hooks-common');

app.use('/external-data', new ExternalDataService({ /* options */ }));

app.service('external-data').hooks({
  before: {
    all: [],
    find: [iff(isProvider('external'), validateExternalQuery)],
    get: [validateId],
    create: [sanitizeExternalUrl],
    update: [validateExternalUrl],
    patch: [validateExternalUrl],
    remove: []
  },
  after: {},
  error: {}
});

function validateExternalHook(context) {
  const { url } = context.data || {};
  if (url && !isAllowedHost(url)) {
    throw new Error('Invalid external host');
  }
  return context;
}

4. AWS SDK configuration and credential safety

Ensure DynamoDB clients use least-privilege IAM roles and do not expose credentials via environment variables that can be exfiltrated through SSRF. Avoid logging raw requests that may include sensitive tokens.

// ddbClient.js
const { DynamoDBDocumentClient } = require('@aws-sdk/lib-dynamodb');
const { fromNodeProviderChain } = require('@aws-sdk/credential-providers');

const ddbDocClient = DynamoDBDocumentClient.from(
  new S3Client({
    region: process.env.AWS_REGION,
    credentials: fromNodeProviderChain()
  })
);

module.exports = { ddbDocClient };

These patterns ensure that FeathersJS with DynamoDB remains resilient against SSRF by eliminating reliance on untrusted URLs for outbound calls, strictly validating inputs, and keeping data access within authorized AWS SDK operations.

Related CWEs: ssrf

CWE IDNameSeverity
CWE-918Server-Side Request Forgery (SSRF) CRITICAL
CWE-441Unintended Proxy or Intermediary (Confused Deputy) HIGH

Frequently Asked Questions

Can middleBrick detect SSRF in a FeathersJS API that uses DynamoDB?
Yes. middleBrick scans unauthenticated attack surfaces and includes SSRF among its 12 parallel checks. It cross-references OpenAPI specs with runtime findings to highlight endpoints where untrusted input reaches network operations, including cases where external URLs are used in FeathersJS services.
Does middleBrick fix SSRF findings in DynamoDB integrations?
middleBrick detects and reports findings with severity and remediation guidance. It does not fix, patch, block, or remediate. You should apply input validation and restrict outbound URLs as shown in the remediation examples.