Security and CI/CD belong in the build process
A practical release pipeline: least-privilege permissions, reviewed changes, reproducible builds, deployment approvals, live checks and a way back when things fail.
Kareem Schultz
Technology enthusiast & systems builder · Guyana
Jump to a section
A green build is necessary, not sufficient
It is easy to spend most of a software project on the visible feature and treat security as a final checklist. The harder problems often appear later: who can approve a production change, how an automated job authenticates to a cloud provider, whether a failed test was skipped, and how to prove the deployed version is the version that was reviewed.
Security and continuous delivery belong together because the build pipeline is itself a privileged application. It reads source code, resolves dependencies, creates artifacts and may have permission to replace production. That access deserves the same care as any administrative system.
Select a stage of the sample release pipeline below. Each gate shows the expected evidence, a typical failure and the operational decision it should produce. This is an educational model, not a live GitHub Actions run.
Begin with the threat model for your pipeline
A typical repository contains application code, workflow definitions, dependency metadata, configuration and documentation. Some changes are routine; others can modify how CI obtains credentials or what gets deployed. Treat workflow files, dependency installers, generated artifacts and secrets-handling code as security-sensitive paths.
Separate untrusted input from privileged execution. For example, a pull request from an unknown source should not automatically run a deployment job with production secrets. Permission scopes, environment protections and event selection all matter.
OWASP and GitHub both recommend least privilege for job tokens and protecting third-party automation dependencies. Current GitHub recommends pinning third-party actions to a verified full-length commit SHA for immutable references, and keeping action dependencies up to date.
| Pipeline surface | Threat or mistake | Safeguard |
|---|---|---|
| Pull request code | Untrusted script reaches credentials | Unprivileged PR tests; separate deploy job |
| Actions dependencies | Mutable dependency unexpectedly changes | Verified lockfile or pinned commit references |
| Workflow token | Unnecessary write access | Minimal permissions per job |
| Cloud credentials | Long-lived secret exposed to CI | Short-lived OIDC where supported |
| Production deployment | Wrong branch or artifact shipped | Environment protection, artifact provenance |
| Verification | A green job but broken public service | Independent live smoke tests |
A small pipeline with explicit gates
An effective pipeline is usually easier to reason about when each gate answers one question. Are the types and tests correct? Is the change reviewed? Can the exact artifact be identified? Is deployment authorized? Does the published application behave correctly? Each answer should be backed by observable evidence.
Not every team needs an elaborate release platform. A small repository can start with a test job, protected main branch, narrowly scoped deployment identity, staging where practical and a post-deployment HTTP check. Complexity is only justified when it solves a real release risk.
Secrets are not a configuration shortcut
A password committed to a source repository may continue to exist in history after it is removed from the latest file. It should be treated as compromised and rotated. Use a secrets manager or approved deployment identity, scope credentials to the exact environment and keep values out of logs, build output and error messages.
Where supported, OpenID Connect allows a pipeline to request short-lived cloud credentials instead of maintaining a long-lived provider key. This still requires correct trust conditions: define which repository, branch or environment may request which cloud permissions.
Protect credential changes as carefully as application code changes. A job that can update a cloud role or rotate secrets has different risks from one that can only read repository content.
The exact commit and artifact matter
Suppose a branch passes tests, but another commit is added before merge. The earlier green check is not proof that the final deployed revision is safe. The stronger release record identifies the reviewed commit, the artifact built from it and the resulting deployment reference.
An artifact should not quietly change between test and deploy. Use a repeatable build and keep the build output or a trustworthy artifact reference, then deploy that artifact. If rebuilding is necessary, record that choice and verify the result.
An immutable reference and a post-deploy check are complementary: provenance tells you what was supposed to ship, while the live test checks what users can actually reach.
| Gate | Evidence to retain | Failure action |
|---|---|---|
| Validation | Typecheck/test/build result for final commit | Block merge or release |
| Review | Approval linked to the actual diff | Return for changes |
| Build | Artifact identifier and source SHA | Reject uncertain provenance |
| Deploy | Environment, target and release identifier | Stop or rollback if unauthorized |
| Live checks | HTTP, functional and dependency health | Rollback, forward-fix or escalate |
Demonstrate the difference between build and live
A build can finish while the published URL serves a previous version, a runtime environment variable is missing, or a reverse proxy cannot reach its origin. A live test should therefore examine the real domain from an independent network path.
A basic HEAD request is quick and useful, but it does not prove a complete user workflow. Combine a simple status check with a representative permitted action, a session test if relevant, and a check for browser/runtime errors. Use synthetic test data, not real customer credentials.
Define rollback before a bad release
A rollback plan is most useful when it can be rehearsed. It should identify what to redeploy, which data migrations are compatible with the earlier version, and who may authorize the reversal. Deploying an old artifact after an irreversible schema migration can make the incident worse.
Use backward-compatible data changes where practical and separate destructive cleanup from initial deployment. If a change cannot be reversed safely, document a forward-fix path and a maintenance plan before production approval.
Microsoft Azure and AWS operational guidance both emphasize small reversible changes and collecting enough telemetry to respond to unexpected behavior.
Security is also a quality-of-life feature
Well-designed safeguards reduce interruptions. An operator sees why a deployment is blocked, a developer gets an actionable test failure, and a support person can identify which revision is live. Permissions are understandable, approvals have context, and audit records are useful instead of noisy.
Those are user-experience decisions as much as operational decisions. The goal is not a pipeline with the greatest number of badges; it is a release process that is predictable, accountable and possible to troubleshoot after something unexpected happens.
- Make environment and release identity visible to authorized operators.
- Explain which check failed and preserve its logs without leaking secrets.
- Require review proportional to the risk of the change.
- Record who approved sensitive actions and what revision they approved.
- Test recovery and alert delivery as often as the happy path.
An achievable starting checklist
Begin with repository branch protection, a least-privilege workflow token and final-commit tests. Add dependency updates and scanning appropriate to the project. Protect production credentials, keep the deployment isolated from untrusted pull requests, and verify the live site with a test that can fail loudly.
Iterate from incident reviews and actual defects. A sound CI/CD process is neither a marketing badge nor a one-time setup task. It is the collection of habits that allows the team to ship responsibly again tomorrow.
Sources & further reading
These links provide the technical basis for the article. Check upstream advisories and documentation for revisions.
- GitHub — Secure use of GitHub Actions(opens in a new tab)
- GitHub — Security hardening for deployments and OIDC(opens in a new tab)
- GitHub — Deployments, environments and approvals(opens in a new tab)
- OWASP — DevSecOps repository hardening(opens in a new tab)
- Microsoft — Operational excellence(opens in a new tab)
- AWS — Well-Architected operating principles(opens in a new tab)