Skip to content

Validate GitHub PAT before use in github_dl.py - #575

Open
clcollins wants to merge 5 commits into
openshift:masterfrom
clcollins:validate-github-token
Open

Validate GitHub PAT before use in github_dl.py#575
clcollins wants to merge 5 commits into
openshift:masterfrom
clcollins:validate-github-token

Conversation

@clcollins

@clcollins clcollins commented Jul 21, 2026

Copy link
Copy Markdown
Member

Summary

  • Add upfront token validation against the GitHub /rate_limit endpoint to fail fast with a clear error message when an invalid or expired token is provided
  • Fix a None dereference crash in list_assets() when get_url_with_authentication() returns None on non-200 responses
  • Fix a None dereference crash in get_checksum() — same pattern as list_assets(), missed in the original fix
  • Token validation runs immediately after token resolution in main(), before any download or quota logic

Test plan

  • Build container with a valid GITHUB_TOKEN — should succeed as before
  • Build container with an invalid GITHUB_TOKEN (e.g., GITHUB_TOKEN=bad-token) — should fail with clear error: "Error: GitHub token is invalid or expired (HTTP 401)"
  • Build container with no GITHUB_TOKEN — should proceed without authentication as before (no validation call made)

Pre-existing bugs fixed

These bugs existed on master before this PR and are fixed opportunistically:

  • Missing import time: get_url_with_authentication() calls time.sleep() on retry (line 103) but the time module was never imported, causing a NameError crash on any 5xx retry path
  • get_checksum() None dereference: get_url_with_authentication() can return None (on max retries or 4xx errors) but get_checksum() accessed response.content without a None guard, causing an AttributeError crash when downloading checksum files failed

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Added proactive validation of GitHub bearer tokens (including basic rate-limit checks) before running authenticated operations.
    • Hardened the asset download and checksum retrieval flows to safely handle upstream failures or missing responses without crashing.
    • Trimmed whitespace from token inputs and now exits early with an error when token validation fails (e.g., unauthorized/forbidden/rate-limited).

@openshift-ci
openshift-ci Bot requested review from AlexSmithGH and tnierman July 21, 2026 22:18
@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 21, 2026
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The downloader validates supplied GitHub tokens through the rate-limit API, trims token input, exits when validation fails, and handles missing responses during asset and checksum retrieval.

Changes

GitHub download hardening

Layer / File(s) Summary
Token validation and startup gate
utils/dockerfile_assets/github_dl.py
Adds rate-limit token validation, trims secret and environment token values, enables retry sleep support, and exits with status 1 when validation fails.
Missing authenticated response handling
utils/dockerfile_assets/github_dl.py
Returns empty asset and checksum results when authenticated URL retrieval returns None.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant main
  participant validate_token
  participant GitHub
  participant list_assets
  participant get_checksum
  main->>validate_token: Validate supplied token
  validate_token->>GitHub: Request rate-limit endpoint
  GitHub-->>validate_token: Return rate-limit response
  validate_token-->>main: Return validation result
  main->>list_assets: Retrieve assets
  list_assets-->>main: Return assets or empty list
  main->>get_checksum: Retrieve checksum
  get_checksum-->>main: Return checksum or empty string
Loading

Suggested reviewers: tnierman, alexsmithgh


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (2 errors)

