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.

These mistakes co-occurThe pattern we see in audits is that these issues rarely appear in isolation. An organization with write-all GITHUB_TOKEN permissions almost always also has unpinned actions, static secrets and no branch protection. The fixes are interconnected — and the most impactful approach is addressing them systematically in a hardening sprint.

Read also: