VYPR
Critical severityNVD Advisory· Published Aug 24, 2018· Updated Sep 16, 2024

CVE-2018-3786

CVE-2018-3786

Description

Command injection in egg-scripts <2.8.1 allows arbitrary shell command execution via a maliciously crafted command line argument.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Command injection in egg-scripts <2.8.1 allows arbitrary shell command execution via a maliciously crafted command line argument.

Vulnerability

A command injection vulnerability exists in egg-scripts versions prior to 2.8.1. The start command passes user-supplied arguments (e.g., --stderr) to the shell by using child_process.exec() instead of child_process.execFile(), allowing shell metacharacters to be interpreted[1][2][3][4].

Exploitation

An attacker who can control the command line arguments passed to egg-scripts start can inject arbitrary shell commands. For example, appending a semicolon after a legitimate argument like --stderr enables execution of additional commands[2]. The attacker does not require authentication if they can directly invoke the start command with crafted arguments.

Impact

Successful exploitation results in arbitrary shell command execution with the privileges of the egg-scripts process. This can lead to complete compromise of the affected system, including data theft, installation of malware, or further lateral movement[1][4].

Mitigation

The vulnerability is fixed in egg-scripts version 2.8.1, released on August 19, 2018[3]. The fix replaces exec() with execFile() to avoid shell interpretation of arguments[2]. Users should upgrade to 2.8.1 or later. No workaround is available for earlier versions.

AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
egg-scriptsnpm
< 2.8.12.8.1

Affected products

2

Patches

1
b98fd03d1e3a

fix: use execFile instead of exec for security reason (#26)

https://github.com/eggjs/egg-scriptsfengmk2Aug 19, 2018via ghsa
5 files changed · +38 8
  • appveyor.yml+1 1 modified
    @@ -2,7 +2,7 @@ environment:
       matrix:
         - nodejs_version: '6'
         - nodejs_version: '8'
    -    - nodejs_version: '9'
    +    - nodejs_version: '10'
     
     install:
       - ps: Install-Product node $env:nodejs_version
    
  • lib/cmd/start.js+7 4 modified
    @@ -4,7 +4,7 @@ const path = require('path');
     
     const Command = require('../command');
     const debug = require('debug')('egg-script:start');
    -const { exec } = require('mz/child_process');
    +const { execFile } = require('mz/child_process');
     const fs = require('mz/fs');
     const homedir = require('node-homedir');
     const mkdirp = require('mz-modules/mkdirp');
    @@ -232,12 +232,15 @@ class StartCommand extends Command {
     
         if (hasError) {
           try {
    -        const [ stdout ] = yield exec('tail -n 100 ' + stderr);
    +        const args = [ '-n', '100', stderr ];
    +        this.logger.error('tail %s', args.join(' '));
    +        const [ stdout ] = yield execFile('tail', args);
             this.logger.error('Got error when startup: ');
             this.logger.error(stdout);
    -      } catch (_) {
    -        // nothing
    +      } catch (err) {
    +        this.logger.error('ignore tail error: %s', err);
           }
    +
           isSuccess = ignoreStdErr;
           this.logger.error('Start got error, see %s', stderr);
           this.logger.error('Or use `--ignore-stderr` to ignore stderr at startup.');
    
  • package.json+1 1 modified
    @@ -50,7 +50,7 @@
         "bin"
       ],
       "ci": {
    -    "version": "6, 8, 9"
    +    "version": "6, 8, 10"
       },
       "bug": {
         "url": "https://github.com/eggjs/egg/issues"
    
  • test/start.test.js+28 1 modified
    @@ -307,6 +307,7 @@ describe('test/start.test.js', () => {
           before(function* () {
             yield utils.cleanup(fixturePath);
             yield rimraf(logDir);
    +        yield rimraf(path.join(fixturePath, 'start-fail'));
             yield mkdirp(logDir);
           });
     
    @@ -315,6 +316,7 @@ describe('test/start.test.js', () => {
             yield utils.cleanup(fixturePath);
             yield rimraf(path.join(fixturePath, 'stdout.log'));
             yield rimraf(path.join(fixturePath, 'stderr.log'));
    +        yield rimraf(path.join(fixturePath, 'start-fail'));
           });
     
           it('should start', function* () {
    @@ -332,6 +334,30 @@ describe('test/start.test.js', () => {
             content = yield fs.readFile(stderr, 'utf-8');
             assert(content === '');
           });
    +
    +      it('should start with insecurity --stderr argument', function* () {
    +        const cwd = path.join(__dirname, 'fixtures/status');
    +        mm(process.env, 'ERROR', 'error message');
    +
    +        const stdout = path.join(fixturePath, 'start-fail/stdout.log');
    +        const stderr = path.join(fixturePath, 'start-fail/stderr.log');
    +        const malicious = path.join(fixturePath, 'start-fail/malicious');
    +        app = coffee.fork(eggBin, [
    +          'start', '--workers=1', '--daemon', `--stdout=${stdout}`,
    +          `--stderr=${stderr}; touch ${malicious}`,
    +          cwd,
    +        ]);
    +        // app.debug();
    +
    +        yield sleep(waitTime);
    +
    +        const content = yield fs.readFile(stdout, 'utf-8');
    +        assert(!content.match(/custom-framework started on http:\/\/127\.0\.0\.1:7001/));
    +        let exists = yield fs.exists(stderr);
    +        assert(!exists);
    +        exists = yield fs.exists(malicious);
    +        assert(!exists);
    +      });
         });
     
         describe('read cluster config', () => {
    @@ -520,10 +546,11 @@ describe('test/start.test.js', () => {
           if (isWin) stderr = stderr.replace(/\\/g, '\\\\');
     
           const app = coffee.fork(eggBin, [ 'start', '--daemon', '--workers=1' ], { cwd });
    -      // app.debug()
    +      // app.debug();
           // TODO: find a windows replacement for tail command
           if (!isWin) app.expect('stderr', /nodejs.Error: error message/);
           yield app.expect('stderr', new RegExp(`Start got error, see ${stderr}`))
    +        .expect('stderr', /Got error when startup/)
             .expect('code', 1)
             .end();
         });
    
  • .travis.yml+1 1 modified
    @@ -3,7 +3,7 @@ language: node_js
     node_js:
       - '6'
       - '8'
    -  - '9'
    +  - '10'
     install:
       - npm i npminstall && npminstall
     script:
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.