HIGH unicode normalizationfeathersjsapi keys

Unicode Normalization in Feathersjs with Api Keys

Unicode Normalization in Feathersjs with Api Keys — how this specific combination creates or exposes the vulnerability

Unicode normalization inconsistencies arise when Feathersjs applications compare or index API keys without normalizing input strings. API keys are often transmitted as query parameters, headers, or cookie values. If an API key contains Unicode characters or is submitted in a non-canonical form (e.g., composed vs. decomposed), a comparison that does not normalize both sides can yield mismatches or, worse, accept a visually identical but different key. This can lead to authentication bypass or privilege confusion.

In Feathersjs, services typically retrieve keys via params.query.key or params.headers.authorization. If the application stores canonical API keys in a database (e.g., NFC form) but does not normalize incoming values before comparison, an attacker can supply a visually equivalent key in a different normalization form to bypass checks. For example, the character sequence café can be represented as U+00E9 (LATIN SMALL LETTER E WITH ACUTE) or as the decomposed sequence c + á (U+0061 + combining acute). Without normalization, these are distinct code points and may not match the stored key, but an attacker can still gain access if the comparison logic is not robust.

Exploiting this in the context of API keys often involves a crafted request that includes a non-canonical key in an Authorization header or a query parameter. Because Feathersjs may rely on custom hooks or authentication middleware to validate keys, inconsistent normalization can lead to incorrect acceptance. This is especially risky when logging or error messages inadvertently reflect the raw key, enabling leakage via output channels. Combined with the LLM/AI Security checks in middleBrick, which detect system prompt leakage and output PII, such weaknesses can amplify information exposure if malformed keys trigger verbose responses.

Middleware that performs normalization must be applied before any key comparison. For example, using the unorm library to normalize incoming parameters ensures that visually identical keys are treated identically. Failing to do so means that even with API key authentication in place, the effective security boundary is weakened due to representation ambiguity.

Api Keys-Specific Remediation in Feathersjs — concrete code fixes

Remediation centers on normalizing API keys before storage and before comparison. Use a consistent Unicode form (typically NFC) for storage and apply the same normalization to every incoming key. In Feathersjs, this can be implemented in an authentication hook so that all services benefit from the protection.

Example of vulnerable code that compares raw keys:

// DO NOT DO THIS — vulnerable to Unicode confusion
app.service('api-keys').hooks({
  before: {
    create: [context => {
      const rawKey = context.params.query.key;
      const storedKey = lookupKeyInDatabase(context.params.account.id);
      if (rawKey !== storedKey) {
        throw new Error('Unauthorized');
      }
      return context;
    }]
  }
});

Example of remediated code using normalization:

const unorm = require('unorm');

app.service('api-keys').hooks({
  before: {
    create: [context => {
      const incomingKey = unorm.nfkc(context.params.query.key);
      const storedKey = unorm.nfkc(lookupKeyFromSecureStore(context.params.account.id));
      if (incomingKey !== storedKey) {
        throw new Error('Unauthorized');
      }
      return context;
    }]
  }
});

For token-based schemes where keys are passed in headers, normalize the header value before validation:

app.service('auth').hooks({
  before: {
    all: [context => {
      const authHeader = context.params.headers.authorization || '';
      const normalized = unorm.nfkc(authHeader.trim());
      if (!isValidKey(normalized)) {
        throw new Error('Invalid API key');
      }
      context.params.apiKey = normalized;
      return context;
    }]
  }
});

When storing keys, ensure they are normalized at write time as well. If you accept a key from an admin UI or import routine, apply normalization before persisting:

function createKeyRecord(rawKey) {
  const normalizedKey = unorm.nfkc(rawKey);
  // Save normalizedKey to database
  return db.keys.insert({ key: normalizedKey, owner: ... });
}

Additionally, prefer HTTP header transmission over query parameters to reduce accidental leakage in logs. If query parameters are necessary, ensure they are not reflected in error messages or logs without masking. middleBrick’s dashboard and CLI can help identify endpoints where raw keys appear in responses or logs, supporting remediation efforts.

By combining consistent Unicode normalization with disciplined handling of API keys, Feathersjs services reduce the risk of authentication bypass due to encoding tricks. The Pro plan’s continuous monitoring can alert on irregularities, while the GitHub Action can enforce checks in CI/CD pipelines to prevent regressions.

Frequently Asked Questions

Why is Unicode normalization relevant for API key validation in Feathersjs?
Because visually identical keys can have different code point representations; comparing without normalization can allow bypasses.
Does middleBrick help detect normalization-related issues in API key handling?
Yes; the scanner’s findings can highlight inconsistencies in authentication and input validation that may indicate normalization risks.