Skip to content

Fix the PG version check so a detected issue is reported instead of failing the job - #11967

Open
Raffi1202 wants to merge 3 commits into
iNavFlight:maintenance-10.xfrom
Raffi1202:fix/pg-version-check-output-10x
Open

Raffi1202 wants to merge 3 commits into
iNavFlight:maintenance-10.xfrom
Raffi1202:fix/pg-version-check-output-10x

Conversation

@Raffi1202

Copy link
Copy Markdown

Problem

maintenance-10.x ships a Parameter Group check that cannot report a finding. The workflow guard at .github/workflows/pg-version-check.yml:45 requires ^### in the checker's stdout, and the github-script filter at :77 keys on ###, but .github/scripts/check-pg-versions.py:187 prints PG version issue: .... Exit code 1 therefore always takes the exit 2 path: raw stdout dump, no PR comment, failed job, in exactly the case the tooling exists for.

Introduced in #11885: d42addb88f added the ### guard for the old shell checker's Markdown headings, 5efd794951 then rewrote the checker in Python with no marker in its output.

Reproduction

Throwaway repo, one struct changed without a version bump: the checker exits 1 and prints the finding, the workflow step exits 2, the comment step never runs. With this PR the step exits 0 and records exit_code=1 for the comment step.

Changes

Three commits by @sensei-hacker, cherry-picked unmodified from #11951 (the release/9.1 backport):

  • e2762ab638 - both markers keyed on PG version issue:; check-pg-versions.py:17 decodes git output with errors='replace'; new fixture that runs the workflow's own guard against the checker's real output, so the two cannot drift apart again
  • f874de624a - check-pg-versions.py:149 gains --no-renames; without it a struct whose header was renamed and whose layout changed was silently excluded from the check
  • e47bf801ae - comment posting moves to a workflow_run consumer; the pull_request token is read-only for fork PRs, so the inline github-script step fails with 403 there

172174158b is deliberately left out, it adds release/9.1 to the trigger list and is release/9.1 only.

Test

python3 .github/scripts/test-check-pg-versions.py passes 18/18, including the two new fixtures. Run under Linux; on Windows the harness passes a Windows path to bash and the test cannot run.

Related

This duplicates work already in #11951. If that merges first, the next release/9.1 to maintenance-10.x sync carries these commits over and this PR should be closed. Opened because maintenance-10.x ships the broken guard today.

Two commits in this same PR chain drifted apart: d42addb added a
workflow guard requiring '### ' in the checker's stdout to treat exit
code 1 as a normal detection, but 5efd794 rewrote the checker in
Python, which prints "PG version issue: ..." with no '###' anywhere.
As a result the workflow hard-fails (exit 2, raw stdout dump) instead
of posting the intended PR comment on every genuine detection - the
one case this tooling exists for. Verified by running the workflow's
own guard logic against the checker's real "issue found" output before
and after this fix. Same fix applied to the PR comment step's JS
output filter, which keyed on the same stale '###' marker.

Also decode git subprocess output with errors='replace' instead of the
default strict UTF-8, since a single non-ASCII byte (e.g. a smart quote
in a comment) anywhere in a touched .c/.h file would otherwise raise an
uncaught UnicodeDecodeError and hard-fail the check with a message that
doesn't name the offending file.

Added a regression fixture that runs the workflow's actual guard logic
(read from the workflow YAML, not duplicated) against a real detected
issue, so the two can't silently diverge again.
git diff --name-only collapses renames to the new path, so a persisted
struct whose header was renamed and its layout changed never loaded its
old definition and was silently excluded from the version-bump check. Use
--no-renames so both old and new paths are collected, and add a rename
regression fixture.
The pull_request workflow's GITHUB_TOKEN is read-only for fork-originated
runs, so its github-script comment step failed with 403 and hard-failed the
job instead of warning. Move comment posting to a privileged workflow_run
consumer: the check workflow uploads the checker output and PR number as
artifacts, and the consumer downloads them and posts/updates the comment
(mirroring pr-test-builds.yml).
@qodo-code-review

Copy link
Copy Markdown
Contributor

ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Report PG Version Findings and Support Fork PR Comments

🐞 Bug fix 🧪 Tests ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

AI Description

• Aligns workflow detection with checker output so findings no longer fail jobs.
• Detects renamed struct layouts and tolerates non-UTF-8 Git output.
• Moves commenting to an artifact-consuming workflow for fork PR compatibility.
Diagram

sequenceDiagram
    actor PR as Pull Request
    participant Check as Check Workflow
    participant Checker as PG Checker
    participant Store as Artifact Store
    participant Comment as Comment Workflow
    participant API as GitHub API
    PR->>Check: Trigger check
    Check->>Checker: Inspect C/H changes
    Checker-->>Check: Return status and output
    Check->>Store: Upload result artifact
    Check-->>Comment: Emit completion event
    Comment->>Store: Download result artifact
    alt Version issue found
        Comment->>API: Create or update comment
    else No issue found
        Comment-->>Comment: Skip comment
    end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use pull_request_target safely
  • ➕ Can post comments directly without transferring artifacts
  • ➕ Avoids a second workflow_run handoff
  • ➖ Requires strict separation from untrusted fork code
  • ➖ Easy to introduce privileged code-execution vulnerabilities
  • ➖ Complicates checking the proposed revision safely
