HIGH command injectionhapibasic auth

Command Injection in Hapi with Basic Auth

Command Injection in Hapi with Basic Auth — how this specific combination creates or exposes the vulnerability

Command Injection in a Hapi application using HTTP Basic Authentication occurs when untrusted input from an authenticated request is passed to a system command without proper validation or sanitization. Even when credentials are verified via Basic Auth, an attacker who has obtained or guessed a valid username and password can still exploit weak server-side handling to execute arbitrary shell commands.

In Hapi, route handlers often receive parameters from authentication artifacts (e.g., credentials stored in request.auth.credentials) combined with query or payload inputs. If these values are used to construct shell commands—such as calling child_process.exec or child_process.spawn with concatenated strings—an attacker can inject shell metacharacters like ;, &&, or backticks to alter command logic. For example, a route that builds a system command using a username from Basic Auth and a user-supplied filename can become a vector for OS command execution.

Because Basic Auth transmits credentials in an encoded (not encrypted) format unless protected by TLS, an attacker who intercepts or reuses a valid token can repeatedly abuse a vulnerable endpoint. The presence of valid credentials does not prevent command injection; it simply means the attacker has cleared the authentication barrier. Once injection is possible, outcomes can include unauthorized file access, environment enumeration, or lateral movement, depending on the server’s permissions.

middleBrick detects this risk by analyzing OpenAPI/Swagger specs with full $ref resolution and correlating them with runtime tests. Among its 12 parallel security checks, Input Validation flags unsafe usage of external input in command construction, while Authentication and BOLA/IDOR checks verify whether credentials are handled in a way that prevents privilege misuse. The scanner does not fix the code but provides severity-ranked findings with remediation guidance, mapping to OWASP API Top 10 and other compliance frameworks.

Basic Auth-Specific Remediation in Hapi — concrete code fixes

To mitigate Command Injection in Hapi while using Basic Auth, avoid building shell commands from any request-derived data, including authenticated user information. Use parameterized APIs, strict allowlists, and server-side validation. The following examples show vulnerable patterns and secure alternatives.

Vulnerable Hapi route with Basic Auth and command injection risk:

const Hapi = require('@hapi/hapi');
const { exec } = require('child_process');

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

  server.auth.scheme('custombasic', () => ({
    authenticate(request, h) {
      const credentials = request.headers.authorization;
      if (!credentials || !/^Basic\s(\S+)$/.test(credentials)) {
        return { isValid: false };
      }
      const token = credentials.split(' ')[1];
      const userBuffer = Buffer.from(token, 'base64');
      const userPass = userBuffer.toString('utf8');
      const [user, pass] = userPass.split(':');
      if (user === 'admin' && pass === 'secret123') {
        return { isValid: true, credentials: { user } };
      }
      return { isValid: false };
    }
  }));

  server.auth.strategy('default', 'custombasic');

  server.route({
    method: 'GET',
    path: '/ping/{filename}',
    options: {
      auth: 'default',
      handler: (request, h) => {
        const { filename } = request.params;
        const username = request.auth.credentials.user;
        // Dangerous: using user input in shell command
        exec(`echo ${username} > /tmp/${filename}`, (err, stdout, stderr) => {
          if (err) return { error: err.message };
          return { stdout };
        });
      }
    }
  });

  await server.start();
};
init();

In the example above, filename from the route parameter and username from Basic Auth are concatenated into a shell command. An authenticated attacker could supply ../../../etc/passwd or use shell metacharacters to read arbitrary files or change behavior.

Secure Hapi route with input validation and safe APIs:

const Hapi = require('@hapi/hapi');
const { execFile } = require('child_process');

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

  server.auth.scheme('custombasic', () => ({
    authenticate(request, h) {
      const credentials = request.headers.authorization;
      if (!credentials || !/^Basic\s(\S+)$/.test(credentials)) {
        return { isValid: false };
      }
      const token = Buffer.from(credentials.split(' ')[1], 'base64').toString('utf8');
      const [user, pass] = token.split(':');
      if (user === 'admin' && pass === 'secret123') {
        return { isValid: true, credentials: { user } };
      }
      return { isValid: false };
    }
  }));

  server.auth.strategy('default', 'custombasic');

  server.route({
    method: 'GET',
    path: '/ping/{filename}',
    options: {
      auth: 'default',
      handler: (request, h) => {
        const { filename } = request.params;
        const username = request.auth.credentials.user;
        // Safe: use execFile with explicit arguments and no shell
        return new Promise((resolve, reject) => {
          execFile('echo', [username], { timeout: 5000 }, (err, stdout, stderr) => {
            if (err) return reject({ error: err.message });
            // Further validate filename to prevent path traversal
            if (!/^[a-zA-Z0-9._-]+$/.test(filename)) {
              return reject({ error: 'Invalid filename' });
            }
            const fs = require('fs');
            fs.writeFileSync(`/tmp/${filename}`, stdout);
            resolve({ status: 'ok' });
          });
        });
      }
    }
  });

  await server.start();
};
init();

The secure version uses execFile with explicit arguments to avoid shell interpretation, validates filename against an allowlist, and removes direct concatenation of user input into shell commands. This approach aligns with remediation guidance provided by middleBrick findings, which highlight unsafe consumption patterns and offer prioritized steps.

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Can a valid Basic Auth token prevent command injection?
No. Authentication confirms identity but does not sanitize input. Command injection depends on how server-side code uses request data, so valid credentials alone do not stop injection.
What are the key coding practices to prevent Command Injection in Hapi with Basic Auth?
Avoid shell command construction from any external input; use parameterized APIs like execFile; validate and allowlist all user-controlled values; and handle credentials via secure transport (TLS) and proper storage.