HIGH shellshockfeathersjs

Shellshock in Feathersjs

How Shellshock Manifests in Feathersjs

Shellshock (CVE-2014-6271) is a vulnerability in the Bash shell that allows arbitrary command execution when specially crafted environment variables are processed. In a Feathersjs application the risk appears when developer code takes user‑controlled data (e.g., request headers, query strings, or payload fields) and places it into the environment before spawning a Bash shell. A common pattern is a service hook that logs request information and then executes a shell command for debugging or administrative tasks.

// feathers-service/hooks/shell-logger.js
const { exec } = require('child_process');

module.exports = function (context) {
  // context.params.headers may contain User-Agent, Referer, etc.
  const ua = context.params.headers['user-agent'] || '';
  // Unsafely echo the header into a shell command
  exec(`echo \"User-Agent: ${ua}\"`, (err, stdout, stderr) => {
    if (err) console.error(err);
    else console.log(stdout);
  })
  return context;
};

If the Feathers service is exposed without authentication, an attacker can send a request with a Shellshock payload in the User-Agent header:

GET /users HTTP/1.1
Host: api.example.com
User-Agent: () { :; }; /bin/cat /etc/passwd
...

Because the header value is interpolated directly into the command string and the environment is inherited by the spawned Bash process, the payload executes, leading to command injection. This maps to OWASP API Top 10 A03:2021 (Injection) and is exploitable on any Feathersjs endpoint that uses child_process.exec (or spawn with shell:true) and mixes unsanitized request data into the command or environment.

Feathersjs-Specific Detection

Detecting Shellshock in a Feathersjs API requires observing whether user‑supplied data can reach a Bash interpreter. middleBrick performs unauthenticated, black‑box testing and can reveal this issue without source access. When scanning an endpoint, middleBrick injects Shellshock‑style payloads into HTTP headers (User‑Agent, Referer, X‑Forwarded‑For, Cookie) and into query string parameters, then looks for signs of command execution in the response (e.g., contents of /etc/passwd, error messages, or timing differences).

To run a scan from the terminal:

npx middlebrick scan https://api.example.com/users

The output will include a finding under the "Command Injection" category if the payload is executed. Example finding:

  • Endpoint: GET /users
  • Parameter: Header User-Agent
  • Payload: () { :; }; /bin/cat /etc/passwd
  • Evidence: Response contains "root:x:0:0:root:/root:/bin/bash"
  • Severity: High
  • Remediation Guidance: Avoid interpolating user data into shell commands; use execFile with an argument array and {shell:false}; validate and whitelist input.

If you have access to the source code, you can also search for patterns like exec(\`.*${.*}\` or spawn(.* , {shell:true}) within Feathers service files or hooks. middleBrick’s dashboard will track the finding over time, showing whether the score improves after a fix.

Feathersjs-Specific Remediation

The most reliable remediation is to eliminate the use of a Bash shell for tasks that can be performed with Node.js built‑in APIs. If a shell command is unavoidable, follow these Feathersjs‑specific steps:

  1. Replace exec with execFile: Use an array for arguments and set shell:false so that the input is never interpreted by Bash.
  2. // Fixed hook
    const { execFile } = require('child_process');
    
    module.exports = function (context) {
      const ua = context.params.headers['user-agent'] || '';
      // Sanitize: allow only alphanumerics, spaces, hyphens and underscores
      const safeUa = ua.replace(/[^\w\s-]/g, '');
      execFile('echo', ['User-Agent: ' + safeUa], (err, stdout, stderr) => {
        if (err) console.error(err);
        else console.log(stdout);
      })
      return context;
    };
    
  3. Never inherit the full process environment when spawning a child process. Pass a clean environment object:
  4. execFile('echo', ['User-Agent: ' + safeUa], {
      env: { PATH: process.env.PATH } // only what you need
    }, callback);
    
  5. Validate and whitelist input at the Feathers hook level. Use a schema validator (e.g., ajv or Feathers’ built‑in validate hook) to reject any header that does not match an expected pattern.
  6. // feathers-service/hooks/validate-ua.js
    const { BadRequest } = require('@feathersjs/errors');
    
    module.exports = function () {
      return async context => {
        const ua = context.params.headers['user-agent'];
        if (!/^[\w\s\-]{1,100}$/.test(ua)) {
          throw new BadRequest('Invalid User-Agent header');
        }
        return context;
      };
    };
    
  7. Keep the underlying Bash patched on the host operating system. Even with safe coding, an outdated Bash could be exploited if any other process inadvertently invokes it.

After applying these changes, rerun middleBrick:

npx middlebrick scan https://api.example.com/users

The Scanner should now report a passing score (A or B) for the Command Injection check, confirming that the Shellshock vector has been eliminated.

Frequently Asked Questions

Can middleBrick detect Shellshock if the Feathersjs service only runs in a container without Bash?
middleBrick tests for command injection by attempting to execute payloads through any available shell. If the container does not have Bash or any other shell installed, the injection attempt will fail and the scanner will report no finding. However, it is still good practice to avoid shell commands altogether, as other interpreters (e.g., sh, dash) may be present and vulnerable.
Is it sufficient to only update Bash on the host to protect my Feathersjs API?
Updating Bash mitigates the specific Shellshock vulnerability (CVE‑2014‑6271) but does not protect against other command injection flaws that arise from unsanitized input being passed to any shell or interpreter. A defense‑in‑depth approach—validating input, avoiding shell commands, and using safe APIs like child_process.execFile with {shell:false}—is required for comprehensive protection.