2. Comment only on trusted PRs
  • ➕ Keeps the workflow simple and avoids privileged consumers
  • ➕ Requires no artifact exchange
  • ➖ Fork PRs would receive no automated findings
  • ➖ Leaves the reported compatibility bug unresolved

Recommendation: Keep the workflow_run artifact handoff. It preserves an unprivileged execution context for PR code while allowing a trusted workflow to comment on fork PRs; pull_request_target would reduce workflow count but carries substantially greater security risk.

Files changed (4) +185 / -89

Bug fix (2) +17 / -88
check-pg-versions.pyHarden Git output handling and renamed-file detection +2/-2

Harden Git output handling and renamed-file detection

• Decodes Git output as UTF-8 with replacement for malformed bytes instead of raising an exception. Disables rename detection so renamed headers with changed struct layouts remain visible to the version checker.

.github/scripts/check-pg-versions.py

pg-version-check.ymlRecognize findings and publish results as artifacts +15/-86

Recognize findings and publish results as artifacts

• Changes the success guard to recognize the checker's 'PG version issue:' marker. Replaces inline commenting with short-lived artifact publication and removes unnecessary pull-request write permission from the checker workflow.

.github/workflows/pg-version-check.yml

Tests (1) +46 / -1
test-check-pg-versions.pyCover renamed headers and the real workflow guard +46/-1

Cover renamed headers and the real workflow guard

• Adds regression coverage for renamed headers containing unversioned layout changes. Extracts and executes the workflow's actual shell guard against real checker output to prevent marker drift.

.github/scripts/test-check-pg-versions.py

Other (1) +122 / -0
pg-version-check-comment.ymlAdd privileged workflow for PG warning comments +122/-0

Add privileged workflow for PG warning comments

• Adds a workflow_run consumer that downloads the check artifact, recognizes PG findings, and creates or updates the PR warning comment. Running separately supplies write permissions for fork-originated pull requests without executing their code in the privileged workflow.

.github/workflows/pg-version-check-comment.yml

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Attackers can redirect bot comments 🐞 Bug ⛨ Security
Description
The comment workflow reads prNumber from the downloaded pr_number.txt artifact instead of
deriving it from the trusted workflow_run event. Because the producing pull-request workflow and
its executed scripts are controlled by the contributor, a malicious fork can supply another pull
request number and use the write-enabled workflow to create or update a bot-authored comment there.
Code

.github/workflows/pg-version-check-comment.yml[39]

+            const prNumber = Number(fs.readFileSync('pr_number.txt', 'utf8').trim());
Evidence
The producer checks out and executes contributor-controlled code, then uploads files as an artifact.
The new write-enabled workflow reads its target number from that artifact and passes it directly to
the comment APIs, so the privileged write is not bound to the pull request that initiated the
completed run.

.github/workflows/pg-version-check.yml[24-37]
.github/workflows/pg-version-check.yml[56-72]
.github/workflows/pg-version-check-comment.yml[18-40]
.github/workflows/pg-version-check-comment.yml[88-117]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The privileged comment workflow trusts `pr_number.txt` from an artifact produced by pull-request-controlled code, allowing a contributor to redirect the bot's write access to another pull request.

## Fix Focus Areas
- .github/workflows/pg-version-check-comment.yml[34-40]
- .github/workflows/pg-version-check.yml[61-71]

## Recommended Fix
Derive and validate the pull request number from `github.event.workflow_run.pull_requests` or another trusted GitHub API association for the completed run. Reject runs with no unique associated pull request, and stop using an artifact-provided value to select the API write target.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: ⚖️ Balanced: Downgraded extended -> standard: change is below the extended eligibility bar (hunks 9/18, lines 274/200; both must reach the floor). Router rationale: This changes security-sensitive GitHub Actions permissions and introduces a separate workflow_run artifact-to-comment path alongside checker, parsing, and test logic, creating several independent, easy-to-miss behavioral and privilege-boundary risks.

Grey Divider

Tip of the day
💡 Did you know, you can type 'qodo, fix this' on a finding and the fix lands right on your PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

with:
script: |
const fs = require('fs');
const prNumber = Number(fs.readFileSync('pr_number.txt', 'utf8').trim());

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Attackers can redirect bot comments 🐞 Bug ⛨ Security

The comment workflow reads prNumber from the downloaded pr_number.txt artifact instead of
deriving it from the trusted workflow_run event. Because the producing pull-request workflow and
its executed scripts are controlled by the contributor, a malicious fork can supply another pull
request number and use the write-enabled workflow to create or update a bot-authored comment there.
Agent Prompt
## Issue description
The privileged comment workflow trusts `pr_number.txt` from an artifact produced by pull-request-controlled code, allowing a contributor to redirect the bot's write access to another pull request.

## Fix Focus Areas
- .github/workflows/pg-version-check-comment.yml[34-40]
- .github/workflows/pg-version-check.yml[61-71]

## Recommended Fix
Derive and validate the pull request number from `github.event.workflow_run.pull_requests` or another trusted GitHub API association for the completed run. Reject runs with no unique associated pull request, and stop using an artifact-provided value to select the API write target.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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