Skip to content

ci(security): raise an issue for what the nightly scan reports, and run in the merge queue - #2390

Merged
Gregory91G merged 7 commits into
mainfrom
ci/trufflehog-nightly-issues
Aug 11, 2026
Merged

ci(security): raise an issue for what the nightly scan reports, and run in the merge queue#2390
Gregory91G merged 7 commits into
mainfrom
ci/trufflehog-nightly-issues

Conversation

@Gregory91G

@Gregory91G Gregory91G commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Refs #2301. Builds on #2351, now merged.

A finding that reaches main is announced exactly once, in the pull request that introduced it, and never again: the blocking job only ever scans a pull request's own commits, so later pull requests never see it. The nightly job does see it, every night, for as long as it is there — but it reports and exits zero, and nobody opens a run summary. A missed secret therefore looks the same as a clean repository.

Two changes.

An issue per finding, assigned to whoever brought it

trufflehog_gate.py already computes the findings that are not in the baseline; it now also writes them to a JSON file when a sixth argument is given. Values are not included — the file carries the detector, the path, the line, the commit and the fingerprint.

trufflehog_notify.py reads that file, resolves each commit to a GitHub login through the commits API, and opens one issue per fingerprint, assigned to that person. One issue per fingerprint rather than a digest, because they close independently and each belongs to a different author; the fingerprint sits in the title, so an already-open issue suppresses the next night's duplicate.

The assignee is resolved in two steps. GitHub can name a commit's author only when the address inside the commit is attached to an account, and a work address often is not — a quarter of this repository's commits resolve to nobody that way. The pull request a commit arrived with names an account either way, so it is the second route, and it covers every commit that reaches main through review.

Neither the issue nor the scripts name an address. The body links the GitHub profile of whoever is resolved and the commit itself; when nothing resolves — a commit pushed straight to a branch — it says so and links the commit, which is where the author is visible anyway. An earlier revision carried a file mapping work addresses to logins; it is gone, because a single harvestable list of live addresses in a public repository is worth more than the historical commits it covered.

The fix for an address that resolves to nobody belongs with its owner: adding it under Settings → Emails attributes it, past commits included, and needs no table here. Attribution works from any verified address on an account, not only the primary one.

The blocking job runs in the merge queue

A required status check has to produce a result inside the merge queue, where there is no pull_request event. The job now also triggers on merge_group, and takes its scan range from github.event.merge_group.base_sha rather than HEAD^1 — on a queue branch the first parent is the previous entry, not the base.

The two nightly jobs are pinned to schedule and workflow_dispatch. They used to run on anything that was not a pull request, which would have meant a full-history scan and a GitHub API sweep on every entry the queue builds.

This does not make the check required — that is a ruleset change, and it belongs after this has run in the queue at least once.

Test plan

  • The gate writes the JSON only when asked, and its verdict is unchanged: 272 known findings against the seeded baseline → exit 0, empty list; the same corpus against an empty baseline → 272 entries, keys detector, verified, commit, file, line, email, fp
  • trufflehog_notify.py --dry-run over real findings assigns through both routes: aleksdotbar by commit author, ktursunov by pull request author, and a commit with neither is left unassigned
  • Author resolution measured over all 53 distinct commits behind the findings: 35 by commit author, 10 by pull request author, 8 by neither
  • No address appears in the issue body, the scripts or the JSON the gate writes
  • The commit id reaches the API whole; only the summary table and the issue body shorten it
  • python -m py_compile on both scripts; the workflow parses and keeps its five, four and two steps per job
  • actionlint 1.7.12 on this workflow and on every workflow in the repository — exit 0
  • secrets (diff) green on this pull request
  • The job produces a result on a merge_group event — only observable once this is on the default branch
  • A nightly run with a finding outside the baseline opens an assigned issue

Summary by CodeRabbit

  • New Features

    • Added optional redacted JSON output for newly detected secrets.
    • Added automated issue reports for unaddressed findings, with dry-run previews and author attribution.
    • Added merge queue scanning support.
    • Added duplicate-finding detection to prevent repeated issue reports.
  • Bug Fixes

    • Limited historical and API scans to scheduled or manually triggered runs.
    • Improved tracking of findings against an established baseline.
    • Preserved complete commit identifiers in generated finding data.

…un in the merge queue

The nightly jobs never fail a run, so a finding outside the baseline was a line
in a summary nobody opens: it surfaced once, in the pull request that
introduced it, and never again — the diff job only ever sees a pull request's
own commits. Now each such finding gets an issue assigned to the author of the
commit it arrived with, and an open one suppresses the next night's duplicate.

The blocking job also runs on merge_group, which is what a required status
check needs: inside the queue there is no pull_request event, and the range
comes from the event rather than from HEAD^1. The two nightly jobs are
restricted to schedule and manual runs so the queue does not trigger a full
history scan.

Refs #2301

Signed-off-by: Gregory Gogin <grigoriy.gogin@constructor.tech>
@Gregory91G Gregory91G self-assigned this Aug 10, 2026
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3741a400-750d-49bb-86a7-321efde26021

📥 Commits

Reviewing files that changed from the base of the PR and between b14af5f and e58f5b5.

📒 Files selected for processing (2)
  • .github/scripts/trufflehog_gate.py
  • .github/scripts/trufflehog_notify.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/scripts/trufflehog_notify.py
  • .github/scripts/trufflehog_gate.py

📝 Walkthrough

Walkthrough

The TruffleHog workflow now scans merge groups, exports redacted findings, and creates GitHub issues for new findings. Scheduled and manual history/API scans use restricted triggers. Notifications resolve commit authors and support dry-run mode.

Changes

TruffleHog notifications

Layer / File(s) Summary
Redacted finding export
.github/scripts/trufflehog_gate.py
The gate accepts an optional JSON output path, preserves full commit identifiers internally, and writes non-allowlisted findings without secret values.
GitHub issue notification
.github/scripts/trufflehog_notify.py
The script skips fingerprints with open issues, resolves commit authors with caching, and creates or previews assigned issues with remediation metadata.
Workflow scan integration
.github/workflows/trufflehog.yml
The workflow supports merge-group diff scans and runs history/API scans only on scheduled or manual events. History findings are written to new-findings.json and passed to the notification script.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TruffleHog
  participant trufflehog_gate.py
  participant trufflehog_notify.py
  participant GitHub
  TruffleHog->>trufflehog_gate.py: Scan findings
  trufflehog_gate.py->>trufflehog_notify.py: Write redacted new-findings.json
  trufflehog_notify.py->>GitHub: Check fingerprints and resolve authors
  trufflehog_notify.py->>GitHub: Create or preview assigned issues
Loading

Possibly related PRs

Suggested reviewers: cyberantonz

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the two primary changes: creating issues from nightly scan findings and enabling merge queue scanning.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/trufflehog-nightly-issues

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/scripts/trufflehog_gate.py:
- Around line 90-92: Update the JSON export flow in trufflehog_gate.py to
preserve the full f["commit"] identifier in new before any formatting; apply
[:8] only when rendering the Markdown table or issue body, so
trufflehog_notify.py receives the complete SHA for GitHub API resolution.

In @.github/scripts/trufflehog_notify.py:
- Around line 84-85: Update the issue-creation flow around gh() so an empty
result from gh issue create is treated as a failure: report the failure without
incrementing created, and track failed creations separately for final status
reporting.
- Around line 38-51: The fallback in body_for must not publish Git author email
addresses; replace the f.get("email") branch with neutral wording such as
“unlinked Git author; inspect commit metadata,” while preserving linked-login
and commit-author fallbacks. In .github/scripts/trufflehog_gate.py lines 75-77,
stop adding email to NEW.json unless the required privacy basis is documented
elsewhere.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ec4c4181-299e-4626-98ea-52e07f5634c2

📥 Commits

Reviewing files that changed from the base of the PR and between 41af90f and 8569e80.

📒 Files selected for processing (3)
  • .github/scripts/trufflehog_gate.py
  • .github/scripts/trufflehog_notify.py
  • .github/workflows/trufflehog.yml

Comment thread .github/scripts/trufflehog_gate.py
Comment thread .github/scripts/trufflehog_notify.py Outdated
Comment thread .github/scripts/trufflehog_notify.py Outdated
Comment on lines +84 to +85
print(gh(*args) or f"failed to open an issue for {f['fp']}")
created += 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Do not count a failed issue creation as opened.

