Skip to content

Silent findings_count=0 fallback when jq is unavailable can mask real findings #129

Description

@kevingorman1000

Summary

In action.yml, the "Install dependencies" step installs jq via sudo apt-get install -y jq with no check that it actually succeeded:

- name: Install dependencies
  shell: bash
  run: |
    ...
    sudo apt-get update && sudo apt-get install -y jq

Later, in the "Run ClaudeCode scan" step, the results-parsing logic uses jq to check for an error and to count findings, with a fallback that silently defaults to 0 on any jq failure (including "command not found"):

if jq -e '.error' claudecode/claudecode-results.json > /dev/null 2>&1; then
  ...
else
  CLAUDECODE_FINDINGS_COUNT=$(jq -r '.findings | if . == null then 0 else length end' claudecode/claudecode-results.json 2>/dev/null || echo "0")
  ...
fi

If jq is missing or broken (e.g. the apt-get install step failed or was silently no-op'd by the runner's environment — see below), jq -e '.error' ... fails to even execute, so the if branch is skipped and control falls into the else branch. There, jq -r '.findings | ...' 2>/dev/null || echo \"0\" also fails (jq not found), and the || echo \"0\" fallback kicks in — reporting findings_count=0 even when claudecode-results.json actually contains real findings.

This means: if jq is unavailable for any reason, a scan that found real vulnerabilities gets reported as a clean pass (0 findings), with no warning or error surfaced anywhere in the job output. That's a meaningful blind spot for a security-scanning action — a broken dependency degrades to "looks clean" instead of "scan result unknown/untrusted."

How we hit this

On a self-hosted runner in our org, the sudo apt-get install -y jq step doesn't actually install jq (environment-specific sudo restriction), but it also doesn't fail the step or the job — so this went unnoticed until we traced through the parsing logic while debugging an unrelated wrapper-workflow bug. We haven't yet observed a run where jq was missing and real findings existed, but the code path is there and would silently swallow them.

Suggested fix

  • Verify jq is actually available after the install step (command -v jq or check the install step's exit code) and fail the job loudly if it isn't, rather than deferring to a silent per-call fallback.
  • Alternatively/additionally, change the results-parsing fallback so a jq failure (as opposed to a genuinely empty/null .findings array) is distinguishable from "0 real findings" — e.g. exit non-zero / set an explicit results-error output rather than defaulting findings_count to \"0\".

Happy to help test a fix if useful.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions