CRITICAL command injectionhapijavascript

Command Injection in Hapi (Javascript)

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

Command Injection occurs when an Hapi application passes untrusted data into a system shell or process-spawning function without proper validation or sanitization. In a JavaScript-based Hapi server, this typically arises from using child process utilities like child_process.exec or child_process.spawn with user-controlled input such as query parameters, headers, or request payloads.

Consider a route that echoes a user-supplied string into a shell command:

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

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

    server.route({
        method: 'GET',
        path: '/ping',
        handler: (request, h) => {
            const name = request.query.name;
            exec(`ping -c 1 ${name}`, (error, stdout, stderr) => {
                if (error) {
                    return `Error: ${error.message}`;
                }
                return stdout;
            });
            return 'OK';
        }
    });

    await server.start();
};

init();

In this example, the value of name is interpolated directly into the shell command string. An attacker can supply a value such as localhost; cat /etc/passwd, causing the server to execute additional commands. Because Hapi routes often handle external input, developers must remain vigilant about injection paths even when the framework does not introduce built-in command execution features.

The JavaScript runtime environment does not inherently protect against command injection; the risk is introduced by the developer’s use of low-level process execution APIs. middleBrick detects this pattern during its unauthenticated black-box scanning, flagging endpoints that reflect or execute shell commands with unchecked input. This aligns with the broader OWASP API Top 10 category of Broken Object Level Authorization and Improper Neutralization of Special Elements used in an OS Command context.

Unlike authenticated scans that test business logic flaws, middleBrick’s unauthenticated approach can still identify command injection when endpoint behaviors reveal command chaining or error-based leakage. The scanner does not fix the issue but provides prioritized findings with remediation guidance, helping teams understand how an attacker could manipulate inputs to achieve unintended execution.

Javascript-Specific Remediation in Hapi — concrete code fixes

To mitigate command injection in Hapi with JavaScript, avoid constructing shell commands with user input. Instead, prefer language-native operations or strict allowlists. When shell interaction is unavoidable, use parameterized APIs that separate arguments from commands.

1. Avoid shell metacharacters by using built-in modules

Replace shell-based operations with Node.js built-in modules. For network diagnostics, use the dns module instead of invoking ping:

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

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

    server.route({
        method: 'GET',
        path: '/resolve',
        handler: async (request, h) => {
            const hostname = request.query.host;
            return new Promise((resolve, reject) => {
                dns.lookup(hostname, (err, address) => {
                    if (err) {
                        return reject({ error: err.message });
                    }
                    resolve(address);
                });
            });
        }
    });

    await server.start();
};

init();

2. Use execFile with argument array when shell execution is necessary

If you must execute an external binary, use child_process.execFile and pass arguments as an array. This prevents the shell from interpreting metacharacters:

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

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

    server.route({
        method: 'GET',
        path: '/version',
        handler: (request, h) => {
            const tool = request.query.tool;
            // Only allow known tools to prevent path traversal or injection
            const allowed = { 'node': true, 'npm': true };
            if (!allowed[tool]) {
                return { error: 'Invalid tool' };
            }

            execFile(tool, ['--version'], (error, stdout, stderr) => {
                if (error) {
                    return { error: error.message };
                }
                return { output: stdout.trim() };
            });
            return 'OK';
        }
    });

    await server.start();
};

init();

3. Validate and sanitize using an allowlist

When input must be used, enforce a strict allowlist rather than a blocklist. For example, if the input must be a numeric ID, ensure it matches a regular expression for integers only:

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

const isValidId = (value) => /^\d+$/.test(value);

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

    server.route({
        method: 'GET',
        path: '/user/{id}',
        handler: (request, h) => {
            const id = request.params.id;
            if (!isValidId(id)) {
                return { error: 'Invalid ID' };
            }

            execFile('id', [id], (error, stdout, stderr) => {
                if (error) {
                    return { error: error.message };
                }
                return { info: stdout.trim() };
            });
            return 'OK';
        }
    });

    await server.start();
};

init();

These JavaScript-specific practices reduce the attack surface by eliminating shell interpretation and enforcing strict input constraints. middleBrick’s checks complement these efforts by identifying endpoints where user data reaches process execution, supporting compliance mappings to OWASP API Top 10 and other frameworks.

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 middleBrick detect command injection in Hapi endpoints that use dynamic binary paths?
Yes. middleBrick tests endpoints where user input influences command execution patterns. If a Hapi route constructs shell commands or passes unchecked input to child process functions, the scanner can flag related behaviors during its runtime analysis.
Does the free plan include scanning for command injection vulnerabilities in JavaScript-based APIs?
Yes. The free plan provides 3 scans per month and includes all 12 security checks, such as injection testing, regardless of the plan tier. Findings include command injection risks with remediation guidance.