Server Side Template Injection in Hapi with Api Keys
Server Side Template Injection in Hapi with Api Keys — how this specific combination creates or exposes the vulnerability
Server Side Template Injection (SSTI) in Hapi becomes high risk when API keys are used for routing, authorization, or data exposure without strict input validation. SSTI occurs when an attacker can inject template code that the server-side rendering engine evaluates. In Hapi, this commonly arises when route handlers render dynamic content using template engines such as Handlebars or when responses embed user-controlled data into templates that are later processed.
When API keys are passed as route parameters, query strings, or headers and then forwarded into a template context, they can become a vector for SSTI. For example, if a developer builds a diagnostic or debugging endpoint that includes the API key in the rendered output without sanitization, an attacker may supply a crafted API key containing template syntax (e.g., {{7*7}} for Handlebars) and observe reflected evaluation results. This allows the attacker to probe for template engine behavior, enumerate internal variables, or achieve unintended code execution depending on the engine’s sandboxing and configuration.
The risk is compounded when API keys are used to determine which data subset is rendered. If the template uses the API key to look up user-specific information and then interpolates that information unsafely, the attack surface expands. A malicious actor can use SSTI to bypass intended data isolation by manipulating how the template resolves variables tied to the API key. Because Hapi routes often compose multiple handlers and plugins, a vulnerable template combined with per-request API key validation can expose sensitive data or enable server-side request forgery when the template makes outbound calls based on injected logic.
Real-world patterns include endpoints that return rendered templates with variables derived from API keys, such as user roles or permissions. If those variables are not strictly typed or escaped, an attacker can chain SSTI with insecure direct object references (BOLA/IDOR) to escalate impact. The interaction between authentication via API keys and unsafe template rendering is notable because it can turn what appears to be a read-only diagnostic into a reflective or blind injection channel.
middleBrick detects this class of issue by correlating OpenAPI/Swagger specifications with runtime behavior. It checks whether inputs that influence template context—such as API key parameters—are properly validated and isolated. The scanner flags cases where user-controlled data reaches template rendering without canonicalization, escaping, or strict schema enforcement, providing prioritized findings mapped to OWASP API Top 10 and referencing real CVEs that describe similar SSTI mechanics in server-side frameworks.
Api Keys-Specific Remediation in Hapi — concrete code fixes
Remediation focuses on ensuring API keys never directly reach template rendering logic and that all dynamic data inserted into templates is strictly validated and escaped. Below are concrete Hapi patterns that reduce SSTI risk when API keys are in use.
- Do not pass API keys into template context. Instead, use the key to fetch permissions or tenant data server-side, then pass only safe, derived values to the template.
- Use strict schema validation for all inputs, including query parameters and headers that carry API keys, and enforce allowlists for expected formats.
- Configure your template engine to auto-escape content and avoid unsafe interpolation patterns.
Example: Safe route definition in Hapi using Joi validation and Handlebars with auto-escaping enabled:
const Hapi = require('@hapi/hapi');
const Handlebars = require('handlebars');
const server = Hapi.server({ port: 4000, host: 'localhost' });
server.views({
engines: { html: Handlebars },
path: './templates',
options: {
isStrict: true,
allowProtoPropertiesByDefault: false,
allowProtoMethodsByDefault: false,
// Ensure Handlebars escapes HTML by default
helpers: {
safeString: (input) => new Handlebars.SafeString(input)
}
}
});
server.route({
method: 'GET',
path: '/report',
options: {
validate: {
query: {
apiKey: Joi.string().pattern(/^[A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12}$/i).required(),
reportId: Joi.number().integer().min(1).required()
}
},
auth: false // handled via API key, not session
},
handler: async (request, h) => {
const { apiKey, reportId } = request.query;
// Fetch report data server-side using the API key, do not embed key in template
const reportData = await fetchReportByApiKeyAndId(apiKey, reportId);
// Pass only safe, transformed data to the template
return h.view('report-template', {
title: 'Report',
reportId: reportData.id,
metrics: reportData.metrics.map(m => ({ name: m.name, value: String(m.value) })) // escaped by default
});
}
});
async function fetchReportByApiKeyAndId(apiKey, reportId) {
// Placeholder: implement secure lookup using the API key without exposing it to the template
return { id: reportId, metrics: [{ name: 'requests', value: 42 }] };
}
Example: Safe route using inert and a strict context object for dynamic pages without templates:
const Hapi = require('@hapi/hapi');
const Inert = require('@hapi/inert');
const server = Hapi.server({ port: 4000, host: 'localhost' });
server.register(Inert, (err) => {
if (err) throw err;
});
server.route({
method: 'GET',
path: '/health',
options: {
validate: {
headers: Joi.object({
'x-api-key': Joi.string().required().pattern(/^[A-Za-z0-9\-_=]+\.[A-Za-z0-9\-_=]+\.?[A-Za-z0-9\-_.+/=]*$/)
}).unknown()
}
},
handler: (request, h) => {
const apiKey = request.headers['x-api-key'];
// Perform server-side authorization using the key, return plain JSON
return h.response({ status: 'ok', scope: 'read-only' }).code(200);
}
});
These examples emphasize that API keys should drive server-side decisions, not template content. By validating structure, avoiding reflection of raw keys, and leveraging the framework’s escaping features, you reduce the likelihood of SSTI when API keys are part of the request surface. middleBrick helps identify endpoints where API key parameters correlate with unsafe template rendering, supporting remediation aligned with OWASP API Top 10 and common compliance frameworks.