Episode 8 β Security, Permissions & the Fork PR Model
In the previous episodes, we learned how to:
- build clean CI/CD pipelines
- reuse workflows
- speed things up with cache and artifacts
Now weβll cover the topic that most broken pipelines get wrong:
Security.
This episode explains:
- how GitHub Actions protects your secrets
- what
GITHUB_TOKENreally is - why forked pull requests are treated differently
- how to design secure pipelines without fear
Why Security Matters in CI/CD
A GitHub Actions workflow can:
- access your source code
- deploy to production
- publish packages
- modify repositories
That means:
A vulnerable workflow can compromise your entire system.
GitHub Actions is secure by default β but only if you understand how its model works.
1οΈβ£ What is GITHUB_TOKEN?
GITHUB_TOKEN is a short-lived, auto-generated token created for every workflow run.
You donβt create it.
You donβt store it.
GitHub injects it automatically.
It can be used to:
- read repository contents
- comment on PRs
- create releases
- push commits (if allowed)
Example:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2οΈβ£ Permissions & Least Privilege
By default, workflows run with restricted permissions.
You should explicitly define what your workflow can access.
β Bad (implicit permissions)
jobs:
build:
runs-on: ubuntu-latest
β Good (least privilege)
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
Common permissions youβll see
| Permission | What it allows |
|---|---|
contents |
Read/write repo |
pull-requests |
Comment on PRs |
packages |
Publish packages |
pages |
Deploy GitHub Pages |
id-token |
Cloud auth (OIDC) |
3οΈβ£ Job-Level Permission Overrides
You can restrict permissions per job.
jobs:
deploy:
permissions:
contents: read
id-token: write
This ensures:
- CI jobs stay minimal
- deploy jobs get only what they need
4οΈβ£ Forked Pull Requests (Critical Concept)
Pull requests from forks are untrusted code.
GitHub protects you by:
- β not passing secrets
- π making
GITHUB_TOKENread-only - π« blocking write access
This prevents:
βMalicious PR steals secretsβ
5οΈβ£ The Danger of pull_request_target
on: pull_request_target
This event:
- runs in the base repository context
- has access to secrets
- can be dangerous if misused
Use it ONLY for:
- labeling PRs
- commenting
- metadata tasks
β Never run untrusted code with it.
6οΈβ£ Third-Party Actions: Trust Carefully
Using an action is equivalent to:
Running someone elseβs code in your pipeline
Best practices:
- use official or well-maintained actions
- pin versions (
@v4, not@main) - avoid unknown or inactive repos
- consider SHA pinning for high-security pipelines
Example:
uses: actions/checkout@v4
7οΈβ£ Secure Deployment Pattern (Recommended)
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
deploy:
needs: test
if: github.ref == 'refs/heads/main'
environment: production
permissions:
contents: read
id-token: write
Why this is safe:
- tests run first
- deploy only from
main - environment approvals apply
- permissions are minimal
Common Security Mistakes π¨
β Running deploys on PRs
β Over-permissive tokens
β Printing secrets in logs
β Trusting all marketplace actions
β Skipping environment protection
Secure pipelines are:
- boring
- predictable
- explicit
Final Mental Model (Lock This In)
Untrusted code β no secrets
Trusted branch β controlled access
Least privilege β always
If you follow this model, most security issues disappear.
Whatβs Next?
π Episode 9:
Debugging & Troubleshooting GitHub Actions
Weβll learn how to:
- read logs effectively
- debug secrets and permissions
- understand silent failures
- fix flaky pipelines
This is where theory turns into real-world confidence π
Thanks for reading!
Build safely π
Top comments (0)