Skip to content

Harden GitHub Actions trust boundaries and credential handling - #858

Open
freeznet wants to merge 3 commits into
masterfrom
security/harden-github-actions
Open

freeznet wants to merge 3 commits into
masterfrom
security/harden-github-actions

Conversation

@freeznet

@freeznet freeznet commented Nov 11, 2026 •

Copy link
Copy Markdown
Member

Motivation

Audit and harden all 11 existing workflows, including PR-controlled execution, cloud secrets, token permissions, remote debugging, release inputs, action dependencies, caches, and artifacts. The full per-workflow findings, behavior changes, and remaining controls are in .github/WORKFLOW_SECURITY.md.

Changes

  • Move basic/TLS integration tests to secretless pull_request execution. Run OAuth2/downloader tests only on official-repository master pushes or manual dispatches, with secrets scoped to the E2E step and GSA limited to its required case.
  • Remove automatic SSH/upterm/tmate access. Use read-only PR tokens and disable persisted checkout credentials and build caches.
  • Separate release-file/SARIF upload permissions from build jobs; consume only same-run artifacts without executing them. Keep release drafting and documentation labeling metadata-only, with three explicit documentation labels.
  • Require version tags reachable from master before publishing jobs start, check out the validated commit SHA, and remove mutable release-helper downloads.
  • Stop logging the Red Hat authentication JSON, use private temporary files with cleanup, and pin the preflight container digest.
  • Pin every third-party workflow action to a verified commit, verify directly downloaded tools with SHA-256, and pin E2E Helm installation/Pulsar chart preparation.
  • Add workflow syntax checks and 11 security regression tests.

Validation

Passed locally:

  • actionlint 1.7.7 with -shellcheck='' -pyflakes='' across all workflows
  • 11 regression tests, including real local Git tag-validation tests, hostile label-body cases, and corrupted Helm downloads rejected before installation
  • shell syntax checks for workflow/E2E command blocks
  • hash-locked PyYAML wheel download and git diff --check
  • independent review of the trust boundaries and validation results

The new Workflow security Actions run also passed on head 0490c93b679bcce9b7ef68f860a99f9c763989e4, including dependency installation, actionlint and the trust-boundary tests. Other PR checks were still running when this note was updated.

Not run locally: Docker/Kubernetes E2E, cloud OAuth/PubSub integration, release publication, or Red Hat submission. No release/cloud workflow was manually dispatched. Check the exact PR-head Actions results before merging.

Review notes

Cloud integration now runs after merge rather than on unmerged PRs. Documentation labeling intentionally drops the old bot's assignment/comment and extra-label behavior. Arbitrary release refs and unmerged release branches are rejected. Existing tag workflows are not retroactively changed. Repository rules, protected environments, credential rotation, cloud IAM, and complete transitive dependency reproducibility remain separate controls; this PR does not modify them.

  • doc
  • doc-required
  • no-need-doc

@github-actions github-actions Bot added the doc This pr contains a document label Nov 11, 2026
@freeznet
freeznet marked this pull request as ready for review November 12, 2026 03:43
@freeznet
freeznet requested a review from a team as a code owner November 12, 2026 03:43
Copilot AI balanced review requested due to automatic review settings November 12, 2026 03:43

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-12T03:45:06.038804Z 6346f35 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@jiangpengcheng jiangpengcheng left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All 12 workflow regression tests passed locally on Python 3.11, and GitHub reports six passing checks on this head. Cloud E2E and publishing remain unverified.

upload:
if: startsWith(github.ref, 'refs/tags/v')
name: Upload Release files
validate-tag:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[P1] Enforce release validation from a protected ref. GitHub loads the release workflow from the tagged commit. Tags that contain the previous workflow still use the old publisher and skip the new ancestry check. Move publishing and its credentials behind a workflow loaded from a protected ref.

GitHub release event

fi
git fetch --no-tags origin "refs/tags/$TAG:refs/tags/$TAG"
sha=$(git rev-parse --verify "refs/tags/$TAG^{commit}")
git merge-base --is-ancestor "$sha" origin/master

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[P1] Preserve maintenance and release-candidate publishing. The manual bundle publisher requires tags to be ancestors of master. I verified that the published v0.28.1 and v0.30.0-rc-2 tags fail that check. Validate against the matching protected release branch or update the release process so the tagged commit lands on master first.

Release process

name: Precommit - Integration Tests
on:
pull_request_target:
pull_request:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[P2] Restore Basic and TLS integration coverage. GitHub marks the existing workflow as disabled_manually. Changing its trigger in place leaves it disabled, and neither job ran on this head. Give the secretless workflow a new filename and verify both jobs on the PR.

Workflow state


class WorkflowSecurity(unittest.TestCase):
def test_all_workflows_obey_baseline(self):
for path in sorted(WORKFLOWS.glob('*.yml')):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[P3] Check both workflow file extensions. The trust-boundary and shell syntax tests only enumerate *.yml. GitHub also accepts *.yaml, so include both extensions in both test loops.

GitHub workflow syntax

This branch has not been deployed

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

Labels

doc This pr contains a document

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants