Skip to content

ci: scan pull requests for credentials and injection with ThreatCrush - #2993

Open
ralyodio wants to merge 6 commits into
generalaction:mainfrom
ralyodio:threatcrush-scan
Open

ci: scan pull requests for credentials and injection with ThreatCrush#2993
ralyodio wants to merge 6 commits into
generalaction:mainfrom
ralyodio:threatcrush-scan

Conversation

@ralyodio

Copy link
Copy Markdown

Adds a pull-request workflow that scans the diff for hardcoded credentials,
injection, SSRF and unsafe deserialisation. Results go to the Security tab as
SARIF and to a comment on the pull request.

It is report-only. failOn is empty, so it annotates and never fails a build.
A repository with pre-existing findings should get a report on its first install,
not a blocked pull request — a gate that fires on everything gets switched off
within a day. Tighten it to critical,high in the workflow once any backlog is
triaged.

  • .github/workflows/threatcrush-scan.yml — the workflow
  • .github/scripts/threatcrush-to-sarif.py — a compatibility shim for CLI versions
    older than native SARIF output; unused once the installed CLI can emit it itself

Permissions are least-privilege (contents: read, pull-requests: write,
security-events: write). It runs on pull_request, not pull_request_target,
so contributor code never executes with your secrets in scope. The SARIF upload
is continue-on-error and degrades quietly where code scanning is unavailable.

Disclosure: I maintain ThreatCrush.
It is free and MIT, and the workflow installs it from npm — nothing here phones
home. If this is not something you want, closing it is the right answer, and I
will not send another.

@greptile-apps

greptile-apps Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds a report-only ThreatCrush pull-request workflow with SARIF upload, job-summary and PR-comment reporting, plus a compatibility converter for CLI releases without native SARIF.

  • Installs and runs ThreatCrush on pull-request checkouts.
  • Uploads SARIF to code scanning and as a retained workflow artifact.
  • Converts legacy terminal output into SARIF and optionally applies severity thresholds.
  • Publishes scan status and findings to the job summary and same-repository pull requests.

Confidence Score: 4/5

The compatibility parser’s fail-open undercounting path should be fixed before merging; dependency pinning and module-style cleanup are also recommended.

A completed legacy scan can declare findings that the parser silently drops, after which the workflow publishes valid-looking partial or empty SARIF instead of treating the scan as unrecognized.

Files Needing Attention: .github/scripts/threatcrush-to-sarif.py, .github/workflows/threatcrush-scan.yml

Security Review

The workflow executes mutable npm and GitHub Action references while holding pull-request and security-event write permissions. Pin the scanner to an exact reviewed release and actions to immutable commit SHAs. How this was verified: The workflow grants both write scopes before executing @profullstack/threatcrush@latest and multiple major-tag action references in the same job.

Important Files Changed

Filename Overview
.github/scripts/threatcrush-to-sarif.py Adds legacy-output SARIF conversion, but its completion check can accept and emit incomplete results when declared findings are not parsed.
.github/workflows/threatcrush-scan.yml Adds the complete scanning and reporting workflow; mutable executable dependencies and one repository-style violation require attention.

Fix All in Greploop

Fix All in Codex Fix All in Claude Code

Prompt To Fix All With AI
### Issue 1
.github/scripts/threatcrush-to-sarif.py:67-69
**Footer count permits partial results**

When an older CLI retains the completion footer but emits a missing, reordered, truncated, or renamed finding field, `parse` silently drops that record without comparing the declared count to the parsed count. The converter then publishes partial or empty SARIF, causing the PR report to undercount findings or report none and making a future `failOn` threshold evaluate only the parsed subset.

### Issue 2
.github/workflows/threatcrush-scan.yml:31
**Mutable code holds write permissions**

The job executes `@profullstack/threatcrush@latest` and mutable major-version action tags while holding pull-request and security-event write permissions. Pinning these dependencies to immutable reviewed versions prevents a changed or compromised release from modifying PR comments or security-event data with the job token.

**How this was verified:** The workflow grants both write scopes before executing the mutable npm package and action references in the same job.

### Issue 3
.github/workflows/threatcrush-scan.yml:224
**Inline script violates module convention**

The new GitHub Script block uses `require('fs')`, contrary to the repository rule requiring top-level imports and avoiding `require()`. This introduces a module-style exception that requires special handling during future maintenance.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "ci: add the ThreatCrush security scan wo..." | Re-trigger Greptile

Comment on lines +67 to +69
lines = ANSI.sub("", text).splitlines()
if not any(FOOTER.match(line) for line in lines):
raise Unrecognised("no scan-completion footer found")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Footer count permits partial results

When an older CLI retains the completion footer but emits a missing, reordered, truncated, or renamed finding field, parse silently drops that record without comparing the declared count to the parsed count. The converter then publishes partial or empty SARIF, causing the PR report to undercount findings or report none and making a future failOn threshold evaluate only the parsed subset.

Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/scripts/threatcrush-to-sarif.py
Line: 67-69

Comment:
**Footer count permits partial results**

When an older CLI retains the completion footer but emits a missing, reordered, truncated, or renamed finding field, `parse` silently drops that record without comparing the declared count to the parsed count. The converter then publishes partial or empty SARIF, causing the PR report to undercount findings or report none and making a future `failOn` threshold evaluate only the parsed subset.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code

Comment thread .github/workflows/threatcrush-scan.yml Outdated
- name: Install ThreatCrush
run: |
for attempt in 1 2 3; do
if npm install -g "@profullstack/threatcrush@latest"; then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 security Mutable code holds write permissions

The job executes @profullstack/threatcrush@latest and mutable major-version action tags while holding pull-request and security-event write permissions. Pinning these dependencies to immutable reviewed versions prevents a changed or compromised release from modifying PR comments or security-event data with the job token.

How this was verified: The workflow grants both write scopes before executing the mutable npm package and action references in the same job.

Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/threatcrush-scan.yml
Line: 31

Comment:
**Mutable code holds write permissions**

The job executes `@profullstack/threatcrush@latest` and mutable major-version action tags while holding pull-request and security-event write permissions. Pinning these dependencies to immutable reviewed versions prevents a changed or compromised release from modifying PR comments or security-event data with the job token.

**How this was verified:** The workflow grants both write scopes before executing the mutable npm package and action references in the same job.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code

lines.append("No findings.")

with open(os.environ["RUNNER_TEMP"] + "/threatcrush-comment.md", "w") as handle:
handle.write("\n".join(lines) + "\n")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Inline script violates module convention

The new GitHub Script block uses require('fs'), contrary to the repository rule requiring top-level imports and avoiding require(). This introduces a module-style exception that requires special handling during future maintenance.

Context Used: AGENTS.md (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/threatcrush-scan.yml
Line: 224

Comment:
**Inline script violates module convention**

The new GitHub Script block uses `require('fs')`, contrary to the repository rule requiring top-level imports and avoiding `require()`. This introduces a module-style exception that requires special handling during future maintenance.

**Context Used:** AGENTS.md ([source](https://github.com/generalaction/emdash/blob/main/AGENTS.md))

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Codex Fix in Claude Code

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant