Xml External Entities in Hapi with Cockroachdb
Xml External Entities in Hapi with Cockroachdb — how this specific combination creates or exposes the vulnerability
Xml External Entity (XXE) processing occurs when an XML parser resolves external references in a way that can disclose files, trigger SSRF, or consume resources. Hapi is a Node.js web framework; while it does not parse XML by default, integrations that add XML parsing (for example to consume SOAP services or legacy payloads) can introduce XXE if the parser is configured to load external DTDs or entities. Cockroachdb is a distributed SQL database; it is not an XML processor, but it can be used as a backend for storing application data, including XML payloads that later undergo unsafe parsing.
When an API built with Hapi accepts XML input and forwards or logs parts of it to Cockroachdb, the risk arises if untrusted XML is parsed before validation. An attacker can supply an XML payload that references a local file (file:///etc/passwd) or an internal network resource (http://metadata/). If the Hapi route or an underlying service parses that XML with external entity resolution enabled, the parser may read the referenced content and include it in the application logic or in logs that eventually reach Cockroachdb as part of a record. This can lead to sensitive data exposure or serve as a pivot for SSRF within the cluster. The combination therefore does not create a database-specific XXE in Cockroachdb itself, but it exposes a pathway where malicious XML processed by Hapi can impact data stored in Cockroachdb or leverage the database as a storage channel for exfiltrated information.
Consider an endpoint that receives an XML document containing user profile metadata and saves it to Cockroachdb. If the Hapi route uses an XML parser without disabling external entities, an attacker can embed a SYSTEM entity that reads a service account token from the filesystem and include that token inside the XML. The application then stores the token in a column in Cockroachdb, exposing credentials. Even if Cockroachdb does not parse XML, the database becomes a reservoir for attacker-controlled data because the Hapi layer trusted and persisted unsafe XML content. The attack chain is: malicious XML → XXE via Hapi XML parser → sensitive read or SSRF → data written to Cockroachdb or used to manipulate database operations through compromised application logic.
Other risks emerge when stored XML is later retrieved and re-parsed without safeguards, allowing injection of entity expansions that degrade performance or bypass input filters. Because Cockroachdb is often used in regulated environments, such exposures can conflict with compliance expectations around data protection. Defensive design requires treating XML from untrusted sources as hostile regardless of the database backing the service.
Cockroachdb-Specific Remediation in Hapi — concrete code fixes
Remediation centers on ensuring that XML processing in Hapi does not resolve external entities and that data written to Cockroachdb is validated and sanitized. Below are concrete patterns you can adopt.
1. Disable external entities in XML parsers
Choose an XML parser for Node.js and configure it to reject external entities. For example, with xmldom, avoid the default behavior that can be permissive, and do not use features that load external resources. With libraries that rely on libxmljs or similar, ensure parser options explicitly disable DTDs and external entity resolution.
// Example using xmldom with safe settings
const { DOMParser } = require('@xmldom/xmldom');
const xml = '<?xml version="1.0"?><user><name>alice</name></user>'; // trusted source
const parser = new DOMParser({
// These options are typical; verify the exact API for your library
// Ensure external entities and DTDs are not processed
});
const doc = parser.parseFromString(xml, 'text/xml');
// Validate schema and data types before using
const name = doc.getElementsByTagName('name')[0]?.textContent;
if (!name) throw new Error('Invalid payload');
2. Validate and parameterize database operations
When inserting or updating records in Cockroachdb from Hapi, use parameterized queries to avoid injection and ensure that data stored cannot carry executable XML constructs that may be repurposed later. Avoid string interpolation for SQL.
// Using @cockroachdb/client with parameterized statements
const { Client } = require('@cockroachdb/client');
const client = new Client({ connectionString: 'postgresql://user:pass@host:26257/db?sslmode=require' });
await client.connect();
async function saveUserProfile(request, h) {
const { userId, email, metadata } = request.payload; // metadata should be validated JSON, not raw XML
// Store structured data; if you must store XML, treat it as a string and do not parse it on read
const result = await client.query(`
INSERT INTO profiles (id, email, metadata_xml, updated_at)
VALUES ($1, $2, $3, NOW())
ON CONFLICT (id) DO UPDATE SET email = $2, metadata_xml = $3, updated_at = NOW()
`, [userId, email, metadata]); // metadata must be vetted; prefer JSON columns
return result;
}
3. Input validation and schema enforcement
Use a schema validation layer (for example Joi) to enforce strict shape and data types for incoming payloads. This prevents malformed or malicious XML fragments from entering your Hapi routes and reaching Cockroachdb.
const Joi = require('joi');
const profileSchema = Joi.object({
userId: Joi.string().pattern(/^[a-f0-9-]+$/).required(),
email: Joi.string().email().required(),
metadata: Joi.object({
displayName: Joi.string().max(100),
locale: Joi.string().length(2)
}).unknown(false) // reject extra fields
});
async function createProfile(request, h) {
const { error, value } = profileSchema.validate(request.payload);
if (error) return h.response({ error: error.details[0].message }).code(400);
// Proceed with safe, validated value
await saveUserProfile({ payload: value });
return h.response({ status: 'ok' }).code(200);
}
4. Secure storage and retrieval patterns
If you must store XML in Cockroachdb, keep it as a string in a dedicated column and avoid on-the-fly parsing in the database layer. When retrieving data, parse it with the same secure settings (external entities disabled) and do not pass raw database content to untrusted contexts without sanitization.
// Retrieve and validate before any further processing
async function getProfile(id) {
const result = await client.query('SELECT metadata_xml FROM profiles WHERE id = $1', [id]);
const row = result.rows[0];
if (!row) return null;
// Re-parse safely if needed, or treat as opaque string
const doc = parser.parseFromString(row.metadata_xml, 'text/xml');
// Perform strict validation on the parsed document
return doc;
}
By combining secure parser configuration, strict validation, and parameterized SQL, you reduce the risk that XML-related vulnerabilities in Hapi will affect your Cockroachdb-backed data stores.