HIGH server side template injectionhapi

Server Side Template Injection in Hapi

How Server Side Template Injection Manifests in Hapi

Server Side Template Injection (SSTI) in Hapi typically arises when user-controlled data is passed into a server-side template without proper escaping or isolation. Hapi does not ship a built-in template engine, so developers commonly integrate third-party engines such as Handlebars or Pug. When these engines are used unsafely—by directly interpolating request parameters into template strings or partials—template injection becomes possible.

Attack patterns specific to Hapi involve routes that render templates using dynamic input. For example, a route that accepts a page query parameter and passes it to a Handlebars template can be abused if the template includes that value in a context that the engine interprets as executable directives. In Handlebars, expressions like {{> (lookup . "page")}} can be leveraged to include arbitrary templates if user input is not strictly constrained.

Another Hapi-specific code path is when developers compose responses using template engines within request handlers without validating or sanitizing input. Consider a route where the template name or a partial name is derived from request.query.view. If the engine resolves this input and the template contains variables that map to the request context, an attacker can supply payloads such as {{this.constructor.constructor('return process')()}} in form fields (when using engines that evaluate JavaScript-like expressions in strict mode or when context is improperly exposed), leading to arbitrary code execution on the server.

In Hapi, server-side rendering often occurs inside plugins or route handlers that call reply.view(). If the view context includes user-supplied objects and the template engine does not enforce strict sandboxing, attackers can traverse prototypes or exploit engine-specific features to read files or execute commands. For instance, in some configurations with Handlebars, nested lookups can traverse Object.prototype to access constructors, enabling prototype pollution or code execution depending on the engine version and configuration.

Hapi-Specific Detection

Detecting SSTI in Hapi requires analyzing how templates are rendered and whether untrusted input influences template structure or variable resolution. A reliable indicator is the use of dynamic view names or partials derived from request parameters without strict allowlisting. Security scanners can identify these patterns by inspecting route definitions and template usage for direct concatenation of user input into rendering functions.

Using middleBrick, you can submit your Hapi API endpoint and run a scan that includes active LLM security probing and checks across 12 security categories, including Input Validation and Unsafe Consumption. The scanner examines unauthenticated attack surfaces and cross-references any OpenAPI/Swagger specifications (with full $ref resolution) against runtime behavior. For SSTI, findings may highlight unsafe usage of template engines, missing input sanitization in reply.view() calls, or exposure of dangerous helper functions in the rendering context.

To validate detection, you can manually test endpoints with crafted payloads such as {{7*7}} in string parameters if the engine evaluates expressions. If the response contains rendered arithmetic or engine-specific markers, this suggests insufficient escaping. middleBrick reports these findings with severity levels and remediation guidance, helping you confirm and prioritize fixes without relying on internal architecture details.

Hapi-Specific Remediation

Remediation centers on strict input validation and isolating templates from user-controlled data. In Hapi, use allowlists for view names and partials, and avoid passing raw request parameters into template rendering functions. When using Handlebars, ensure the engine is configured with strict mode and without access to dangerous helpers or prototypes.

Code example: Safe route definition using a fixed set of allowed views.

const Hapi = require('@hapi/hapi');

const allowedViews = ['home', 'about', 'contact'];

const init = async () => {
  const server = Hapi.server({ port: 3000, host: 'localhost' });

  server.views({
    engines: { html: require('handlebars') },
    relativeTo: __dirname,
    path: './views',
    isCached: false
  });

  server.route({
    method: 'GET',
    path: '/page',
    handler: (request, h) => {
      const viewName = request.query.view;
      if (!allowedViews.includes(viewName)) {
        return h.response('Invalid view').code(400);
      }
      return h.view(viewName, { title: 'Safe Page' });
    }
  });

  await server.start();
  console.log('Server running on %s', server.info.uri);
};

init();

Code example: Using partials safely with explicit mapping instead of dynamic lookup.

const Hapi = require('@hapi/hapi');

const init = async () => {
  const server = Hapi.server({ port: 3000, host: 'localhost' });

  server.views({
    engines: { html: require('handlebars') },
    relativeTo: __dirname,
    path: './views',
    partialsPath: './views/partials',
    isCached: false
  });

  server.route({
    method: 'GET',
    path: '/profile',
    handler: (request, h) => {
      // Always reference a known partial; do not use user input to select partials
      return h.view('profile', {
        username: request.auth.credentials.name
      });
    }
  });

  await server.start();
  console.log('Server running on %s', server.info.uri);
};

init();

Additional measures include avoiding the use of plugins that expose template helpers based on request data and regularly updating template engines to mitigate known prototype pollution or injection vectors. middleBrick’s Pro plan supports continuous monitoring so that future changes to routes or templates can be automatically rescanned based on a configurable schedule.

Frequently Asked Questions

Can SSTI in Hapi lead to remote code execution?
Yes, if a template engine evaluates user-controlled input as code and the rendering context exposes dangerous constructors or helpers, SSTI can lead to remote code execution. Mitigate by using strict allowlists and avoiding dynamic template selection.
How does middleBrick detect SSTI in Hapi APIs?
middleBrick scans unauthenticated attack surfaces, cross-references OpenAPI/Swagger specs with runtime behavior, and checks for unsafe template usage in routes like reply.view(). Findings include severity, category breakdowns, and remediation guidance without describing internal architecture.