Leandro Mantovani

Leandro Mantovani

How CTOs Can Automate Zero-Trust CI/CD and SLSA Without Killing Velocity

How CTOs Can Automate Zero-Trust CI/CD and SLSA Without Killing Velocity

Imagine discovering that a foundational piece of your startup’s infrastructure was quietly compromised by a nation-state actor over two years—and your sophisticated, expensive security scanners didn’t say a word. For CTOs, the XZ Utils backdoor wasn’t just a headline; it was a terrifying wake-up call that shattered the illusion of modern CI/CD security. The reality is grim: reactive vulnerability scanning is dead. But for lean engineering teams pushing aggressive roadmaps, slamming the brakes to implement draconian supply chain policies is an equally fatal threat.

For startup executives managing lean teams and aggressive roadmaps, this raises an existential question: If a malicious actor can almost compromise the entire global open-source ecosystem, what malicious code is quietly hiding in your startup's unverified pipeline dependencies?

The immediate reaction to supply chain threats is often a knee-jerk implementation of draconian security policies. But in the startup world, blocking developer velocity to implement strict security compliance—like SLSA and SBOMs—is a death sentence. You need to ship features to survive. 

In this post, we'll explore why reactive scanning is dead, how to technically implement proactive Software Supply Chain Security without adding friction to your developers' workflows, and how Betta's fractional SREs are helping startups achieve enterprise-grade security while maintaining day-one agilit

The Illusion of Security: Why Reactive CVE Scanning is Dead

For the last decade, CI/CD security was synonymous with running a quick `npm audit`, utilizing Dependabot, or slapping a container scanner on the end of a build pipeline. If the scan came back green (or, let's be honest, mostly yellow), the artifact was deployed.

The XZ Utils incident proved that this reactive model is fundamentally broken for modern threats. Vulnerability scanners look for known vulnerabilities (CVEs) that have already been identified, analyzed, and published. Supply chain attacks—such as malicious pull requests, compromised maintainer accounts, dependency confusion, and typo-squatting—introduce zero-day malicious code that scanners simply bypass because the code *functions* exactly as the attacker intended. It isn't a vulnerability; it's a feature designed by a malicious actor.

Enter SLSA: Proactive Supply Chain Security

To stop pipeline poisoning and supply chain attacks, engineering organizations are shifting to the SLSA (Supply chain Levels for Software Artifacts) framework. Created by Google, SLSA is a set of incrementally adoptable security guidelines designed to prevent tampering, improve integrity, and secure packages and infrastructure in your projects.

Rather than just scanning the final output, SLSA secures the process of building the software.

  • SLSA Level 1: You have a build process, and you generate provenance (metadata about how an artifact was built).

  • SLSA Level 2: The build service requires authentication, and the provenance is authenticated.

  • SLSA Level 3: The source and build platforms meet specific standards to guarantee the auditability and integrity of the provenance.

  • SLSA Level 4: Two-person review of all changes and a fully hermetic, reproducible build process.

For most high-growth startups, achieving SLSA Level 2 or 3 is the sweet spot. It provides massive risk reduction without requiring the grueling overhaul necessary for hermetic builds (Level 4). But how do you implement this without forcing developers to jump through hoops?


Automating the Heavy Lifting: Transparent SBOMs and Container Signing

The golden rule of DevSecOps is simple: If security requires developers to remember extra commands or steps, it will fail. 

To achieve SLSA compliance, you need two critical components generated on every build:

  1. SBOM (Software Bill of Materials): A comprehensive inventory of all software components, dependencies, and metadata in your application.

  2. Cryptographic Signatures:Proof that the container or artifact was built by your trusted CI/CD system and hasn't been tampered with since.

You can automate this entirely within your CI/CD pipelines (e.g., GitHub Actions or GitLab CI) using tools like Syft (for SBOM generation) and Sigstore's Cosign (for keyless signing).

The Technical Implementation: Keyless Signing in GitHub Actions

Historically, managing private keys for code signing was a nightmare. Keys would be stored in CI variables, rotated rarely, and inevitably leaked. Sigstore revolutionized this by introducing keyless signing using OIDC (OpenID Connect). The CI runner proves its identity to an overarching certificate authority (Fulcio), signs the artifact, and logs the signature in an immutable ledger (Rekor).

Here is a technical example of how you can implement transparent SBOM generation and container signing in a GitHub Actions workflow:


name: Build, SBOM, and Sign

on:
  push:
    branches: [ "main" ]

# Crucial: Give the workflow permissions to request an OIDC token
permissions:
  contents: read
  packages: write
  id-token: write

jobs:
  build-and-sign:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v3
      - name: Install Cosign
        uses: sigstore/cosign-installer@v3.1.1
        with:
          cosign-release: 'v2.1.1'
      - name: Install Syft
        uses: anchore/sbom-action/download-syft@v0.14.2
      - name: Log into GitHub Container Registry
        uses: docker/login-action@v2
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build and Push Docker Image
        id: build-image
        uses: docker/build-push-action@v4
        with:
          push: true
          tags: ghcr.io/your-startup/your-app:${{ github.sha }}
      - name: Generate and Attest SBOM
        run: |
          syft ghcr.io/your-startup/your-app:${{ github.sha }} -o spdx-json=sbom.spdx.json
          cosign attest --yes --predicate sbom.spdx.json --type spdx \
          ghcr.io/your-startup/your-app:${{ github.sha }}
      - name: Sign the Published Image (Keyless)
        run: |
          cosign sign --yes ghcr.io/your-startup/your-app:${{ github.sha }}

name: Build, SBOM, and Sign

on:
  push:
    branches: [ "main" ]

# Crucial: Give the workflow permissions to request an OIDC token
permissions:
  contents: read
  packages: write
  id-token: write

jobs:
  build-and-sign:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v3
      - name: Install Cosign
        uses: sigstore/cosign-installer@v3.1.1
        with:
          cosign-release: 'v2.1.1'
      - name: Install Syft
        uses: anchore/sbom-action/download-syft@v0.14.2
      - name: Log into GitHub Container Registry
        uses: docker/login-action@v2
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build and Push Docker Image
        id: build-image
        uses: docker/build-push-action@v4
        with:
          push: true
          tags: ghcr.io/your-startup/your-app:${{ github.sha }}
      - name: Generate and Attest SBOM
        run: |
          syft ghcr.io/your-startup/your-app:${{ github.sha }} -o spdx-json=sbom.spdx.json
          cosign attest --yes --predicate sbom.spdx.json --type spdx \
          ghcr.io/your-startup/your-app:${{ github.sha }}
      - name: Sign the Published Image (Keyless)
        run: |
          cosign sign --yes ghcr.io/your-startup/your-app:${{ github.sha }}

Closing the Loop: Enforcing Signatures in Kubernetes

Generating signatures is only half the battle; you must enforce them at deployment. When your orchestration tool (like Kubernetes) pulls the image, an admission controller must verify the signature before allowing the pod to run. 

Using Kyverno, you can deploy a zero-trust policy that validates the Sigstore keyless signature seamlessly. If an attacker injects a malicious image into your registry, it won't have the OIDC-backed signature, and Kubernetes will outright reject it.


apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signatures
spec:
  validationFailureAction: Enforce
  rules:
    - name: verify-github-actions-signature
      match:
        resources:
          kinds:
            - Pod
      verifyImages:
        - imageReferences:
          - "ghcr.io/your-startup/*"
          attestors:
          - entries:
            - keyless:
                subject: "https://github.com/your-startup/your-repo/.github/workflows/build.yml@refs/heads/main"
                issuer: "https://token.actions.githubusercontent.com"
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signatures
spec:
  validationFailureAction: Enforce
  rules:
    - name: verify-github-actions-signature
      match:
        resources:
          kinds:
            - Pod
      verifyImages:
        - imageReferences:
          - "ghcr.io/your-startup/*"
          attestors:
          - entries:
            - keyless:
                subject: "https://github.com/your-startup/your-repo/.github/workflows/build.yml@refs/heads/main"
                issuer: "https://token.actions.githubusercontent.com"


Why this matters for developer velocity: The developers just push code. The pipeline automatically builds the image, generates the SBOM, attests it to the container, and cryptographically signs it. The cluster enforces it automatically. Velocity remains at 100%.


Hardening the Build Environment: Zero-Trust CI/CD Runners

Even with SBOMs and signing, your software supply chain is only as secure as the environment running the build. A compromised CI/CD runner is an attacker's dream—it holds the keys to your cloud environment, your infrastructure-as-code, and your production deployments.

Eliminating Long-Lived Credentials

If your GitHub repository still has secrets like AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY stored in the settings, you are highly vulnerable. If an attacker compromises a dependency in your testing phase, they can execute arbitrary code on the runner and exfiltrate those static credentials, gaining permanent backdoor access to your AWS account.

The Fix: Transition completely to OIDC federation. With OIDC, your CI/CD platform acts as an Identity Provider. AWS trusts GitHub, and the runner requests temporary, short-lived STS credentials valid only for the duration of the job.

AWS IAM Trust Policy Example for GitHub Actions:


{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringLike": {
          "token.actions.githubusercontent.com:sub": "repo:your-startup/your-app:*"
        },
        "StringEquals": {
          "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
        }
      }
    }
  ]
}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringLike": {
          "token.actions.githubusercontent.com:sub": "repo:your-startup/your-app:*"
        },
        "StringEquals": {
          "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
        }
      }
    }
  ]
}


