Skip to content

Security: Missing explicit permissions block on 4 CI workflows #406

@pratikchaskar

Description

@pratikchaskar

Severity: Medium

Summary

Four workflows lack an explicit permissions declaration, causing the GITHUB_TOKEN to inherit the repository/organization default — which is typically read-write access to all scopes. This violates the principle of least privilege and increases the blast radius if any step in these workflows is compromised.

Affected Workflows

Workflow File Trigger Permissions Needed Permissions Inherited (likely)
.github/workflows/chromatic.yml push to staging contents: read Read-write to everything
.github/workflows/storybook-tests.yml push (all branches) contents: read Read-write to everything
.github/workflows/code-analysis.yml pull_request contents: read Read-write for internal PRs
.github/workflows/tag-release.yml push to master contents: write Read-write to everything

Already have explicit permissions (correct):

  • publish.ymlcontents: read, packages: write
  • storybook-deployment.ymlcontents: read, pages: write, id-token: write
  • claude.ymlcontents: read, pull-requests: read, issues: read, id-token: write
  • claude-code-review.ymlcontents: read, pull-requests: read, issues: read, id-token: write

Impact

  • When no permissions key is declared, the GITHUB_TOKEN inherits the repository's default permission setting. For repositories/organizations that have not explicitly restricted this, the default grants read-write access to all scopes.
  • If any step in these workflows is compromised (e.g., via an unpinned third-party action like chromaui/action@latest, or a malicious dependency pulled in by npm install), the attacker would gain write access they should never have had — including the ability to push commits, create releases, modify packages, and more.
  • The tag-release.yml case is notable because it legitimately needs contents: write (for creating tags/releases) — but even this workflow should not have implicit access to packages: write, pull-requests: write, issues: write, etc.

Recommended Fix

Add explicit minimal permissions to each workflow:

# chromatic.yml — only reads source code
permissions:
  contents: read

# storybook-tests.yml — only reads source code and runs tests
permissions:
  contents: read

# code-analysis.yml — only reads source code and runs linters
permissions:
  contents: read

# tag-release.yml — needs to create tags and GitHub Releases
permissions:
  contents: write

Context

Identified during a modular security audit. The fact that 4 other workflows already have explicit permissions shows the team follows this practice — these 4 were likely missed.


Found by automated security audit — VULN-08

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions