HIGH cors wildcardsailshmac signatures

Cors Wildcard in Sails with Hmac Signatures

Cors Wildcard in Sails with Hmac Signatures — how this specific combination creates or exposes the vulnerability

A CORS wildcard in a Sails.js application that also uses Hmac Signatures can expose both authentication and integrity mechanisms when the wildcard is too permissive and the Hmac implementation does not adequately bind the signature to the exact request context. Sails, which runs on top of Express, allows CORS settings via config/cors.js. Setting origin: '*' permits any domain to make browser-based requests that include credentials only when credentials: true is not used; however, when credentials or custom headers are required, a wildcard origin is not allowed by browsers unless the server explicitly reflects the Origin header back in Access-Control-Allow-Origin. This reflection behavior combined with Hmac Signatures can create a cross-site request forgery or signature-reuse scenario if the signature does not cover the full request context.

Hmac Signatures in Sails are typically generated by the client using a shared secret and a canonical representation of the request (method, path, selected headers, and body). A common vulnerability occurs when the server validates the Hmac but does not enforce strict CORS policies, allowing a malicious site to forge requests with known or predictable parameters and have them signed by an authenticated user’s browser. For example, an attacker’s page can issue a POST /transfer request with JSON payload {"to":"attacker","amount":100} and the browser automatically includes cookies or an auth token. If Sails reflects the origin and accepts the request, the Hmac signature computed over the attacker’s chosen data may be accepted as valid, leading to unauthorized actions.

The interaction between CORS wildcard and Hmac Signatures also affects integrity and replay protections. If the signature is computed without including a nonce or a timestamp, an attacker can replay a captured signed request as long as the CORS policy permits the target origin. Because the wildcard does not restrict which origins can send requests, the server may accept the replayed request as legitimate. Moreover, if the Hmac does not cover all relevant headers (e.g., Content-Type or custom headers like X-Request-ID) or does not enforce strict content canonicalization, an attacker might modify non-covered parts of the request without invalidating the signature.

To detect such misconfigurations, middleBrick scans the unauthenticated attack surface of a Sails endpoint and checks whether CORS settings use a wildcard while Hmac validation is present but lacks binding to the full request context. The scan highlights high-risk combinations and provides prioritized findings with severity and remediation guidance, helping teams understand how browser policies and cryptographic integrity checks interact in production environments.

Hmac Signatures-Specific Remediation in Sails — concrete code fixes

Remediation centers on tightening CORS configuration and ensuring Hmac signatures cover the full request context, including method, path, canonical headers, and body. In Sails, CORS settings should avoid wildcards when credentials or custom headers are required. Instead, use a function to reflect a controlled set of origins and explicitly allow only trusted domains.

For Hmac Signatures, adopt a canonical representation that includes the HTTP method, the request path without query parameters, selected headers (e.g., Content-Type, X-Request-Timestamp), and the request body. The server must recompute the Hmac using the shared secret and compare it in constant time to prevent timing attacks. Below are concrete code examples for a Sails hook that computes and validates Hmac Signatures and a CORS configuration that avoids unsafe wildcard usage.

Example: Hmac Signature Generation and Validation in Sails

Client-side code to generate the signature (Node.js):

const crypto = require('crypto');

function computeHmac(secret, method, path, headers, body) {
  const canonicalHeaders = ['content-type', 'x-request-timestamp'].map(h => h + ':' + headers[h.toLowerCase()]).join('|');
  const payload = [method.toUpperCase(), path, canonicalHeaders, body].join('\n');
  return crypto.createHmac('sha256', secret).update(payload).digest('hex');
}

const secret = process.env.HMAC_SECRET;
const method = 'POST';
const path = '/v1/transfer';
const headers = { 'content-type': 'application/json', 'x-request-timestamp': Date.now().toString() };
const body = JSON.stringify({ to: 'recipient', amount: 100 });
const signature = computeHmac(secret, method, path, headers, body);
console.log({ headers: { 'x-signature': signature }, body });

Server-side validation in a Sails hook (e.g., api/hooks/hmac-validation/index.js):

const crypto = require('crypto');

module.exports = function verifyHmac(req, res, next) {
  const secret = process.env.HMAC_SECRET;
  const method = req.method.toUpperCase();
  const path = req.path; // e.g., '/v1/transfer'
  const headers = req.headers;
  const body = req.rawBody || ''; // ensure raw body is available

  const received = headers['x-signature'];
  if (!received) return res.badRequest('Missing signature');

  const canonicalHeaders = ['content-type', 'x-request-timestamp'].map(h => h + ':' + (headers[h.toLowerCase()] || '')).join('|');
  const payload = [method, path, canonicalHeaders, body].join('\n');
  const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex');

  const isValid = timingSafeEqual(expected, received);
  if (!isValid) return res.forbidden('Invalid signature');

  // Optional: reject replay by checking timestamp skew
  const ts = parseInt(headers['x-request-timestamp'], 10);
  if (Math.abs(Date.now() - ts) > 60000) return res.badRequest('Request expired');

  return next();
};

function timingSafeEqual(a, b) {
  if (typeof a !== 'string' || typeof b !== 'string') return false;
  if (a.length !== b.length) return false;
  return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));
}

Example: Secure CORS configuration in Sails (config/cors.js):

module.exports.cors = {
  origin: function(origin, callback) {
    const allowed = ['https://trusted.example.com', 'https://app.example.com'];
    if (allowed.includes(origin)) {
      callback(null, true);
    } else if (!origin) {
      // Allow requests with no origin (e.g., mobile apps, curl)
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  },
  credentials: true,
  exposedHeaders: ['x-request-id'],
  maxAge: 3600
};

Additional measures include ensuring the Hmac covers all headers that affect the request semantics, using short timestamps to prevent replays, and avoiding wildcard origins when authentication and integrity checks are in place. middleBrick’s scans can verify that CORS does not use a wildcard while Hmac validation is present, and that the signature computation includes a robust canonical form, reducing the risk of signature misuse and unauthorized actions.

Related CWEs: dataExposure

CWE IDNameSeverity
CWE-200Exposure of Sensitive Information HIGH
CWE-209Error Information Disclosure MEDIUM
CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
CWE-312Cleartext Storage of Sensitive Information HIGH
CWE-359Exposure of Private Personal Information (PII) HIGH
CWE-522Insufficiently Protected Credentials CRITICAL
CWE-532Insertion of Sensitive Information into Log File MEDIUM
CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
CWE-540Inclusion of Sensitive Information in Source Code HIGH

Frequently Asked Questions

Why is a CORS wildcard risky when Hmac Signatures are used in Sails?
A CORS wildcard allows any origin to make requests; if the server reflects the origin and the Hmac does not bind to the full request context (method, path, canonical headers, body), an attacker can have the browser submit signed requests with attacker-chosen data, bypassing integrity controls.
How can I securely configure CORS and Hmac Signatures in Sails to avoid these risks?
Set CORS origin to a specific list of trusted domains instead of a wildcard, reflect only those origins, and ensure Hmac signatures are computed over method, path, selected headers, and body with a shared secret. Validate signatures with constant-time comparison and optionally reject requests with stale timestamps to prevent replay.