Ephemeral, Isolated Runners

Shared, long-lived build runners (like a dedicated EC2 instance running Jenkins or GitLab Runner 24/7) accumulate state. If one build pulls a malicious, typo-squatted NPM package, it could subtly modify the global node modules or the build cache, poisoning all subsequent builds. 

To achieve SLSA Level 3, build environments must be ephemeral and isolated.

Using tools like Actions Runner Controller (ARC) on Kubernetes (EKS) combined with Karpenter, you can dynamically spin up a fresh, pristine pod for every single CI/CD job. 

  1. A developer pushes code.

  2. ARC requests a runner pod.

  3. Karpenter provisions compute instantly.

  4. The job runs in a completely isolated, zero-trust container.

  5. The runner is immediately destroyed.

Any malicious artifact introduced during the build dies with the runner. Furthermore, you can apply strict Egress Network Policies to these runner pods. The build runner only needs outbound access to your trusted registries, GitHub, and your cloud provider API. Denying generic outbound internet access effectively stops data exfiltration in its tracks.


The 80/20 Pivot: The Fractional SRE Advantage

Implementing SLSA Level 3, deploying keyless signing via Cosign, writing admission controllers via Kyverno, migrating static secrets to OIDC, and building ephemeral runner fleets is complex, highly specialized work. 

Herein lies the trap for scaling startups: Your core engineering team should be building features that generate revenue, not wrestling with CI/CD plumbing.

When the XZ Utils news broke, one of our clients—a fast-growing Series B fintech startup—realized they were completely exposed. Their enterprise customers were demanding SOC 2 compliance and robust SBOMs, but pulling their senior engineers off the product roadmap to harden the supply chain would have caused a critical product launch to slip by an entire quarter. 

This is exactly where Betta steps in. 

Through our fractional SRE and platform engineering model, we partnered with their internal team. Our experts—who build these highly secure, ephemeral pipelines every day—came in as a specialized strike team. 

Within three weeks, we:

  • Audited and mapped their entire software supply chain.

  • Migrated 100% of their legacy static secrets to OIDC federation.

  • Implemented transparent SBOM generation and Sigstore keyless signing in GitHub Actions.

  • Deployed Actions Runner Controller (ARC) on an isolated EKS cluster for completely ephemeral, zero-trust builds.

  • Set up Kyverno admission controllers to block any unsigned images from running in production.

The Developer Velocity Drop? Zero.

The product engineers simply kept pushing code to the main branch. The only difference was that under the hood, the entire supply chain was now armored against state-level threat vectors, unblocking their enterprise sales pipeline instantly.

Why Fractional Makes Economic Sense

You don't need a full-time, $250k/year DevSecOps engineer to maintain this setup once it's built. Securing the software supply chain is an intense, front-loaded architectural challenge. By partnering with Betta, startups gain access to elite, specialized talent to design and implement the foundation correctly the first time. We build the paved road, secure the guardrails, and hand the keys back to your team. 

In a post-XZ world, you can no longer afford to treat your CI/CD pipeline as an afterthought. But you also can't afford to freeze developer velocity to fix it. With the right architecture and the right specialized partner, you don't have to choose.

Cloud Infrastructure Experts

AWS cloud experts delivering scalable, secure,

and cost-efficient infrastructure solutions for growing teams.

Let’s Talk

Get expert guidance on secure

and scalable cloud solutions.

Cloud Infrastructure Experts

AWS cloud experts delivering scalable, secure,

and cost-efficient infrastructure solutions for growing teams.

Let’s Talk

Get expert guidance on secure and scalable

cloud solutions.