Skip to content

Commit 638e957

Browse files
fix(security): least-privilege workflow permissions (SonarCloud New Code) (#58)
`main` is green as of #57. This addresses the one original red that had gone unexamined all programme: **SonarCloud Quality Gate — `C Security Rating on New Code` (required ≥ A)**. ## Getting the findings without dashboard access SonarCloud's project is public, so its API lists them directly: ``` https://sonarcloud.io/api/issues/search?componentKeys=hyperpolymath_krl&types=VULNERABILITY ``` **15 vulnerabilities, all inside the new-code period.** Two are fixed here — including one this programme introduced. ## Fixed ### `e2e.yml` — *"Replace `read-all` with specific permissions"* **This one is mine.** `e2e.yml` was rewritten in #53 and carried the RSR template's `permissions: read-all`. Narrowed to `contents: read`, which is all four jobs need. ### `pages.yml` ×3 — *"Move this read/write permission from workflow level to job level"* The workflow granted `contents:read` + `pages:write` + `id-token:write` to **both** jobs, but only `deploy` needs the pages and id-token scopes. Now split per job: | Job | Permissions | |---|---| | `build` | `contents: read` | | `deploy` | `contents: read`, `pages: write`, `id-token: write` | That matters here beyond satisfying the linter: the `build` job runs a **container image** and executes the SSG over repository content. It should not be holding deploy credentials while doing so. ## Not fixed — deliberately, so this stays reviewable | Finding | Location | |---|---| | Only pass required secrets to this workflow | `secret-scanner.yml:18`, `mirror.yml:12` | | Dependencies without locked resolved versions | `release.yml:38` | | Not enforcing HTTPS | `release.yml:91`, `static-analysis-gate.yml:30,31,229,230`, `setup.sh:144,156` | | Workflow-level permission | `static-analysis-gate.yml:11` | **The rating will not reach A until those are triaged too.** Several of the HTTPS findings may be false positives and need reading in context before anything is changed — which is exactly why they aren't bundled into a PR about permissions. ## Verified `actionlint` **0** · K9 **0 errors** · A2ML **0 errors** · e2e 4/4 · aspect 4/4 · smoke 20/20
1 parent 1dbe96d commit 638e957

2 files changed

Lines changed: 11 additions & 5 deletions

File tree

.github/workflows/e2e.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ on:
2727
- 'examples/**'
2828
- '.github/workflows/e2e.yml'
2929
workflow_dispatch:
30-
permissions: read-all
30+
permissions:
31+
contents: read
3132
concurrency:
3233
group: e2e-${{ github.ref }}
3334
cancel-in-progress: true

.github/workflows/pages.yml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@ on:
55
push:
66
branches: [main, master]
77
workflow_dispatch:
8-
permissions:
9-
contents: read
10-
pages: write
11-
id-token: write
8+
# Permissions are declared per job rather than at workflow level, so the build
9+
# job never holds the pages/id-token write scopes that only the deploy job
10+
# needs.
1211
concurrency:
1312
group: "pages"
1413
cancel-in-progress: false
1514
jobs:
1615
build:
16+
permissions:
17+
contents: read
1718
runs-on: ubuntu-latest
1819
timeout-minutes: 15
1920
container:
@@ -43,6 +44,10 @@ jobs:
4344
with:
4445
path: '_site'
4546
deploy:
47+
permissions:
48+
contents: read
49+
pages: write
50+
id-token: write
4651
environment:
4752
name: github-pages
4853
url: ${{ steps.deployment.outputs.page_url }}

0 commit comments

Comments
 (0)