HIGH server side template injectionhapijwt tokens

Server Side Template Injection in Hapi with Jwt Tokens

Server Side Template Injection in Hapi with Jwt Tokens — how this specific combination creates or exposes the vulnerability

Server Side Template Injection (SSTI) in Hapi becomes higher risk when JWT tokens are used for session handling and route protection. Hapi applications often parse and validate JWTs in server-side templates or in request preprocessing steps before rendering views. If a template is constructed using unsanitized values extracted from the JWT payload—such as user roles, display names, or injected claims—an attacker who can influence the token content may achieve template injection.

Consider a scenario where a Hapi route reads a JWT, extracts a user-supplied claim, and passes it directly to a template engine without validation or escaping. For example, a route might use the payload’s name field to personalize a page. Because JWTs can be unsigned or forged when validation is misconfigured, an attacker can supply a malicious claim containing template syntax. When the server renders the template, the injected code can execute in the context of the application, leading to sensitive data exposure or remote code execution.

In a black-box scan, middleBrick tests unauthenticated endpoints and checks whether data from JWTs (e.g., via Authorization header parsing) influences template rendering. The scanner’s 12 security checks run in parallel and include Authentication, Input Validation, and Data Exposure, which are relevant when JWTs interact with server-side templates. If a template engine fails to escape user-controlled data originating from a JWT, middleBrick flags this as a high-severity finding with remediation guidance to treat all token-derived data as untrusted input.

SSRF and Unsafe Consumption checks also matter here because a malicious JWT claim could direct the server to load remote templates or external resources, amplifying the impact. Because JWT tokens often carry metadata and roles, developers may mistakenly trust them more than form inputs, increasing the likelihood of insecure template usage. middleBrick’s LLM/AI Security checks are unique in detecting whether prompts or configuration patterns in server-side logic expose token handling or template paths that could be abused.

To illustrate, a vulnerable Hapi route might look like this in JavaScript:

const Hapi = require('@hapi/hapi');
const Jwt = require('@hapi/jwt');
const vision = require('@hapi/vision');

const init = async () => {
  const server = Hapi.server({ port: 4000 });
  await server.register([Jwt, vision]);

  server.views({
    engines: { html: { modulePath: 'handlebars' } },
    path: './views',
  });

  server.route({
    method: 'GET',
    path: '/profile',
    options: {
      auth: false,
      handler: (request, h) => {
        const token = request.headers.authorization?.split(' ')[1];
        let payload = {};
        if (token) {
          try {
            // Insecure: no validation or key management shown
            payload = JwtUtils.decode(token); // hypothetical decoder
          } catch (err) {}
        }
        // Vulnerable: injecting untrusted JWT claim into template
        return h.view('profile', { username: payload.name || 'Guest' });
      },
    },
  });
};

Jwt Tokens-Specific Remediation in Hapi — concrete code fixes

Remediation focuses on strict JWT validation, avoiding direct use of token claims in templates, and ensuring all dynamic data is escaped. First, always validate the JWT using a trusted library with a verified signing key and expected audience and issuer. Never decode and trust the payload without verification.

Second, map only safe, non-user-controlled data from the token to the template context—such as user ID for lookup rather than display name. If you must pass data from the JWT to the UI, sanitize and escape it explicitly. For Handlebars templates used with @hapi/vision, enable autoescaping and avoid triple-stash syntax that disables escaping.

Below is a hardened example that validates a JWT and uses a database lookup instead of injecting claims directly into the template:

const Hapi = require('@hapi/hapi');
const Jwt = require('@hapi/jwt');
const vision = require('@hapi/vision');

const init = async () => {
  const server = Hapi.server({ port: 4000 });
  await server.register([Jwt, vision]);

  server.views({
    engines: { html: { modulePath: 'handlebars' } },
    path: './views',
  });

  server.route({
    method: 'GET',
    path: '/profile',
    options: {
      auth: false,
      handler: async (request, h) => {
        const authHeader = request.headers.authorization;
        let userId = null;
        if (authHeader && authHeader.startsWith('Bearer ')) {
          const token = authHeader.split(' ')[1];
          try {
            // Secure: validate with key and options
            const { isValid, credentials } = await Jwt.validate(token, 'your-secret-key', {
              rules: { aud: 'your-audience', iss: 'your-issuer' },
            });
            if (isValid && credentials.userId) {
              userId = credentials.userId;
            }
          } catch (err) {
            // Log but do not expose details
            console.error('JWT validation failed:', err);
          }
        }
        // Avoid injecting raw token claims into the view model
        const user = userId ? await db.getUserById(userId) : null;
        return h.view('profile', { user: user ? { name: escapeHtml(user.name) } : { name: 'Guest' } });
      },
    },
  });
};

function escapeHtml(str) {
  return str.replace(/[<>"']/g, (s) => ({'&': '&', '<': '<', '>': '>', '"': '"', \"'\": '''}[s]));
}

Additionally, configure your JWT library to reject unsigned tokens and enforce algorithm restrictions to prevent token substitution attacks. middleBrick’s Authentication and Input Validation checks can verify that your endpoints enforce these controls and that templates do not reflect untrusted data from JWTs without escaping.

Frequently Asked Questions

Can SSTI via JWT tokens be detected without authentication?
Yes. middleBrick scans unauthenticated attack surfaces and tests whether JWT-derived data influences template rendering. The scanner’s Authentication and Input Validation checks detect cases where token claims reach server-side templates without proper escaping.
Does middleBrick fix template injection vulnerabilities found via JWT tokens?
No. middleBrick detects and reports findings with remediation guidance. You must apply code fixes such as strict JWT validation, avoiding direct use of token claims in templates, and ensuring output escaping.