Skip to content

Lint workflow changes with actionlint and zizmor, and roll out SHA-pinned actions and job-level permissions #187

Closed

Description

@woksin

Workflows itself pins third-party actions by full commit SHA. The product repositories mostly use tags: Studio has no SHA pins, and Chronicle's publish.yml has 61 tag references. GitHub documents full-SHA pinning as the only immutable reference. Tags can be moved; the tj-actions/changed-files compromise exploited exactly that. Many workflows also run with the default token permissions.

Proposed:

  1. A reusable verify-workflows gate (one job, path-filtered to .github/workflows/** and .github/actions/**) that runs actionlint (syntax, expressions, reusable-workflow interfaces, shellcheck) and zizmor (unpinned-uses, excessive-permissions, template-injection, cache-poisoning). Start in report mode and make it blocking per repository once that repository is clean.
  2. Pin third-party actions by full SHA with a version comment. Dependabot's github-actions ecosystem keeps the pins current. Roll out per repository through bootstrap.
  3. Add a top-level permissions: contents: read and grant write scopes per job.
    Related: Run the shared pull-request policy gates in one job #157/Move the remaining legacy-gate repositories to the one-job pull-request policy #171 (one-job policy gate) — the new check could become a step of that gate instead of a separate job, saving a scheduler start per PR.

Status

State: Done — shared gate delivered; remaining rollout split to a dedicated backlog issue.
Delivered: #218 added offline, checksum-pinned zizmor auditing with report/blocking modes. #224 added conditional composite-action coverage and regression checks for report/blocking and missing/empty action directories.
Remaining: Consumer SHA pinning, least-privilege permissions, finding disposition, and enabling blocking audits are not claimed complete. They are tracked in #223.
Follow-ups: #223 (open backlog).

Activity

  1. self-assigned this
    on Oct 22, 2026
  2. added theissue type on Oct 25, 2026
  3. woksin commented on Oct 29, 2026

    @woksin
    ContributorAuthor

    Analysis and proposed solution

    Current behaviour

    A reusable syntax-lint workflow exists at .github/workflows/workflow-lint.yml:6. It exposes optional ShellCheck at .github/workflows/workflow-lint.yml:16-17 and builds the corresponding actionlint arguments at .github/workflows/workflow-lint.yml:62. This is useful existing coverage, but it is not the proposed combined actionlint/zizmor gate, and it does not demonstrate consumer SHA pinning or least-privilege permissions.

    Root cause / gap

    Syntax checking and security-policy checking remain separate concerns without the requested shared report/blocking contract. The rollout also requires changes in consumer repositories; adding a reusable workflow alone cannot satisfy it.

    Proposed change

    Add verify-workflows.yml with pinned, integrity-verified tool installation and explicit report-only versus blocking behavior. Reuse the existing actionlint installation rather than introducing competing versions. Detect changes to workflows and composite actions, and keep any required check reporting deterministically even when no relevant files change. Run with read-only permissions and without consumer secrets.

    Add offline tests under .github/scripts/tests/ in the existing Python test style. Include broken syntax, mutable action references, excessive permissions, template injection, clean fixtures, irrelevant changes and both enforcement modes. Dogfood the gate here before consumer rollout. Then migrate third-party actions to full SHAs with version comments, configure Dependabot and reduce write grants job by job.

    Size, risk and release intent

    L; medium rollout risk from false positives and missing permissions; minor release intent.

    Dependencies and blockers

    Coordinate check naming and possible policy-job integration with #171. Establish clean report-mode results before enabling blocking enforcement in each consumer.

  4. changed the issue type fromtoon Oct 30, 2026
  5. woksin commented on Nov 4, 2026

    @woksin
    ContributorAuthor

    The shared lint/security gate and conditional composite-action audit are delivered in #218 and #224. Consumer SHA pinning, permissions, finding disposition, and blocking-enforcement rollout remain open in #223.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions