Xpath Injection in Feathersjs with Hmac Signatures
Xpath Injection in Feathersjs with Hmac Signatures — how this specific combination creates or exposes the vulnerability
XPath Injection in Feathersjs when Hmac Signatures are used arises when user-controlled input is reflected into XPath expressions and the request is authenticated only by an Hmac Signature. An attacker can manipulate query parameters or payload fields to alter the XPath filter, bypassing intended data access controls. Because Feathersjs services often map HTTP queries to XPath lookups against XML or structured document stores, unchecked input can change path segments, predicate values, or axis selectors.
Hmac Signatures are intended to ensure request integrity and origin authentication. They are computed over selected parts of the request (method, path, headers, and body). If the signature does not cover the full canonicalized request body or if the server recomputes the signature after modifying the XPath based on user input, an attacker can inject malicious XPath while keeping a valid signature. For example, an attacker may append encoded predicates to a query string that are concatenated into the XPath before signature verification, or they may exploit ambiguous parameter parsing that is excluded from the signed string.
Consider a Feathers service that retrieves user records from an XML backend using an XPath derived from an id parameter. If the id value is not strictly validated and is directly interpolated into the expression, an attacker can provide ' or 1=1 or ' to change the predicate logic. Even when the call is signed with Hmac, if the server normalizes or sanitizes the id before signing, the runtime XPath may differ from what was signed. This mismatch enables unauthorized data enumeration or extraction, a BOLA/IDOR pattern often flagged by middleBrick’s BOLA/IDOR and Property Authorization checks.
Real-world attack patterns include probing for numeric injection to bypass record-level ownership checks, using path traversal sequences to reach sibling nodes, and injecting function calls or namespace manipulations to escalate access. Because XPath supports axes and wildcards, an injected // or @* can broaden the result set significantly. The combination of a permissive XPath builder and an Hmac scheme that does not tightly bind the exact input used in path construction creates a window for privilege escalation and data exposure, which would be surfaced by middleBrick’s XPath-related tests under its security checks.
middleBrick detects these issues by correlating OpenAPI/Swagger specifications with runtime behavior, highlighting where user-controlled data reaches XPath-like selectors and where Hmac Signature coverage is incomplete. Findings include severity-ranked guidance to tighten input validation and ensure signature scope matches the runtime execution model, aligning with OWASP API Top 10 and relevant compliance mappings.
Hmac Signatures-Specific Remediation in Feathersjs — concrete code fixes
Remediation focuses on strict input validation, canonical request construction, and ensuring Hmac signature verification occurs after all user input is normalized and constrained. Do not allow raw user input to directly form XPath expressions. Use allowlists, type checks, and explicit mapping to safe identifiers.
Example: Secure Feathers Service with Hmac Signature Validation
The following example demonstrates a Feathers service that validates an id parameter, builds a canonical string for Hmac signing, and uses a whitelisted mapping to a safe internal key rather than directly injecting the value into XPath.
const crypto = require('crypto');
const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const app = express(feathers());
// Middleware to verify Hmac Signature
app.use((req, res, next) => {
const signature = req.headers['x-hmac-signature'];
const timestamp = req.headers['x-request-timestamp'];
const nonce = req.headers['x-nonce'];
if (!signature || !timestamp || !nonce) {
return res.status(400).send({ message: 'Missing authentication headers' });
}
// Prevent replay attacks (basic example)
if (Math.abs(Date.now() - parseInt(timestamp, 10)) > 300000) {
return res.status(401).send({ message: 'Request expired' });
}
const secret = process.env.HMAC_SECRET;
const payload = [
req.method.toUpperCase(),
req.path,
timestamp,
nonce,
req.is('application/json') ? JSON.stringify(req.body) : ''
].join('\n');
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
return res.status(401).send({ message: 'Invalid signature' });
}
next();
});
// Safe id validation and mapping
const idWhitelist = new Set(['user-123', 'user-456', 'user-789']); // Example allowlist
app.use('/records', {
async get(id, params) {
if (!id || typeof id !== 'string' || !idWhitelist.has(id)) {
throw new Error('Invalid record identifier');
}
// Map id to a safe internal key, do not use raw id in XPath
const safeKey = `record_${id.replace(/[^a-z0-9_-]/gi, '_')}`;
// Use safeKey in any XPath construction, ensuring it cannot alter path structure
const xpath = `/data/${safeKey}`;
// Perform lookup with xpath, ensuring no user input is concatenated directly
return { id, xpath, data: 'safe payload' };
}
});
app.configure(express.rest());
Key practices:
- Include the exact request body in the Hmac canonical string to bind signature to content.
- Validate and normalize all inputs before using them in path construction.
- Use allowlists for identifiers; avoid dynamic concatenation of user values into XPath.
- Perform signature verification before any data access logic to reject tampered requests early.
- Log rejected attempts for audit without exposing internal paths or secrets.
For APIs exposed through middleBrick, applying the Pro plan’s continuous monitoring and CI/CD integration can help catch regressions where Hmac coverage or XPath handling becomes inconsistent after updates. The dashboard and GitHub Action allow you to fail builds if risk scores degrade, reinforcing secure deployment practices.