None of the four workflows declare a permissions: block, so GITHUB_TOKEN is issued with the repository default scope rather than the least privilege each job needs. CodeQL raised actions/missing-workflow-permissions on two of them:
- alert #2 —
.github/workflows/server.yml:42
- alert #1 —
.github/workflows/www.yml:28
It only flagged those two because mac.yml and windows.yml genuinely use the token — gh release create / gh release upload — so their wider scope looks intentional to the analysis. They are still relying on an implicit default rather than asking for what they need.
What each job actually uses:
| workflow |
needs |
proposed |
server.yml |
checkout only |
contents: read |
www.yml |
checkout; deploys with Cloudflare credentials, not GITHUB_TOKEN |
contents: read |
mac.yml |
checkout + create/upload a Release |
contents: write |
windows.yml |
checkout + create/upload a Release |
contents: write |
Adding a top-level permissions: block to each is the whole change. It clears both alerts and makes the two release workflows state the write access they depend on instead of inheriting it, so a later change to the repository default cannot silently widen or break them.
Note mac.yml also passes HOMEBREW_TAP_TOKEN to push the cask to lightware-dev/homebrew-tap. That is a separate PAT and unaffected by permissions:, which only scopes GITHUB_TOKEN.
Found by CodeQL after the repo went public.
None of the four workflows declare a
permissions:block, soGITHUB_TOKENis issued with the repository default scope rather than the least privilege each job needs. CodeQL raisedactions/missing-workflow-permissionson two of them:.github/workflows/server.yml:42.github/workflows/www.yml:28It only flagged those two because
mac.ymlandwindows.ymlgenuinely use the token —gh release create/gh release upload— so their wider scope looks intentional to the analysis. They are still relying on an implicit default rather than asking for what they need.What each job actually uses:
server.ymlcontents: readwww.ymlGITHUB_TOKENcontents: readmac.ymlcontents: writewindows.ymlcontents: writeAdding a top-level
permissions:block to each is the whole change. It clears both alerts and makes the two release workflows state the write access they depend on instead of inheriting it, so a later change to the repository default cannot silently widen or break them.Note
mac.ymlalso passesHOMEBREW_TAP_TOKENto push the cask tolightware-dev/homebrew-tap. That is a separate PAT and unaffected bypermissions:, which only scopesGITHUB_TOKEN.Found by CodeQL after the repo went public.