← Writing
Cloud DeliveryLast reviewed 11 Aug 2026 · 14 min read

Secure CI/CD for Healthcare Apps

The deployment pipeline is a production identity. Configure it with the same care as an administrator, then give it fewer choices.

A pipeline can publish code, change infrastructure, run database migrations, read secrets, and route traffic. That makes it one of the most privileged automated actors in a software platform.

Healthcare delivery does not require slow releases. It requires a pipeline where source, artifact, provenance, identity, target environment, approval, result, and recovery decision can be established after the fact.

My default: build once, promote the same immutable artifact, authenticate with short-lived credentials, and use a different narrowly scoped cloud role for every environment.

This is engineering guidance, not legal advice or a claim that a pipeline is "HIPAA compliant." The appropriate safeguards depend on the organization's risk analysis, systems, agreements, policies, and operating procedures. HHS guidance is useful here because it emphasizes authorized access, audit controls, documented incident response, and tested contingency procedures.

Threat model

Design for mistakes as well as attackers

Many deployment incidents do not begin with a sophisticated compromise. A branch maps to the wrong account, a reusable workflow inherits excessive permissions, a migration runs twice, an environment secret becomes available to a pull request, or a person reruns an old production job.

Source risk

Unreviewed commits, dependency changes, injected workflow values, leaked secrets, and compromised actions.

Identity risk

Long-lived keys, broad roles, weak OIDC trust conditions, and shared credentials.

Target risk

Ambiguous accounts, shared clusters, wrong Regions, and production-like names.

Change risk

Irreversible migrations, missing health checks, unsafe rollbacks, and hidden drift.

Pipeline shape

Separate build from deployment

Protected source + reviewed workflow
└── Test, scan, build, generate SBOM
    └── Immutable artifact + provenance attestation
        ├── Deploy digest to development
        ├── Promote same digest to staging
        └── Approve, verify, deploy same digest to production

The build job should not need production credentials. Deployment jobs should consume an artifact identified by digest or immutable version, not rebuild whatever happens to be on a branch. This reduces the chance that staging tested one binary while production received another.

Generate build provenance that binds the artifact digest to its source and build workflow, then verify that provenance before deployment. Signing or generating an attestation is incomplete if the deployment system never enforces the expected repository, workflow, signer, and digest. For Kubernetes, an admission policy can reject images that do not satisfy the provenance policy; other platforms need an equivalent pre-deploy verification step.

Store a release manifest with the commit and workflow SHA, artifact digest, SBOM, scan results, infrastructure plan, migration version, approver, cloud principal, target, deployment result, and rollback or forward-repair decision. Keep it in an access-controlled system with retention based on organizational policy.

Authentication

Use OIDC instead of stored cloud keys

GitHub Actions can issue an OpenID Connect token containing claims about the repository, workflow, branch, tag, GitHub environment, actor, runner type, and workflow SHA. AWS, Google Cloud, and Azure can exchange that assertion for short-lived cloud credentials.

The security value comes from the cloud trust policy, not merely enabling id-token: write. Grant that permission only to jobs that authenticate, and restrict the token issuer, audience, repository identity, workflow, environment, branch, or tag as the provider supports. Prefer immutable repository IDs or subject claims where available, and validate the actual claims before changing a live trust policy.

AWS

Trust GitHub's OIDC provider from an environment-specific IAM role. Match the expected audience and a narrow subject, then scope the role permissions and session duration.

Google Cloud

Use Workload Identity Federation with explicit attribute mappings and a condition that limits the trusted GitHub organization plus the intended repository, branch, workflow, or environment. Grant the federated principal only the required roles, directly or through controlled service-account impersonation.

Azure

Configure a federated identity credential for an Entra application or user-assigned managed identity with the expected issuer, subject, and audience. Prefer an environment subject for production and scope its Azure role to the deployment target.

Other systems

Use the equivalent workload federation mechanism. If keys remain unavoidable, isolate, rotate, monitor, and expire them.

Create separate trust relationships and roles for development, staging, and production. A condition that trusts every branch or every repository in an organization is too broad for a production role. Short-lived credentials reduce persistence; they do not repair an over-broad trust policy or authorization role.

Permissions

Give the deployment role a deployment job

