Full Report
GitHub Actions are actually pretty hard to secure against all of the threats. In particular, insider threats. This article goes over some GitHub protections that can help a repository be better. Branch Protections prevent modifications to specific named branches. This prevents straight pushes to main from compromised developers. This can also be used to require signed commits or request pull requests before merging. Another good feature is Dismiss Stale pull request approvals. This prevents a PR from being approved and then having a major change being made from underneath it. Again, insider threats are very hard to protect against. GitHub Actions can have Secrets as well. One annoying component about this is that a user with push permissions on the repository can create a branch with a new GitHub action and just leak the secrets. To prevent this, I have required PRs from users only and not allowed branches except for admins. Environments are a collection of variables and secrets in GitHub. They can be created with specific names, like prod and dev. Secrets within an environment take place over those in the secrets directly. The environment feature has several helpful features. First, you can have required reviewers for using a particular environment. Second, you can only allow the environment to be used within a branch, such as a protected branch. This prevents the stealing of sensitive secrets as a result. There are also Tag-based protections. Restricting deletions, blocking force pushes, and requiring deployments to succeed are all somewhat helpful.
Analysis Summary
# Best Practices: Securing GitHub Actions Against Insider Threats
## Overview
These practices address the vulnerabilities inherent in CI/CD pipelines where users with "Write" access can potentially compromise secrets, inject malicious code, or bypass quality gates. The goal is to implement defense-in-depth to mitigate risks from compromised developer accounts and insider threats.
## Key Recommendations
### Immediate Actions
1. **Enable Branch Protections:** Lock the `main` (or production) branch to prevent direct pushes.
2. **Enforce Pull Requests (PRs):** Require at least one independent approval before any code can be merged.
3. **Activate "Dismiss Stale Approvals":** Ensure that if new code is pushed to an already approved PR, the approval is reset.
4. **Audit Permissions:** Strictly limit "Write" access to only those developers actively working on the specific repository.
### Short-term Improvements (1-3 months)
1. **Migrate to Environment Secrets:** Move repository-level secrets to "Environments" (e.g., `prod`, `staging`) to take advantage of deployment gates.
2. **Configure Environment Protection Rules:** Link sensitive environments to specific protected branches only.
3. **Implement Required Reviewers for Deployments:** Add a manual approval step for any workflow attempting to access production environments.
4. **Enforce Signed Commits:** Ensure all merged code is cryptographically verified to prevent identity spoofing.
### Long-term Strategy (3+ months)
1. **Zero-Trust Permissions:** Implement a "Least Privilege" model at the GitHub Organization level; remove default write access for all employees.
2. **Tag-based Security:** Implement rules to restrict the deletion of tags and block force pushes on release tags.
3. **Continuous Security Auditing:** Schedule semi-annual penetration tests specifically targeting the CI/CD pipeline and OIDC integrations (e.g., Azure/AWS).
## Implementation Guidance
### For Small Organizations
- Focus on the "Immediate Actions." Simple branch protections and PR requirements provide the highest ROI for minimal overhead.
- Use repository-level secrets but ensure only admins can manage them.
### For Medium Organizations
- Implement **Environments** to separate development and production secrets.
- Use "Required Approvals" for deployments to production to ensure a second pair of eyes on every release.
- Segment repository access by department or project team.
### For Large Enterprises
- Standardize workflow templates and use **Environment Protection Rules** across all business units.
- Disable the ability for non-admins to create new branches or push to anything except feature branches.
- Integrate with OIDC for secret-less authentication to cloud providers (e.g., Azure).
## Configuration Examples
**GitHub Environment Protection Strategy:**
- **Name:** `production`
- **Deployment Branches:** "Selected branches only" -> `main`
- **Required Reviewers:** Select a dedicated "Release Engineering" or "Security" team.
- **Wait Timer:** (Optional) Add a 5-minute delay to allow for automated "stop-ship" overrides.
**Branch Protection Settings:**
- [x] Require a pull request before merging
- [x] Required approvals: 1+
- [x] Dismiss stale pull request approvals when new commits are pushed
- [x] Require approval of the most recent reviewable push
- [x] Require signed commits
## Compliance Alignment
- **NIST SP 800-204 (Microservices/CI/CD):** Aligns with recommendations for automated access control and deployment integrity.
- **CIS GitHub Benchmark:** Follows controls for branch protection and secret management.
- **ISO/IEC 27001:** Supports Annex A controls regarding access control and secure development environments.
## Common Pitfalls to Avoid
- **Implicit Trust of Write Access:** Assuming that because a user has write access, they are authorized to view production secrets.
- **Secret Leaking via Fork/Branch:** Failing to realize that any user with push access can create a dummy GitHub Action to `echo` secrets to the logs.
- **Self-Review:** Allowing developers to approve their own PRs or deployment requests.
## Resources
- **GitHub Documentation:** `docs[.]github[.]com/en/actions`
- **Security Testing:** `binarysecurity[.]no` (Consultant Reference)
- **Video Resource:** NDC Security 2025 - "GitHub Actions Security" (YouTube)