gh() returns an empty string when gh issue create fails. Line 84 reports that failure, but Line 85 still increments created. The final status can therefore report issues as opened when no issue exists. Track failed creations separately.

Proposed fix
-    created = skipped = 0
+    created = skipped = failed = 0
...
-        print(gh(*args) or f"failed to open an issue for {f['fp']}")
-        created += 1
+        url = gh(*args)
+        if url:
+            print(url)
+            created += 1
+        else:
+            print(f"failed to open an issue for {f['fp']}")
+            failed += 1
...
-    print(f"{created} issue(s) {'would be ' if dry else ''}opened, {skipped} already tracked")
+    print(
+        f"{created} issue(s) {'would be ' if dry else ''}opened, "
+        f"{skipped} already tracked, {failed} failed"
+    )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/scripts/trufflehog_notify.py around lines 84 - 85, Update the
issue-creation flow around gh() so an empty result from gh issue create is
treated as a failure: report the failure without incrementing created, and track
failed creations separately for final status reporting.

@Gregory91G
Gregory91G requested a review from cyberantonz August 10, 2026 11:08
…mit id whole

Fixes a problem found by CodeRabbit on this pull request: the commit was
truncated to eight characters at parse time and that prefix was then used as
the API identifier. It stays whole now and is shortened only where rendered.

Assignment used to rely on the commit author alone, which GitHub can only
attribute when the address in the commit is attached to an account — a work
address usually is not, and a quarter of the corpus resolved to nobody. The
pull request the commit arrived with names an account either way, and
.github/trufflehog-authors.txt covers the rest until those addresses are
attached to their accounts.

Over the 53 distinct commits behind the current findings: 35 resolve by commit
author, 10 by pull request author, 7 by the map, 1 by nothing at all.

Refs #2301

Signed-off-by: Gregory Gogin <grigoriy.gogin@constructor.tech>

@cyberantonz cyberantonz left a comment

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.

You provide real email addresses of real people. I think it is not the right way

Comment thread .github/scripts/trufflehog_notify.py Outdated


def main() -> int:
new_json, repo, author_map = sys.argv[1], sys.argv[2], sys.argv[3]

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.

There is argparse library for this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

thanks, fixed

Comment thread .github/scripts/trufflehog_notify.py Outdated
print(gh(*args) or f"failed to open an issue for {f['fp']}")
created += 1

print(f"{created} issue(s) {'would be ' if dry else ''}opened, {skipped} already tracked")

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.

No pre-commit installed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

thanks, fixed

The map held live work addresses in a public repository. They are already in
the commit history, but a single harvestable list is a different thing, and it
bought only historical commits: a finding from a new commit resolves through
the pull request it arrived with.

The issue body now links the GitHub profile and the commit rather than naming
an address, and the gate no longer carries the author's address at all. An
address that resolves to nobody is fixed at the source, by adding it under
Settings → Emails, which reattributes past commits too.

Refs #2301

Signed-off-by: Gregory Gogin <grigoriy.gogin@constructor.tech>
@Gregory91G

Gregory91G commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

Emails are removed, now attributions of issues are based only on emails registered in the accounts

… linters

Both from review. argparse gives the script a usage line and rejects a
mistyped flag, which the manual sys.argv walk silently read as "not --dry-run";
it also matches discover-image-matrix.py, the other script in this repository
that takes arguments.

The rest is what pre-commit would have caught before the review did: ruff at
the pinned v0.15.21 reported eleven violations across the two scripts and
ruff-format rewrote both. Prints stay, marked as the sibling scripts mark
them — they are how a CI script reports.

Refs #2301

Signed-off-by: Gregory Gogin <grigoriy.gogin@constructor.tech>
@Gregory91G
Gregory91G requested a review from cyberantonz August 10, 2026 15:36
@Gregory91G
Gregory91G requested a review from a team as a code owner August 10, 2026 22:52
@Gregory91G
Gregory91G enabled auto-merge August 11, 2026 08:04
@Gregory91G
Gregory91G added this pull request to the merge queue Aug 11, 2026
Merged via the queue into main with commit bf73b7e Aug 11, 2026
25 checks passed
@Gregory91G
Gregory91G deleted the ci/trufflehog-nightly-issues branch August 11, 2026 08:31
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.

2 participants