HIGH server side template injectionsailsbasic auth

Server Side Template Injection in Sails with Basic Auth

Server Side Template Injection in Sails with Basic Auth — how this specific combination creates or exposes the vulnerability

Server Side Template Injection (SSTI) occurs when an attacker can inject template code that is subsequently evaluated by the server-side rendering engine. In Sails.js, which can leverage templating engines such as EJS or Pug, unsanitized user input embedded in templates may lead to arbitrary code execution. When Basic Authentication is used without additional safeguards, the attack surface expands because credentials are often handled in controllers or policies before reaching the template layer, and developer assumptions about the safety of authenticated contexts can lead to insufficient input validation.

Consider a Sails controller that renders a profile page using a template engine and incorporates user-supplied data, such as a display name, without proper escaping or validation:

module.exports.profile = function (req, res) {
  return res.view('profile', {
    name: req.query.name || 'Guest'
  });
};

An SSTI payload like ${7*7} in the name query parameter can lead to code execution if the template engine evaluates the expression. With Basic Auth, the request includes an Authorization header (e.g., Authorization: Basic base64(username:password)). If a policy or middleware parses and logs credentials insecurely, or if developer focus on authentication blinds testing of unauthenticated-style inputs, the template may receive attacker-controlled data from headers or cookies in addition to query parameters. This combination means that even when authentication is enforced, SSTI flaws persist because the template processes untrusted input that may originate from parsed credentials or from indirect sources assumed safe due to the authenticated context.

Moreover, Sails applications that expose REST endpoints returning rendered templates can inadvertently amplify SSTI when input validation is limited to presence checks rather than strict allow-lists. Attackers probe endpoints using techniques aligned with the OWASP API Top 10 and API Security Top 10, such as injection patterns categorized under SSTI. The presence of Basic Auth does not mitigate injection; it only ensures identity, not the safety of the data processed by templates. Therefore, the risk persists, and scans using methodologies like those employed by middleBrick can surface these issues by correlating spec definitions with runtime behavior, identifying places where authentication and template rendering intersect without adequate sanitization.

Basic Auth-Specific Remediation in Sails — concrete code fixes

To mitigate SSTI in Sails when using Basic Authentication, treat all user-influenced data—including parsed credentials and header values—as untrusted. Apply output encoding appropriate for the template engine, enforce strict input validation, and avoid embedding raw user input in templates.

1. Use template engine escaping features

Ensure your template engine auto-escapes output. For EJS, use <%= %> instead of <%- %>. For Pug, rely on its default escaping:

// profile.ejs (safe)
<h1>Welcome, <%= name %></h1>

// profile.pug (safe)
h1 Welcome, #{name}

2. Validate and sanitize inputs

Use a validation library or custom checks to enforce allow-lists. Reject or sanitize unexpected characters, especially for names or identifiers that should not contain template syntax:

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

module.exports.profile = function (req, res) {
  const rawName = req.query.name;
  if (typeof rawName !== 'string' || !/^[
a-zA-Z0-9 _-]{1,50}$/.test(rawName)) {
    return res.badRequest('Invalid name');
  }
  const safeName = escapeHtml(rawName);
  return res.view('profile', { name: safeName });
};

3. Secure Basic Auth handling

Parse credentials in policies or controllers without passing raw values directly to templates. Use middleware to authenticate and attach a minimal user object to req, avoiding logging or reflecting credentials in responses:

// api/policies/basicAuth.js
module.exports.basicAuth = function (req, res, next) {
  const authHeader = req.headers().authorization;
  if (!authHeader || !authHeader.startsWith('Basic ')) {
    return res.unauthorized('Missing credentials');
  }
  const base64 = authHeader.split(' ')[1];
  const decoded = Buffer.from(base64, 'base64').toString('utf8');
  const [username, password] = decoded.split(':');
  // Perform secure verification against a database or service
  if (!isValidUser(username, password)) {
    return res.unauthorized('Invalid credentials');
  }
  req.user = { username };
  return next();
};

// Example usage in a controller
module.exports.dashboard = function (req, res) {
  // req.user is set by the policy; do not echo credentials back
  return res.view('dashboard', { username: req.user.username });
};

4. Enforce secure transport and avoid reflection

Ensure HTTPS is used to protect credentials in transit. Never reflect the Authorization header or raw credentials in error messages or templates, as this can aid injection attacks or credential leakage.

By combining these practices—template escaping, strict input validation, secure credential handling, and transport security—you reduce the risk of SSTI in Sails applications using Basic Authentication. Tools like middleBrick can help verify that such controls are effective by scanning endpoints and correlating spec definitions with runtime findings.

Frequently Asked Questions

Does using Basic Authentication prevent Server Side Template Injection in Sails?
No. Basic Authentication handles identity verification but does not sanitize user input. SSTI depends on how templates process data; attackers can inject payloads through query parameters, headers, or cookies regardless of authentication, so input validation and output encoding remain essential.
How can I test my Sails endpoints for SSTI without credentials?
Focus on unauthenticated-style inputs such as query parameters, headers, and cookies. Use targeted payloads like ${7*7} or {{7*7}} depending on the template engine, and inspect responses for code execution evidence. Automated scans, including those that correlate OpenAPI specs with runtime behavior, can help identify vulnerable endpoints.