Do not make the pipeline an account administrator because deployment permissions are inconvenient to enumerate. Separate application deployment, infrastructure changes, database migration, and emergency operations when their risks differ.

  • Limit the role to the target account, project, subscription, Region, cluster, and workload resources.
  • Deny access to patient records unless a deployment step genuinely requires data-plane access.
  • Keep security logging, organization policy, billing, and break-glass controls outside the application role.
  • Use short session durations and attach release context to cloud audit events where supported.
  • Test that the role cannot deploy to another environment.

Apply segregation of duties to the control plane as well as the application: a developer should not be able to change protected source, weaken the production environment rule, broaden the cloud trust policy, approve the same release, and erase its audit evidence alone. Assign code owners for workflows and infrastructure, restrict who can change repository and cloud controls, prevent self-approval where supported, and send audit logs to a boundary the deployment identity cannot alter.

Source and production gates

Make every important decision explicit

Protect the release branch with pull-request reviews, code-owner review for workflow and infrastructure paths, required checks from trusted apps, resolved conversations, and restrictions on direct pushes, force pushes, deletion, and bypass. Dismiss stale approvals or require approval of the latest reviewable push so a new commit cannot inherit an approval for older code.

A production approval should name the artifact digest, infrastructure plan, migration version, target, health criteria, and recovery owner—not approve an open-ended future workflow. Configure a protected deployment environment, required reviewers, prevention of self-review, allowed branches or tags, concurrency controls, and an approval expiry where the platform or an external change system supports them. Disallow administrator bypass when the operating model permits it.

Protect the controls themselves. Changes to deployment workflows, reusable workflows, infrastructure modules, environment rules, runner groups, and cloud trust policies should require review by appropriate owners. Keep the default GITHUB_TOKEN read-only, elevate job permissions only as needed, and pin third-party actions and reusable workflows to reviewed full-length commit SHAs.

Pre-merge security

Scan the change, then record the decision

Require tests, static analysis, secret scanning with push protection, dependency review, and an infrastructure plan before merge. Scan the built artifact or container too: source-only scanning can miss vulnerable operating-system packages or files introduced during the build.

  • Fail dependency review according to a documented vulnerability and license policy; record time-bounded exceptions with an owner and expiry.
  • Run secret scanning on commits and history, block supported secrets before push, and rotate a real credential rather than merely deleting it from the latest commit.
  • Produce an SBOM and vulnerability result for the exact artifact digest that will be promoted.
  • Keep untrusted pull-request jobs read-only, without production secrets or cloud identity, and avoid interpolating untrusted event values into shell scripts.

A green scanner is evidence for a release decision, not proof that the application is secure. Define which findings block, who may accept residual risk, how long an exception lasts, and how remediation is tracked.

Infrastructure changes

Separate plan from apply

Create the infrastructure plan from the reviewed commit using read-only or planning permissions, store it with the release evidence, and require reviewers to inspect replacements, deletions, identity changes, network exposure, encryption changes, logging changes, and state movement. Apply the reviewed plan with a separate production identity after approval; reject stale plans when source, state, variables, provider versions, or target context change.

Use remote state locking and tightly restrict access to state because it can contain sensitive configuration. Keep policy checks and destructive-change gates independent from the role that performs the apply. Afterward, record the actual change result and reconcile drift rather than treating the pre-deploy plan as the final record.

Runner isolation

Treat every runner as a security boundary

Prefer fresh hosted or ephemeral runners for untrusted build work. A persistent self-hosted runner can retain files, credentials, processes, or access between jobs; a container label does not by itself isolate the host. Do not place pull requests from forks or other untrusted code on a runner with network reachability to production, internal package systems, secrets, or a privileged container socket.

  • Separate build, deployment, and production runner groups; allow only selected repositories and workflows to use privileged groups.
  • Use an ephemeral runner per job where self-hosting is required, start from a maintained image, patch it, and destroy the compute and workspace afterward.
  • Restrict outbound network access and metadata-service access, and monitor the runner host independently of the workflow.
  • Assume any credential available to one step may be exposed by another compromised step in that job.
Secrets and PHI

Keep secrets and patient data out of pipeline output

OIDC removes stored cloud access keys, not every secret. Applications still need database credentials, API keys, certificates, and vendor tokens. Store them in the environment's secret manager and let the runtime retrieve them where possible. GitHub environment approval can delay access to environment secrets, but it does not make a self-hosted runner isolated.

  • Do not echo secrets, decoded tokens, connection strings, request bodies, or deployment environment dumps.
  • Use synthetic data in automated tests and sanitized fixtures in build artifacts.
  • Keep production database snapshots and diagnostic exports outside CI workspaces.
  • Review artifacts, test reports, screenshots, traces, and failure attachments for PHI exposure.
  • Set retention and access rules for workflow logs and artifacts.
  • Use a credential broker or masking as defense in depth, but never rely on log redaction as the only protection.

A test failure that uploads a browser screenshot, SQL row, HTTP transcript, crash dump, tracing payload, or environment snapshot can disclose more than the deployment itself. Tests should use synthetic data by default. If production diagnosis is unavoidable, use a separately authorized process outside the ordinary build path and collect only the minimum approved evidence.

Database changes

Treat migrations as releases of their own

Database migrations deserve an explicit identity, compatibility window, checkpoint, and recovery plan. Prefer expand-and-contract changes that allow old and new application versions to coexist: add before remove, deploy compatible code, backfill in bounded and resumable batches, verify, switch reads or writes, and clean up in a later release.

Give the migration job only the schema or data permissions it needs, serialize it, make retry behavior explicit, and record the migration version and result. Before production, test duration, locking, replication lag, backup impact, and abort criteria against representative scale. Take or verify an appropriate recovery point before an irreversible operation.

Define whether recovery means reverting code, applying a forward repair, restoring data, replaying an event stream, or failing over. A rollback button cannot reverse every schema or data transformation, and restoring a database can discard valid writes made after the recovery point.

Verification

Deployment success is not process exit zero

  1. Confirm the expected artifact digest reached the intended environment.
  2. Run health, authorization, dependency, and migration checks.
  3. Watch error rate, latency, saturation, and critical healthcare workflows.
  4. Record release metadata in deployment, cloud audit, observability, and incident systems without PHI.
  5. Stop or roll back automatically when defined safety thresholds fail.

Use canary, blue-green, or progressive delivery when the platform and workload justify it. The strategy matters less than having measurable acceptance and a practiced recovery path.

Emergency releases

Shorten the path without making it invisible

Define an emergency route before an incident. It may reduce the normal approval count or test set, but it should not use a shared permanent administrator key or bypass artifact identity, target checks, and audit logging. Limit invocation to named on-call roles, require a linked incident or change record and a second person when feasible, issue time-limited access, and notify security and service owners automatically.

Record why the path was used, requester, approver, artifact digest, commands or workflow, target, timestamps, result, and any deferred control. Revoke elevated access when the emergency ends, normalize access, complete the skipped checks, review the change promptly, and capture corrective actions. HHS materials require emergency access and contingency procedures for applicable regulated organizations, but each organization must determine its own legal and operational requirements with authorized privacy, security, and legal owners.

Review checklist

Before allowing a production deployment

  1. Does the job use short-lived credentials bound to this repository identity, workflow, environment, and audience?
  2. Can it modify only the intended workload and environment?
  3. Is the production digest identical to the artifact validated in staging, and is its provenance enforced?
  4. Are protected source, workflow, dependency, secret, artifact, and infrastructure checks complete or covered by an owned, expiring exception?
  5. Are workflow, infrastructure, environment, trust-policy, and runner changes reviewed by appropriate owners?
  6. Are build and deployment runners isolated from untrusted code and from each other?
  7. Can logs, artifacts, screenshots, or test output contain PHI or secrets?
  8. Are database compatibility, verification, and recovery steps defined?
  9. Can an investigator reconstruct who requested, approved, and deployed which digest and plan to which target?
  10. Does the emergency path preserve identity, evidence, revocation, and retrospective review?
Related reading

Put the pipeline inside clear boundaries

Secrets and Encryption-Key Management

Let delivery configure references and workload identities without exposing production values.

Multi-Environment Cloud Architecture

Separate accounts, projects, subscriptions, networks, identities, and data by environment.

Production Data in Lower Environments

Use synthetic and controlled datasets without turning staging into an unmanaged PHI copy.

Centralized Cloud Audit Logging

Preserve deployment and cloud evidence outside the identity that makes production changes.

Sources reviewed 11 Aug 2026: GitHub OIDC claims, deployment environments, secure use and runners, artifact attestations, dependency review, secret security, protected branches, AWS OIDC role trust, Google Cloud deployment federation, Azure Login with OIDC, and the HHS HIPAA Audit Protocol.