Check name Status Explanation Resolution
Ote Binary Stdout Contract ❌ Error FAIL: main() and validate_token() use print() to stdout (e.g. lines 265, 297, 48, 77), so the binary can emit non-JSON stdout during process-level execution. Move all user-facing messages to stderr or a logger configured to stderr, and keep stdout reserved for JSON only; silence success/info prints in process-level code.
No-Sensitive-Data-In-Logs ❌ Error validate_token() logs raw exceptions and response.text, which can leak internal hostnames or response details. Sanitize those prints: log only exception type/status code, and avoid raw response.text or exception strings.
✅ Passed checks (13 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly captures the main change: validating GitHub PATs before use in github_dl.py.
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.
Stable And Deterministic Test Names ✅ Passed Only utils/dockerfile_assets/github_dl.py changed; no Ginkgo test titles were added or modified.
Test Structure And Quality ✅ Passed No Ginkgo test files were changed in this PR; only utils/dockerfile_assets/github_dl.py was modified.
Microshift Test Compatibility ✅ Passed Only utils/dockerfile_assets/github_dl.py changed; no Ginkgo e2e tests or MicroShift-sensitive APIs/features were added.
Single Node Openshift (Sno) Test Compatibility ✅ Passed Only a Python utility file changed; no Ginkgo/e2e tests were added or modified, so there’s nothing SNO-specific to flag.
Topology-Aware Scheduling Compatibility ✅ Passed Only utils/dockerfile_assets/github_dl.py changed; it adds token validation and None guards, with no manifests/controllers or scheduling fields.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed PR only changes a Python utility; no new Ginkgo/e2e tests or IPv4/external-network assumptions were added.
No-Weak-Crypto ✅ Passed PASS: The patch doesn't add weak crypto or secret comparisons; the existing MD5 checksum path is unchanged.
Container-Privileges ✅ Passed Only the Python helper changed; no container/K8s manifests or privilege settings were added or modified.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@chamalabey

Copy link
Copy Markdown

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Jul 21, 2026
@openshift-ci

openshift-ci Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: chamalabey, clcollins

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:
  • OWNERS [chamalabey,clcollins]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@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: 2

🤖 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 `@utils/dockerfile_assets/github_dl.py`:
- Around line 46-56: Update validate_token() so only HTTP 401 reports the token
as invalid or expired. Handle HTTP 403 and 429 as rate-limit or temporary abuse
blocks, surfacing the response status and details without instructing users to
replace GITHUB_TOKEN; preserve the existing unexpected-response handling for
other statuses.
- Line 44: Update the GitHub probe request in the surrounding function to pass
an explicit timeout, catch requests.exceptions.RequestException, and return
False on request failures. Also revise the 403 handling so it returns False
without describing the token as rejected, since the response may indicate rate
limiting or temporary blocking.
🪄 Autofix (Beta)

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: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d097dd19-f9ba-4d7b-b07c-d66afb17b175

📥 Commits

Reviewing files that changed from the base of the PR and between efde56c and d15ede3.

📒 Files selected for processing (1)
  • utils/dockerfile_assets/github_dl.py

Comment thread utils/dockerfile_assets/github_dl.py Outdated
Comment thread utils/dockerfile_assets/github_dl.py
@openshift-ci openshift-ci Bot removed the lgtm Indicates that a PR is ready to be merged. label Jul 22, 2026
@openshift-ci

openshift-ci Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

New changes are detected. LGTM label has been removed.

@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: 2

🤖 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 `@utils/dockerfile_assets/github_dl.py`:
- Around line 239-249: Update token loading in the CI secret and GITHUB_TOKEN
environment-variable branches to treat stripped empty strings as absent,
preserving the existing token value or unauthenticated flow. Ensure
whitespace-only values do not overwrite a valid token or satisfy later
token-presence validation.
- Around line 62-70: Validate that remaining is an int immediately after
extracting it in the rate-limit handling block, before the remaining < 37
comparison. For None, strings, or other non-integer values, print the existing
malformed-response error and return False; preserve the current threshold
behavior for valid integers.
🪄 Autofix (Beta)

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: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 2684f39d-da77-4ff9-9354-d486d624ab5b

📥 Commits

Reviewing files that changed from the base of the PR and between d15ede3 and 5b3c1cf.

📒 Files selected for processing (1)
  • utils/dockerfile_assets/github_dl.py

Comment thread utils/dockerfile_assets/github_dl.py
Comment thread utils/dockerfile_assets/github_dl.py Outdated

@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: 1

🤖 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 `@utils/dockerfile_assets/github_dl.py`:
- Around line 239-249: Update token loading in the CI secret and GITHUB_TOKEN
environment-variable branches so stripped values are assigned to args.token only
when non-empty; preserve any previously loaded valid token when a source is
blank or whitespace-only.
🪄 Autofix (Beta)

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: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 83b571d2-503f-4e29-8916-a5b6712e7397

📥 Commits

Reviewing files that changed from the base of the PR and between 5b3c1cf and a17f5ec.

📒 Files selected for processing (1)
  • utils/dockerfile_assets/github_dl.py

Comment thread utils/dockerfile_assets/github_dl.py Outdated
@clcollins

Copy link
Copy Markdown
Member Author

/retest

@clcollins
clcollins force-pushed the validate-github-token branch from 0efc1bc to f2f6f9d Compare July 27, 2026 21:32

@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: 1

🧹 Nitpick comments (1)
utils/dockerfile_assets/github_dl.py (1)

63-75: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Read resources.core.remaining instead of relying only on legacy rate.

A missing rate object currently defaults remaining to 0, causing valid responses to be reported as exhausted. GitHub documents resources.core as the canonical field and removes rate in API version 2026-03-10; add a resources.core lookup with a legacy fallback and reject missing values explicitly. (docs.github.com)

Proposed fix
-        remaining = response.json().get("rate", {}).get("remaining", 0)
+        payload = response.json()
+        rate = payload.get("resources", {}).get("core")
+        if rate is None:
+            rate = payload.get("rate")
+        remaining = rate.get("remaining") if isinstance(rate, dict) else None
🤖 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 `@utils/dockerfile_assets/github_dl.py` around lines 63 - 75, Update the
rate-limit extraction in the response handling block to read
resources.core.remaining first, falling back to legacy rate.remaining only when
needed. Do not default missing fields to zero; explicitly treat a missing or
non-integer remaining value as a malformed response, while preserving the
existing threshold check and error behavior.

Source: MCP tools

🤖 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 `@utils/dockerfile_assets/github_dl.py`:
- Line 48: Update the GitHub token-validation error handling around the existing
print statement to avoid logging the raw exception or its message. Emit only a
sanitized fixed message or the exception type, while preserving the failure
indication and surrounding control flow.

---

Nitpick comments:
In `@utils/dockerfile_assets/github_dl.py`:
- Around line 63-75: Update the rate-limit extraction in the response handling
block to read resources.core.remaining first, falling back to legacy
rate.remaining only when needed. Do not default missing fields to zero;
explicitly treat a missing or non-integer remaining value as a malformed
response, while preserving the existing threshold check and error behavior.
🪄 Autofix (Beta)

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: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 47c1f61f-28d2-4013-b987-1806240ebc15

📥 Commits

Reviewing files that changed from the base of the PR and between 0efc1bc and f2f6f9d.

📒 Files selected for processing (1)
  • utils/dockerfile_assets/github_dl.py

Comment thread utils/dockerfile_assets/github_dl.py
clcollins and others added 5 commits July 28, 2026 10:00
Add upfront token validation against the GitHub /rate_limit endpoint
to fail fast with a clear error message when an invalid or expired
token is provided. Also fix a None dereference crash in list_assets
when the API returns a non-200 response.

Created with assistance from Claude 🤖 <claude@anthropic.com>

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Christopher Collins <collins.christopher@gmail.com>
- Add 10s timeout and RequestException handling to prevent stalled builds
- Treat HTTP 403/429 as rate-limit/blocking, not invalid token
- Check remaining API calls after validation (fail if < 37)
- Handle malformed rate_limit API responses
- Strip whitespace from file-read and env var tokens
- Remove extraneous f-string prefix on 401 message

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Christopher Collins <collins.christopher@gmail.com>
Empty or whitespace-only secret files would produce "" after .strip(),
passing the `is None` check but failing token validation. Use `or None`
to fall through to unauthenticated mode instead.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Christopher Collins <collins.christopher@gmail.com>
- Add None guard to get_checksum() after get_url_with_authentication()
  call, matching the pattern already used in list_assets() and
  get_binary()
- Add missing `import time` that caused NameError on retry paths in
  get_url_with_authentication() (pre-existing bug)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Validate remaining is an int before comparison to prevent TypeError
- Use local variable pattern for token loading so empty/whitespace-only
  secrets don't overwrite a previously loaded valid token

Created with assistance from Claude 🤖 <claude@anthropic.com>

Signed-off-by: Christopher Collins <collins.christopher@gmail.com>
@clcollins
clcollins force-pushed the validate-github-token branch from f2f6f9d to ae89f81 Compare July 28, 2026 20:01
@clcollins

Copy link
Copy Markdown
Member Author

/override "Red Hat Konflux / ocm-container-main-enterprise-contract / ocm-container-micro" "Red Hat Konflux / ocm-container-main-enterprise-contract / ocm-container-minimal"

The EC micro/minimal checks are failing with rpm_packages.unique_version:kernel-headers — a version mismatch between arches in the full ocm-container image (kernel-headers-6.12.0-211.39.1.el10_2 on arm64 vs 211.40.1 on x86_64).

This is NOT from PR 575's code — the EC snapshot includes the full ocm-container image from master (revision 1ca3ac0, PR #581 merge), not an image built by this PR. PR 575 only modifies github_dl.py and does not affect the container image contents.

The version skew is a race condition: a kernel-headers update landed in the UBI 10 repos between when the two arch builds ran dnf install. We confirmed locally that building both arches at the same point in time produces identical kernel-headers versions. This is the same class of issue documented in KONFLUX-10262, which led to a blanket rpm_packages.unique_version exclusion in the app-interface-rhtap-build-buildah-container EC policy. The app-interface-standard policy used by ocm-container does not yet have this exclusion.

🤖 Claude claude@anthropic.com commenting on behalf of @clcollins

@openshift-ci

openshift-ci Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

@clcollins: Overrode contexts on behalf of clcollins: Red Hat Konflux / ocm-container-main-enterprise-contract / ocm-container-micro, Red Hat Konflux / ocm-container-main-enterprise-contract / ocm-container-minimal

Details

In response to this:

/override "Red Hat Konflux / ocm-container-main-enterprise-contract / ocm-container-micro" "Red Hat Konflux / ocm-container-main-enterprise-contract / ocm-container-minimal"

The EC micro/minimal checks are failing with rpm_packages.unique_version:kernel-headers — a version mismatch between arches in the full ocm-container image (kernel-headers-6.12.0-211.39.1.el10_2 on arm64 vs 211.40.1 on x86_64).

This is NOT from PR 575's code — the EC snapshot includes the full ocm-container image from master (revision 1ca3ac0, PR #581 merge), not an image built by this PR. PR 575 only modifies github_dl.py and does not affect the container image contents.

The version skew is a race condition: a kernel-headers update landed in the UBI 10 repos between when the two arch builds ran dnf install. We confirmed locally that building both arches at the same point in time produces identical kernel-headers versions. This is the same class of issue documented in KONFLUX-10262, which led to a blanket rpm_packages.unique_version exclusion in the app-interface-rhtap-build-buildah-container EC policy. The app-interface-standard policy used by ocm-container does not yet have this exclusion.

🤖 Claude claude@anthropic.com commenting on behalf of @clcollins

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@clcollins

Copy link
Copy Markdown
Member Author

/retest

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants