GitHub Actions GITHUB_TOKEN Permissions: Build a Museum Site Without Write Access

A volunteer maintains a museum website with a GitHub Actions workflow that runs link checks, builds static pages and occasionally publishes an approved exhibition update. If the routine build carries a broadly writable token, a compromised dependency or untrusted script may gain far more authority than testing needs. GitHub provides workflow- and job-level permissions for the ephemeral GITHUB_TOKEN. This hypothetical tutorial separates read-only validation from controlled publication without claiming that a real museum repository was audited.

Map the jobs and their legitimate operations

Draw the workflow as distinct jobs: fetch the source, check links, run tests, build pages and publish. For each step, list the repository or package API operation it truly needs. A linter that reads a checkout usually does not need permission to push a commit, modify issues, approve a pull request or publish a release.

Create a permission table with the event trigger, third-party action, execution environment and sensitive output for every job. Review hidden authority: a helper script may call gh, use a credential from the environment or upload artifacts. Treat workflows as executable code, not simply as status badges on a pull request.

Set a deliberately restrictive baseline

GitHub documents the permissions key at workflow and job level. Start with permissions: read-all or more narrowly permissions: {} as appropriate, then grant only named scopes such as contents: read when a job requires them. GitHub recommends least privilege. Be precise about how an unspecified permission is handled when permissions are declared, and test the behavior in a safe branch.

Original educational diagram of GitHub Actions GITHUB_TOKEN permissions. Process: Inventory workflow jobs → Restrict token permissions → Separate publish job → Test forked pull requests. Illustrative, not a vendor test or real result.

Repository and organization settings establish a default for GITHUB_TOKEN and can be more restrictive than a workflow author expects. Record the current Actions General settings before changing YAML. A copied sample from an older public repository may assume broad write access, so inspect each permission requirement rather than granting write-all because a job fails.

Keep pull request checks away from publishing credentials

Run untrusted pull request changes through linting and unit tests that do not carry deployment credentials. GitHub documents that normal pull_request workflows from forks are typically read-only and lack secrets, but other events and configurations have different trust properties. A branch within the same repository is not automatically safe merely because it is not a fork.

Do not replace a read-only pull request event with pull_request_target just to obtain credentials, then check out and execute untrusted contributor code. Review every event boundary in context. If the tests need fixtures, generate synthetic data rather than reading private donor exports. Runner isolation and dependency integrity matter even when token scopes are limited.

Split publication into a separately gated job

Put the public deploy step in an explicitly named publish job that runs only for an authorized branch or release event and after required checks succeed. Give it only the publication-specific token permissions; use an appropriate environment approval or identity mechanism when that job reaches an external hosting system.

The process diagram shows the read-only build path separated from the deployment gate. Approval should represent an actual human or automated policy decision, not a green check attached to a different commit. If publication uses a separate GitHub App or cloud identity, audit that credential’s scope and lifetime independently of GITHUB_TOKEN.

Evaluate dangerous inherited privileges

Third-party marketplace actions and downloaded scripts execute in the job’s trust context. Pin and review dependencies, protect runner secrets and avoid echoing token strings into logs. Setting permissions is necessary but not sufficient: a build may still access private files in its workspace or send results to an outside endpoint.

Original educational diagram of GitHub Actions GITHUB_TOKEN permissions. Comparison: Broad write token, Read-only build job, Approved publishing job. Illustrative, not a vendor test or real result.

The comparison diagram contrasts a broadly writable test job, a read-only checker, and a reviewed publisher. These are conceptual workflow roles, not screenshots of GitHub. The reduced permissions prevent unauthorized API writes through that token; they do not make arbitrary downloaded code harmless.

Verify permissions through safe negative tests

On a test branch, use an authorized diagnostic action to attempt a harmless API operation that should fail, such as updating a disposable issue from a read-only job. Confirm the request receives a permission failure without altering production resources. Test the real deploy path with an approved dummy change, and check that a failed validation cannot trigger publishing.

Use ephemeral test resources and never paste actual tokens into issue comments or debug output. For fork pull requests, check what event type runs and which context values select the checkout. Make sure the same workflow cannot accidentally obtain stronger permissions through a job-level override or a reusable workflow with broader privileges.

Protect artifacts and deployment provenance

A passing build job can still produce an altered artifact if its inputs are compromised. Record the source commit, workflow run ID, artifact digest and approval decision. Require the publisher to verify that it is deploying the expected artifact, not just whichever file happens to be present at a predictable path.

Original educational diagram of GitHub Actions GITHUB_TOKEN permissions. Review points: Read workflow permissions, Inspect event triggers, Review third-party actions, Verify publish approval. Illustrative, not a vendor test or real result.

Do not let a status check stand in for authorization. A workflow can be green while an unrelated job had write privileges. Use branch rules, review gates and independent provenance controls as appropriate. Keep release logs free of donor information, secret values and hidden records that could be packaged accidentally into a public website.

Maintain the permissions map as workflows evolve

New site features add API operations over time. When a workflow fails with 403, identify the exact needed scope and grant it to only the affected job instead of increasing permissions across the entire repository. Document why a publisher needs write access and when its approval path is reviewed.

Re-audit event triggers, settings and third-party actions after major GitHub changes. The stable design principle is narrow authority: regular tests should be able to fail without gaining the ability to change the site, and the publishing job should act only on verified inputs after the required approval. No real deployment or security test is claimed here.

How We Research

For this November 2026 article, we examined named vendor references: Authenticating with GITHUB_TOKEN; GitHub Actions repository settings; Understanding compromised runners. We compared documented input options, output fields, supported modes and limitations against an expressly fictional archive or community-service workflow. We did not process private records, make paid API requests, obtain live service results, run a security assessment or measure product performance. All artwork consists of original conceptual examples rather than actual interface screenshots or benchmark evidence. Readers must verify up-to-date product documentation, eligibility, region, legal permissions and authorized environment configuration before deployment.

Frequently Asked Questions

Does GITHUB_TOKEN need write permissions to run tests?

Usually not. Most checkout, build and lint tasks need only repository read access, depending on their actions.

Where can permissions be defined?

GitHub supports a permissions key at workflow and job scope, alongside repository and organization defaults.

Are forked pull requests always safe?

No. Normal fork pull_request behavior is restricted, but events, runner execution and other configurations still require review.

Does least privilege replace a publish approval?

No. Keep deployment rights and the release approval gate separate from routine CI tests.

Did this guide test a live repository?

No. The workflow is hypothetical and should be verified with safe, authorized tests in your own repository.

Scroll to Top