GitHub Actions runs your code with elevated privileges: access to your
secrets, write rights on the repository, the ability to publish packages. This
section explains how the platform works, what it costs, and above all how to
secure it, from the GITHUB_TOKEN permissions to provenance attestations.
The English pages focus on security, the part that is most often treated
last and where the real incidents happen.
What is GitHub Actions?
GitHub Actions is the CI/CD (continuous integration and continuous delivery) automation platform built natively into GitHub. Launched in 2019, it runs code automatically in response to events on your repository.
Concretely, GitHub Actions lets you:
- Automate the tests: on every push or pull request, your tests run by themselves
- Build and publish: compile your code, create Docker images, publish to npm or PyPI
- Deploy: push automatically to AWS, Azure, GCP, Kubernetes, or your own infrastructure
- Maintain your code: check the formatting, analyse the security, update the dependencies
- Orchestrate tasks: schedule recurring actions, react to issues or releases
How does it work?
Everything rests on workflows: YAML files placed in the .github/workflows/
directory of your repository. Each workflow defines:
- When to run (push, pull request, schedule, manually, and so on)
- What to do (a series of tasks called jobs and steps)
- Where to do it (on virtual machines called runners)
# A minimal workflow examplename: Tests
on: [push, pull_request]
jobs: test: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - run: npm testWhen you push code, GitHub detects the workflows automatically, provisions a virtual machine, runs your tasks, and shows the results in the interface.
The Marketplace: an ecosystem of actions
One of the strengths of GitHub Actions is its Marketplace: thousands of ready-made actions built by the community and by vendors. Rather than rewriting the logic to "deploy to AWS" or "send a Slack notification", you use an existing action.
But be careful: using an action means running third-party code with access to your secrets. The security of your pipeline depends on the trust you place in those actions. That is why this section insists on SHA pinning and on verifying the sources.
What does it cost?
GitHub Actions is free in two situations that cover a large share of real usage: public repositories on standard runners, and self-hosted runners, whatever the visibility of the repository. Everything else draws on a monthly included quota, then bills per minute.
| Plan | Included minutes per month |
|---|---|
| GitHub Free | 2,000 |
| GitHub Pro | 3,000 |
| GitHub Team | 3,000 |
| GitHub Enterprise Cloud | 50,000 |
Beyond the quota: a price per machine
The old multiplier model (a Windows minute counted twice, a macOS minute counted ten times) has disappeared from the GitHub documentation, replaced by a per-SKU price list. Each runner type now carries its own per-minute rate:
| Standard runner | Price per minute |
|---|---|
| Linux 2-core (x64) | $0.006 |
| Linux 2-core (arm64) | $0.005 |
| Windows 2-core (x64) | $0.010 |
| macOS 3 or 4-core | $0.062 |
The order of magnitude has not changed, a macOS minute still costs roughly ten times a Linux minute. What changed is the reading: the price is read directly, and the same list covers the larger runners (4 cores and above) and the GPU runners, billed significantly more.
The escape hatch: self-hosted runners
Self-hosted runners (machines you manage yourself) consume no minute of the GitHub quota, and using Actions on them is free. It is the economical option for large volumes or specific needs (GPU, internal network). The trade-off is not financial but security-related: you inherit the isolation, the hardening and the lifecycle of those machines.
Following your consumption
Go to Settings, then Billing and plans, then Plans and usage to see your current consumption. You can also configure alerts to avoid surprises.
For open source projects, everything is free and unlimited. That is one of the reasons GitHub Actions became the de facto standard for open source CI/CD.
Why security comes first here
The 2025-2026 incidents make the case better than any argument. The
tj-actions/changed-files compromise leaked the secrets of nearly 23,000
repositories into public build logs. GhostAction stole 3,325 secrets across 817
repositories. Shai Hulud v2 spread through 796 npm packages. And in February
2026, an autonomous AI bot wiped the Trivy repository after exploiting a
vulnerable workflow.
None of those attacks needed a zero-day. They walked through five doors you
control: a badly secured pull_request_target, mutable tags, excessive
permissions, command injection, and uncontrolled network exfiltration.
Where to start
Understand the attacks
What actually happened in 2025 and 2026
tj-actions, GhostAction, Shai Hulud v2, hackerbot-claw: the four real cases, the five vectors they used, and the fix for each one.
Harden your workflows
Permissions, pinning, triggers, OIDC
The concrete configuration: permissions: {}, actions pinned by SHA,
pull_request_target neutralised, cloud credentials replaced by OIDC.
Scan automatically
actionlint, zizmor, poutine, Plumber
Four complementary tools: syntax, workflow security, multi-platform pipelines, and an A-E posture score.
Prove what you ship
Provenance, SBOM, verification
Generate a SLSA attestation for every release, then verify it before deployment, in CI/CD and at admission time in Kubernetes.
FAQ: frequent questions
These questions come back constantly, from the first workflow to the first security audit.
GitHub Actions is a CI/CD automation platform built into GitHub. It runs code automatically (tests, builds, deployments) in response to events on your repository: push, pull request, release, or a schedule.
GitHub Actions is free for public repositories. For private ones, GitHub gives a free monthly quota (2,000 minutes per month on free accounts), beyond which it is billed. Self-hosted runners are free and unmetered.
Workflows go in the .github/workflows/ directory at the root of your repository. The files must carry the .yml or .yaml extension. GitHub picks up every file in that directory automatically.
A job is a unit of work running on its own virtual machine (a runner). Steps are the individual tasks inside a job. Jobs run in parallel by default, whereas steps run sequentially on the same machine.
The essential practices are: declare minimal permissions with permissions:, pin actions by full SHA rather than by tag, never store secrets in the code, use environments with approval for production, and avoid pull_request_target unless you understand the risks.
Tags such as @v4 are mutable: the maintainer can change them at any moment. If the action is compromised, your workflow will run malicious code. A full SHA such as @11bd71901bbe5b1630ceea73d27597364c9af683 points at one exact, immutable version of the code.
Use the actions/upload-artifact and actions/download-artifact actions. Each job runs on a different machine, so files are not shared automatically. Artefacts are kept for 90 days by default.
A runner is the virtual machine that executes your jobs. GitHub offers hosted runners (Ubuntu, Windows, macOS) ready to use. You can also register self-hosted runners on your own infrastructure for specific needs (GPU, internal network, compliance).
Aliases such as ubuntu-latest point at a version that changes without warning when GitHub updates its runners. One day your workflow works, the next it breaks. Use an explicit version such as ubuntu-24.04 for reproducible builds.
Add the workflow_dispatch trigger to the on: section of your workflow. That adds a 'Run workflow' button in the GitHub Actions interface. You can also define inputs to pass parameters at launch time.
Secrets are created under Settings, then Secrets and variables, then Actions. In the workflow, use the ${{ secrets.SECRET_NAME }} syntax. GitHub masks secrets in the logs automatically with ***.
Secrets are encrypted, masked in the logs, and can never be read back after creation. Use them for tokens, passwords and API keys. Variables are in clear text, visible in the logs, and serve public configuration (versions, URLs, flags).
Use the act tool, which simulates GitHub Actions on your machine with Docker. Be aware that not every feature is supported (notably GitHub secrets, some events, and the macOS and Windows runners).
Cache the dependencies with actions/cache, run jobs in parallel where possible, filter the triggers with paths: to avoid useless runs, and configure concurrency to cancel obsolete runs.
No. By default, workflows triggered by pull requests coming from forks have no access to the target repository's secrets. That is an important security protection. The pull_request_target trigger bypasses it and must be used with care.
Next steps
- Securing CI/CD pipelines: the section hub, with the full reading order.
- Supply chain attacks on GitHub Actions: the real cases and the five vectors to close.
- OpenSSF Scorecard: measuring your repository's posture against nineteen objective checks.