Integrity Failures in Feathersjs with Api Keys
Integrity Failures in Feathersjs with Api Keys — how this specific combination creates or exposes the vulnerability
FeathersJS is a framework for real-time web applications and REST APIs. When using API keys for service-to-service access, integrity failures occur when the framework does not enforce strict validation, scope checks, or replay protections on the key itself or on the requests it authorizes. An integrity failure means an attacker can tamper with an otherwise valid API key or its associated permissions and gain unauthorized operations.
In FeathersJS, integrity failures with API keys often stem from three patterns. First, keys are accepted as a bearer token without verifying scope, intended action, or resource ownership. Second, the server may trust client-supplied key metadata (such as an embedded role or tenant ID) without re-verification against a trusted store. Third, the service may not enforce idempotency or replay protections, allowing a captured key and request to be reused to alter data or escalate impact.
Consider a typical FeathersJS service that relies on an API key passed via an Authorization header. If the key is used only to authenticate the client but the service then applies permissions based on mutable user-supplied fields (e.g., role in the payload), an attacker can modify those fields to elevate privileges. This becomes an integrity issue because the authorization decision depends on data that the client can influence rather than on server-side, cryptographically verifiable attributes of the key.
Additionally, FeathersJS hooks that dynamically modify queries based on the key’s metadata can introduce integrity failures when the metadata is not validated against a trusted source. For example, an API key might embed a tenant identifier; if the server uses that identifier directly to filter data without verifying it against a server-managed mapping, an attacker can change the identifier in transit or via a manipulated request and access another tenant’s resources.
Real-world attack patterns mirror these risks. An attacker may attempt to exploit weak integrity by tampering with tokens, replaying requests to perform unintended mutations (such as modifying or deleting records), or leveraging overly permissive key scopes described in the service’s OpenAPI contract. These behaviors align with OWASP API Top 10 controls related to broken object-level authorization and insufficient security controls around service identities.
In regulated contexts, such weaknesses can map to compliance concerns under frameworks like PCI-DSS and SOC 2, where integrity of authentication and authorization decisions is required. middleBrick’s LLM/AI Security checks and standard authentication and authorization scans can detect scenarios where API keys are accepted without sufficient integrity enforcement, providing prioritized findings and remediation guidance.
Api Keys-Specific Remediation in Feathersjs — concrete code fixes
Remediation focuses on ensuring that API keys are treated as non‑mutable, server‑validated credentials and that all decisions based on them are verified independently of client‑supplied data.
- Validate API keys against a trusted store on every request and do not trust any claims embedded in the payload or headers supplied by the client.
- Enforce scope-based authorization server-side, binding allowed operations explicitly to the key rather than inferring permissions from mutable user-controlled fields.
- Use constant-time comparison for key validation and implement replay protections such as nonce or request-id tracking where applicable.
Example: Secure API key validation in a FeathersJS service file.
// src/services/secure-data/secure-data.service.js
const crypto = require('crypto');
// Trusted store lookup (replace with your actual key management)
const trustedKeys = new Map([
['ak_live_abc123', { scope: 'data:read', tenantId: 'tenant-a' }],
['ak_live_xyz789', { scope: 'data:write', tenantId: 'tenant-b' }]
]);
function verifyApiKey(rawKey) {
if (!rawKey || !trustedKeys.has(rawKey)) {
return null;
}
// Use constant-time comparison to avoid timing attacks
const expectedKey = Array.from(trustedKeys.keys()).find(k => crypto.timingSafeEqual(Buffer.from(k), Buffer.from(rawKey)));
return expectedKey ? trustedKeys.get(expectedKey) : null;
}
module.exports = function (app) {
const apiKeys = app.get('apiKeys'); // could be a service or a Map
app.before(async (context) => {
const { headers } = context.params;
const key = headers && headers['x-api-key'];
const keyMeta = verifyApiKey(key);
if (!keyMeta) {
throw new app.errors.NotAuthenticated('Invalid or missing API key');
}
// Bind server-side metadata to the context, never trust the client
context.params.apiKeyMeta = keyMeta;
});
app.after(hooks => ({
async removeSensitiveData(context) {
// Ensure no key material leaks in responses
if (context.result && context.result.data) {
// sanitize if needed
}
}
}));
};
Example: Enforce scope and tenant integrity within a FeathersJS hook.
// src/hooks/require-scope.js
module.exports = function requireScope(requiredScope) {
return async context => {
const { apiKeyMeta } = context.params;
if (!apiKeyMeta) {
throw new context.app.errors.Forbidden('API key metadata missing');
}
// Scope-based integrity check
if (apiKeyMeta.scope !== requiredScope) {
throw new context.app.errors.Forbidden(`Insufficient scope. Required: ${requiredScope}`);
}
// Example: Ensure tenantId matches the resource being accessed
if (context.method === 'create' || context.method === 'get') {
const resourceTenant = context.data && context.data.tenantId;
if (resourceTenant && resourceTenant !== apiKeyMeta.tenantId) {
throw new context.app.errors.Forbidden('Tenant mismatch');
}
}
return context;
};
};
// Usage in a service configuration
const hooks = require('./hooks');
app.use('/secure-data', require('./services/secure-data/secure-data.service.js'));
app.service('secure-data').hooks({
before: {
all: [hooks.requireScope('data:write')]
}
});
These examples demonstrate server-side verification, scope enforcement, and separation of client input from authorization logic, reducing integrity failures when using API keys in FeathersJS.
For ongoing monitoring, the middleBrick CLI can scan your FeathersJS endpoints from the terminal with middlebrick scan <url>, and the GitHub Action can add API security checks to your CI/CD pipeline to fail builds if risk scores drop below your chosen threshold.