The Pipeline as a General-Purpose Program
Traditional CI systems like Jenkins and older GitHub Actions workflows operate on relatively constrained YAML configurations. The shift to CI-as-code with frameworks like Dagger changes this fundamentally: your pipeline is now a Python, Go, or TypeScript program that executes arbitrary code in a containerised environment with access to deployment credentials, signing keys, artifact registries, and production systems.
This shift provides real benefits β type-checked pipelines, reusable modules, local testing. But it also means that every security consideration that applies to production code now applies to pipeline code. Pipelines can have dependency vulnerabilities, injection vulnerabilities, and logic flaws that give attackers capabilities far beyond "break the build".
The highest-privilege code in your system: Your pipeline code runs in an environment that has credentials for your artifact registry, your deployment cluster, your signing infrastructure, and often your production secrets vault. Compromising pipeline code is often more impactful than compromising an individual application.
Dagger's Security Model
Dagger executes pipelines inside a BuildKit daemon, with each pipeline function running in an isolated container. This provides better isolation than native GitHub Actions runners, but introduces its own risk surface. Dagger functions can access secrets via the Dagger secrets API, which passes them as environment variables to container executions. These secrets are not logged, but they are accessible to any Dagger module that is invoked in the pipeline.
Dagger's module ecosystem β published to the Dagger Cloud registry β is an npm-like ecosystem for pipeline building blocks. A malicious or compromised Dagger module can exfiltrate secrets that are passed to it, make outbound network calls during what appears to be a legitimate build step, or modify build artifacts before they are signed and pushed.
Dagger modules are untrusted code: When you call a Dagger module from the Dagger registry, you are executing third-party code in your pipeline environment with access to any secrets you have loaded. Pin modules to specific digest versions and review their source before use.
Tekton Attack Patterns
Tekton runs pipeline tasks as Kubernetes pods, with pipeline steps executing as containers in those pods. Tekton pipelines are Kubernetes custom resources, and the Tekton controller has ClusterRole permissions to create pods, manage PipelineRuns, and access secrets in any namespace it manages. Attack patterns against Tekton pipelines include:
- Workspace volume manipulation: Tekton workspaces are shared volumes between pipeline tasks. A malicious task step can modify workspace contents β such as replacing a compiled binary with a backdoored version β that downstream tasks then sign and publish.
- EventListener injection: Tekton Triggers use EventListeners to start pipelines from webhook events. Unvalidated webhook payloads can be used to inject parameters into PipelineRun resources, influencing pipeline behaviour.
- ServiceAccount escalation: Pipeline pods run under a Tekton ServiceAccount. Overly permissive bindings on this account can allow a pipeline step that achieves code execution to interact with the Kubernetes API, read cluster secrets, or modify other workloads.
Argo Workflows RBAC and API Exposure
Argo Workflows provides a UI and API for viewing, triggering, and managing workflow runs. The Argo Workflows API is often accessible to all cluster users without fine-grained role restrictions. An attacker who can access the Argo Workflows API can read workflow definitions (which contain step commands and references to secrets), trigger new workflow runs with modified parameters, and read the outputs of previous runs β which may contain sensitive build artifacts or deployment tokens.
Pipeline Module Supply Chain
CI-as-code frameworks introduce module ecosystems that extend the pipeline supply chain beyond application dependencies. Dagger modules, Tekton catalog tasks, and Argo Workflows templates are all external content that pipelines depend on. Each of these can be compromised to inject malicious steps into builds without modifying the application code itself β making the attack invisible to code review focused on application changes.
Pipeline Hardening
- Apply the same code review standards to pipeline code as to application code: Pipeline changes that modify secret access, deployment targets, or build artifact handling require security team review.
- Pin all external pipeline modules to specific digest hashes: Never reference external modules by tag β tags are mutable. Pin to immutable digest references and verify them against known-good values.
- Scope pipeline service accounts to minimum required permissions: Pipeline pods should have only the Kubernetes and cloud permissions required for their specific tasks. Avoid shared service accounts with broad access across all pipelines.
- Separate signing and deployment credentials from build credentials: The credentials that sign artifacts and deploy to production should not be accessible to arbitrary pipeline steps. Introduce approval gates or separate signing workflows that are not inline with build steps.
- Audit pipeline API access: Restrict access to Argo Workflows and Tekton APIs to pipeline operators and CI systems. Require authentication for all API operations and log every trigger, parameter modification, and output access.
- Scan pipeline code for secrets and injection vulnerabilities: Apply SAST scanning to your pipeline code. Flag hard-coded credentials, unvalidated parameter interpolation into shell commands, and broad secret access patterns.