node.jsmacospackage.jsongitleaks

Why is my exec command failing but works if the command is passed in the terminal?


For some reason I'm not understanding why I'm having an issue in my exec command and I believe I followed the documentation and examples I've referenced correctly. When I run this command in the terminal I do not have an issue:

gitleaks --repo=https://github.com/user/repo -v --username=foo --password=bar

but when I try to code it as a module so I can call upon it in package.json:

const { exec } = require("child_process")
const test = `gitleaks --repo=https://github.com/user/repo -v --username=foo --password=bar`

const execRun = (cmd) => {
  return new Promise((resolve, reject) => {
    exec(cmd, (error, stdout, stderr) => {
      if (error) reject(error)
      resolve(stdout ? stdout : stderr)
    })
  })
}

(async () => {
try {
  const testing = await execRun(test)
  console.log(testing)
} catch (e) {
  console.log(e)
}
})()

but I continue to get the error:

{ Error: Command failed: gitleaks --repo=https://github.com/user/repo -v --username=foo --password=bar

    at ChildProcess.exithandler (child_process.js:294:12)
    at ChildProcess.emit (events.js:198:13)
    at maybeClose (internal/child_process.js:982:16)
    at Socket.stream.socket.on (internal/child_process.js:389:11)
    at Socket.emit (events.js:198:13)
    at Pipe._handle.close (net.js:606:12)
  killed: false,
  code: 1,
  signal: null,
  cmd:
   'gitleaks --repo=https://github.com/user/repo -v --username=foo --password=bar' }

I've tried to research my issue to see if I'm missing something and read:

Why does my exec command fail but I can pass the same command in the terminal and it works?


Solution

  • When the exec function runs a command it examines the exit code from that command. It assumes that an exit code other than 0 is an error and thus passes the error in the callback. If gitleaks finds secrets in a repo then it exits with code 1.

    Something along these lines should work:

    const { exec } = require("child_process")
    const test = `gitleaks --repo=https://github.com/user/repo -v --username=foo --password=bar`
    
    const execRun = (cmd) => {
      return new Promise((resolve, reject) => {
        exec(cmd, (error, stdout, stderr) => {
          if (error) {
            if (error.code === 1) {
              // leaks present
              resolve(stdout);
            } else {
              // gitleaks error
              reject(error);
            }
          } else {
            // no leaks
            resolve(stdout);
          }
        })
      })
    }
    
    (async () => {
    try {
      const testing = await execRun(test)
      console.log(testing)
    } catch (e) {
      console.log(e)
    }
    })()