Skip to content

chore(workflows): apply best-practice hardening across all reusable workflows#30

Open
lml2468 wants to merge 1 commit into
mainfrom
chore/workflow-best-practices
Open

chore(workflows): apply best-practice hardening across all reusable workflows#30
lml2468 wants to merge 1 commit into
mainfrom
chore/workflow-best-practices

Conversation

@lml2468
Copy link
Copy Markdown
Contributor

@lml2468 lml2468 commented May 19, 2026

Full audit of .github reusable workflows

Ran a systematic review against best-practice checklist: SHA pinning, minimal permissions, timeout-minutes, persist-credentials. All external actions were already SHA-pinned ✅.

Issues found and fixed

1. permissions: {} missing at top level

File Before After
issue-welcome.yml (missing — job had it, top didn't) permissions: {}
octo-ci-status.yml actions: read at top permissions: {} + moved to job
workflow-sanity.yml contents: read at top permissions: {} + moved to jobs

Why it matters: Top-level permissions without {} means GitHub applies default permissions (which are broad in some orgs). Least-privilege requires permissions: {} at top and explicit grants at job level.

2. Missing timeout-minutes on jobs

File Job Timeout added
reusable-pr-labeler.yml label 10 min
reusable-release-drafter.yml draft 10 min
reusable-release-publish.yml publish 15 min
reusable-stale.yml stale-unassigned 30 min
reusable-stale.yml stale-assigned-issues 30 min
reusable-stale.yml stale-assigned-prs 30 min
workflow-sanity.yml no-tabs 5 min
workflow-sanity.yml actionlint 10 min

Why it matters: Without timeout, a hung job consumes runner minutes until GitHub's 6-hour hard limit.

Already correct (no changes needed)

  • auto-add-to-project.yml: note about actions/checkout is in a comment (security warning), no actual checkout step — not an issue
  • octo-issue-feed.yml: permissions: {} ✅, timeouts ✅
  • octo-pr-feed.yml: permissions: {}
  • reusable-codeql.yml: permissions: {} ✅, timeout ✅
  • All external actions: SHA-pinned ✅

No behavioral changes

Pure hardening — permissions grants are unchanged in scope, just moved to correct level. Timeout values are generous for the workload.

…orkflows

Fixes found during full audit of .github reusable workflows:

permissions:
- issue-welcome.yml: add missing top-level permissions: {}
- octo-ci-status.yml: move actions:read from top-level to job level;
  top-level now permissions: {}
- workflow-sanity.yml: move contents:read from top-level to job level;
  top-level now permissions: {}

timeout-minutes (all were unbounded):
- reusable-pr-labeler.yml label job: 10 min
- reusable-release-drafter.yml draft job: 10 min
- reusable-release-publish.yml publish job: 15 min
- reusable-stale.yml all 3 jobs: 30 min each
- workflow-sanity.yml no-tabs: 5 min, actionlint: 10 min

No behavioral changes. All external actions remain SHA-pinned.
Copy link
Copy Markdown

@Jerry-Xin Jerry-Xin left a comment

Choose a reason for hiding this comment

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

Summary: The PR is in scope for Mininglamp-OSS/.github and cleanly hardens repository workflows without changing effective job behavior.

✅ Highlights

  • 🔵 Suggestion / Positive: permissions: {} is now explicit at the workflow level while required grants are scoped to jobs, e.g. .github/workflows/octo-ci-status.yml:40-47 and .github/workflows/workflow-sanity.yml:18-30.
  • 🔵 Suggestion / Positive: Added bounded job timeouts for the affected reusable workflows, e.g. .github/workflows/reusable-pr-labeler.yml:22-28, .github/workflows/reusable-release-publish.yml:27-34, and .github/workflows/reusable-stale.yml:26-32.
  • 🔵 Suggestion / Positive: Checkout jobs retain persist-credentials: false with contents: read restored at job scope in .github/workflows/workflow-sanity.yml:29-35 and .github/workflows/workflow-sanity.yml:67-73.

Validation performed:

  • git diff --check passed.
  • actionlint v1.7.12 passed against the workflow set.

No blocking or non-blocking issues found.

Copy link
Copy Markdown
Contributor Author

@lml2468 lml2468 left a comment

Choose a reason for hiding this comment

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

Summary

Applies two best-practice hardening patterns across all reusable workflows: (1) deny-by-default permissions at workflow level with job-scoped grants, (2) bounded timeout-minutes on all jobs.

Findings

None. Every change is mechanical and behavior-preserving:

Permissions scoping (workflow → job level)

File Before After
issue-welcome.yml (implicit default) permissions: {} at workflow
octo-ci-status.yml actions: read at workflow permissions: {} at workflow, actions: read at job
workflow-sanity.yml contents: read at workflow permissions: {} at workflow, contents: read at each job

Timeout additions

File Job(s) Timeout
reusable-pr-labeler.yml label 10m
reusable-release-drafter.yml draft 10m
reusable-release-publish.yml publish 15m
reusable-stale.yml 3 jobs 30m each
workflow-sanity.yml no-tabs / actionlint 5m / 10m

All timeout values are reasonable: API-only jobs get 5-15m, stale sweeps that may paginate many issues get 30m.

No behavioral changes, no breaking changes, no new inputs/outputs. CI green (sanity checks pass; add-to-project failure is pre-existing).

Verdict

APPROVED — clean mechanical hardening, consistent with the least-privilege and fail-bounded patterns already applied in earlier PRs. (Submitted as COMMENTED due to GitHub limitation.)

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