1. GITHUB_TOKEN with default write-all permissions
By default, GitHub Actions grants the GITHUB_TOKEN write access to all scopes. This means every job in every workflow can write to packages, create releases, modify repository content and more. The fix is simple: set permissions at the workflow or job level to the minimum required (typically contents: read and id-token: write for OIDC).
2. Actions pinned to tags instead of SHA
Using actions/checkout@v4 means trusting that the tag v4 points to the same code tomorrow as it does today. A tag can be moved by the repository owner at any time. Pinning to a full commit SHA (actions/checkout@11bd71901bbe...) ensures deterministic, immutable behavior. Any compromise of the action maintainer’s account cannot affect your pipeline.
3. Static secrets in repository settings
AWS access keys, API tokens and service account credentials stored as GitHub Secrets with no rotation policy. These secrets are available to every workflow and every branch (unless restricted). OIDC federation eliminates this entirely for cloud provider authentication.
4. No branch protection on main
Direct pushes to main without required reviews, no required status checks, no linear history enforcement. This means any developer can deploy to production without peer review — and the audit trail shows no separation of duties.
5. Secrets exposed in workflow logs
echo $SECRET_VALUE in a debug step, environment variable dumps from third-party tools, error messages that include credential values. GitHub’s log masking covers known secret names — but not every format, and not custom secrets passed through environment variables.
6. No dependency scanning
No SCA (Software Composition Analysis) tool integrated into the pipeline. Known vulnerabilities in dependencies are only discovered when a penetration test is commissioned — months or years after the vulnerability was published.
7. Docker images built from latest tag
Using FROM node:latest or FROM python:latest means the base image changes without notice. This is a supply chain attack vector — the image content is non-deterministic. Pin to a specific SHA or version tag.
8. Workflow files modifiable without review
If pull_request_target or self-hosted runners are used without proper restrictions, a malicious PR can modify the workflow file and access secrets. Workflow file changes should require security team review.
9. No artifact signing
Container images pushed to registry without cryptographic signatures. There is no way to verify that the image running in production is the one the pipeline built. Cosign adds signing in one pipeline step.
10. Overly broad self-hosted runner access
Self-hosted runners with access to internal networks, databases, and other infrastructure — shared across multiple repositories. A compromised workflow in any repository gets access to everything the runner can reach.
Read also: