chore(workflows): apply best-practice hardening across all reusable workflows#30
chore(workflows): apply best-practice hardening across all reusable workflows#30lml2468 wants to merge 1 commit into
Conversation
…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.
Jerry-Xin
left a comment
There was a problem hiding this comment.
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-47and.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: falsewithcontents: readrestored at job scope in.github/workflows/workflow-sanity.yml:29-35and.github/workflows/workflow-sanity.yml:67-73.
Validation performed:
git diff --checkpassed.actionlint v1.7.12passed against the workflow set.
No blocking or non-blocking issues found.
lml2468
left a comment
There was a problem hiding this comment.
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.)
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 levelissue-welcome.ymlpermissions: {}octo-ci-status.ymlactions: readat toppermissions: {}+ moved to jobworkflow-sanity.ymlcontents: readat toppermissions: {}+ moved to jobsWhy it matters: Top-level permissions without
{}means GitHub applies default permissions (which are broad in some orgs). Least-privilege requirespermissions: {}at top and explicit grants at job level.2. Missing
timeout-minuteson jobsreusable-pr-labeler.ymllabelreusable-release-drafter.ymldraftreusable-release-publish.ymlpublishreusable-stale.ymlstale-unassignedreusable-stale.ymlstale-assigned-issuesreusable-stale.ymlstale-assigned-prsworkflow-sanity.ymlno-tabsworkflow-sanity.ymlactionlintWhy 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 aboutactions/checkoutis in a comment (security warning), no actual checkout step — not an issueocto-issue-feed.yml:permissions: {}✅, timeouts ✅octo-pr-feed.yml:permissions: {}✅reusable-codeql.yml:permissions: {}✅, timeout ✅No behavioral changes
Pure hardening — permissions grants are unchanged in scope, just moved to correct level. Timeout values are generous for the workload.