3

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?

DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127
  • I checked out docs for gitleaks and it shows the following exit codes: 0: no leaks, 1: leaks present, 2: error encountered. I'm wondering if the command is returning 1 for "leaks present" but the "exec" function is thinking that's an error. When you run the same command directly in the terminal, what's the exit code? – Richard Gieg Apr 15 '20 at 14:41
  • Ya that seems to be what the issue is. When I console log the `error` under the code 1 it dumps all the INFO of the leaks. Guess that means I need to figure out how to condition that as a response and not an error though and then resolve it. – DᴀʀᴛʜVᴀᴅᴇʀ Apr 15 '20 at 14:48
  • Does my comment qualify as an answer? If so I can add it as an answer. – Richard Gieg Apr 15 '20 at 14:52
  • I would use it as an answer if you write the resolution for the issue (a rewrite of the exec conditionalizing against the `error.code` of 1 and to resolve the error info). It would make a better Q&A or I can answer it. That way if anyone ever runs into the same issue with gitleaks they can see the issue and the resolution. Just my thought. – DᴀʀᴛʜVᴀᴅᴇʀ Apr 15 '20 at 14:54

1 Answers1

7

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)
}
})()
Richard Gieg
  • 1,276
  • 8
  • 17