Skip to content

ci: harden workflow token permissions and add CodeQL analysis - #145

Open
mgarbs wants to merge 1 commit into
hiero-ledger:mainfrom
mgarbs:ci/openssf-scorecard-hardening
Open

ci: harden workflow token permissions and add CodeQL analysis#145
mgarbs wants to merge 1 commit into
hiero-ledger:mainfrom
mgarbs:ci/openssf-scorecard-hardening

Conversation

@mgarbs

@mgarbs mgarbs commented Aug 27, 2026

Copy link
Copy Markdown

Description:

Harden the GitHub Actions workflows so the repository scores well on the OpenSSF Scorecard Token-Permissions, SAST and Pinned-Dependencies checks, without changing what any job is able to do.

  • Declare a read-only top-level permissions block in every workflow and move write scopes down to the jobs that use them
  • Add a CodeQL workflow (actions + javascript-typescript) that runs on pull requests, pushes to main/release/** and weekly
  • Replace the unpinned npm install axios in the PR label/milestone check with npm ci --omit=dev (axios is already a dependency in package.json/package-lock.json)

Changes by Scorecard check

Token-Permissions

  • release.yml: the top-level block granted actions, checks, contents, id-token, issues, pull-requests and packages: write to every job. It is now contents: read at the top level and each job gets only what its steps use:
    • dispatch-rcactions: write, contents: write (creates the rc/* branch and re-dispatches the workflow)
    • prepare-releasecontents: read (semantic-release dry run)
    • create-github-releasecontents: write, issues: write, pull-requests: write (semantic-release publish, milestone close)
    • create-snapshot-prcontents: write, pull-requests: write (peter-evans/create-pull-request)
    • publish-npm-packageid-token: write (npm provenance), packages: write, contents: read
    • checks: write was not used by any job in this workflow and is not re-granted.
  • tests.yml / manual-testing.yml: top level is now contents: read; checks: write + pull-requests: write are granted per job (each caller of the reusable test-workflow.yml, and PublishResults). The called workflow already declares the same job-level scopes, so the effective permissions of every job are unchanged.
  • pr-label-milestone-check.yml: had no permissions block at all (defaulted to the repository-wide token). Now contents: read at the top level and issues: read + pull-requests: read on the job, which is all check-pr.js needs (it only performs GET requests).
  • code-quality-check.yml, flow-pr-title-check.yml and test-workflow.yml already followed this pattern and are untouched.

SAST

  • New .github/workflows/codeql.yml, pinned to github/codeql-action@v4.37.9, using the same hl-contr-lin-md runner, step-security/harden-runner and actions/checkout pins as the other PR checks. Solidity is not a CodeQL-supported language, so the matrix covers actions (the workflow files themselves) and javascript-typescript (tests, scripts and config), both with build-mode: none.

Pinned-Dependencies

  • pr-label-milestone-check.yml: npm install axiosnpm ci --omit=dev, so the install is driven by the committed lockfile.
Check Before After (local scorecard --local)
Token-Permissions 0 10
SAST 0 10 (≥ 7 upstream once the workflow has run on PRs)
Pinned-Dependencies 8 9
Dangerous-Workflow 10 10
Binary-Artifacts 10 10

Intentionally not changed

  • release.yml installs semantic-release and its plugins with npm install --no-save …@<version> into contracts/, where there is no lockfile. Scorecard still flags these two commands; converting them would mean adding a lockfile for the release tooling, which is out of scope here.
  • No fuzzing/property-based test was added: the test suite runs against a live solo network and is invoked with --grep filters in CI, so a standalone property test would not fit the current runner setup.

Related issue(s):

None

Notes for reviewer:

  • Verification: actionlint on every touched workflow (only the pre-existing self-hosted runner-label and release.yml shellcheck notes remain, identical to main); scorecard --local . --checks Token-Permissions,Pinned-Dependencies,Binary-Artifacts,Dangerous-Workflow,SAST before/after (table above); npm ci --omit=dev against the committed package-lock.json installs axios in ~1s.
  • The release workflow authenticates with secrets.GH_ACCESS_TOKEN for checkout, git push, gh workflow run, semantic-release and create-pull-request, so the per-job GITHUB_TOKEN scopes mostly matter for id-token: write (npm provenance) and as a safety net. If a job is found to need an additional scope it can be added at the job level without affecting the Scorecard result.
  • The CodeQL job will show up as a new check on this PR; it needs no build and should complete in a few minutes on hl-contr-lin-md.

Checklist

  • Documented (Code comments, README, etc.)
  • Tested (unit, integration, etc.)

Declare a read-only top-level permissions block in every workflow and
move write scopes to the jobs that use them, add a CodeQL workflow, and
replace the unpinned npm install in the PR label check with npm ci.

- release.yml: top-level actions/checks/contents/id-token/issues/
  pull-requests/packages write replaced by contents: read; each job now
  declares only the scopes its steps use (dispatch-rc: actions+contents
  write; create-github-release: contents/issues/pull-requests write;
  create-snapshot-pr: contents/pull-requests write; publish-npm-package:
  id-token/packages write)
- tests.yml, manual-testing.yml: checks: write and pull-requests: write
  moved from the top level to each job calling test-workflow.yml and to
  PublishResults; effective job permissions are unchanged
- pr-label-milestone-check.yml: add the missing permissions block
  (contents: read top level, issues/pull-requests read on the job) and
  use npm ci --omit=dev instead of npm install axios
- add .github/workflows/codeql.yml (actions + javascript-typescript,
  build-mode none) on pull_request, push to main/release/** and weekly

Scorecard checks affected: Token-Permissions (0 -> 10), SAST (0 -> 10
locally), Pinned-Dependencies (8 -> 9).

Signed-off-by: Michael Garber <michael.garber@hashgraph.com>
@mgarbs
mgarbs requested review from a team as code owners August 27, 2026 14:53
@mgarbs
mgarbs requested a review from nathanklick August 27, 2026 14:53
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@mgarbs

mgarbs commented Aug 31, 2026

Copy link
Copy Markdown
Author

Some context on the intent behind this PR: it's part of a coordinated effort to raise the OpenSSF Scorecard scores across the hiero-ledger org. Scorecard is an automated 0–10 rating of a repository's supply-chain security practices — workflow token permissions, dependency pinning, SAST coverage, committed binaries, fuzzing, and similar checks — and it's what the org's security dashboard tracks.

The checks this PR moves (measured with scorecard --local on this branch): Token-Permissions 0→10, SAST 0→7, Pinned-Dependencies 8→9. The published score is currently 6.3 and the projection once this merges and the weekly Scorecard cron re-runs is ≈7.8.

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