Dynamic Secret Injection in CI/CD: When to Use It and How to Implement It

Retool's new app builder is where AI-generated code ships safely
Building apps with AI is easy. Getting them to production safely is another story.
Every CI/CD pipeline needs credentials: database passwords for integration tests, API keys for deployment targets, container registry credentials for pushing images, cloud credentials for infrastructure provisioning. The question is not whether credentials exist -- it is whether they are long-lived static secrets that need manual rotation and are valid indefinitely if compromised, or short-lived dynamic secrets that are scoped to a single pipeline run and expire automatically.
Static secrets in CI/CD platform secret stores (GitHub Actions encrypted secrets, GitLab CI variables, Jenkins credentials) are operationally simple: configure once, use indefinitely. The security properties are correspondingly simple: a compromised secret is valid until someone rotates it manually, and every pipeline in the repository can access the same credential regardless of the specific workflow.
Dynamic secrets require more implementation work upfront but change the risk profile: a compromised credential from a dynamic pipeline is valid for 15 minutes rather than indefinitely, and the credential is scoped to the specific pipeline run that generated it rather than shared across all workflows. For high-privilege credentials (production database access, cloud deployment credentials), this tradeoff is worth the implementation complexity. For lower-privilege credentials (read-only access to a test artifact store), static secrets with automated rotation are often sufficient.
This guide covers the decision framework for when dynamic secrets are worth the complexity, the four implementation approaches, and the monitoring required to detect dynamic secret abuse.
The Decision Framework: Dynamic vs. Static for Each Credential Type
Not every pipeline credential benefits equally from dynamic injection. The decision framework considers three factors: the privilege level of the credential, the blast radius if the credential is compromised, and the rotation burden of managing it statically.
Use dynamic secrets when:
- The credential provides write, delete, or administrative access to a production system (production database, production cloud account, production Kubernetes cluster)
- The credential, if compromised, would allow an attacker to access customer data, financial systems, or production infrastructure
- The credential is used in a pipeline that runs frequently (multiple times per day), creating high re-use of the same static credential and a long exposure window
- Compliance requirements mandate credential rotation at a frequency shorter than the operational tolerance for manual rotation (NIST SP 800-57 recommends 90 days max for symmetric keys in production -- manual rotation at that frequency is feasible but error-prone)
Static secrets with automated rotation are sufficient when:
- The credential provides read-only access to non-production systems (a test database, a staging artifact store)
- The blast radius of compromise is limited (a compromised credential can only read test data, not modify production)
- The credential is used in a low-frequency pipeline where re-use risk is minimal
- The target system does not support dynamic credential generation (some legacy systems can only accept static username/password authentication)
Zero-credential pipelines (best practice for cloud deployments): For AWS, GCP, and Azure deployments from GitHub Actions, GitLab CI, or CircleCI, the OIDC federation approach eliminates stored credentials entirely. The pipeline authenticates using a short-lived OIDC token generated by the CI/CD platform, which is exchanged for a cloud platform IAM token. No credential is stored anywhere -- the pipeline identity is verified by the CI/CD platform's signing of the OIDC token.
Approach 1: Cloud OIDC Federation -- Zero-Credential Cloud Deployments
GitHub Actions OIDC federation with AWS, GCP, and Azure is the most impactful dynamic secret approach because it eliminates stored cloud credentials entirely rather than replacing one credential type with another.
How it works: GitHub generates a short-lived OIDC token for each workflow run. The token contains claims about the workflow: the repository name, the branch, the workflow name, the triggering event. The CI/CD platform signs this token with its private key. Your cloud provider verifies the signature using GitHub's published JWKS endpoint and, if the token's claims match your trust policy, issues a short-lived cloud IAM token.
AWS implementation. Create an IAM OIDC Identity Provider in AWS for token.actions.githubusercontent.com. Create an IAM role with a trust policy that permits assumption by the OIDC provider with conditions matching your repository name and branch: StringLike: {"token.actions.githubusercontent.com:sub": "repo:your-org/your-repo:ref:refs/heads/main"}. In the GitHub Actions workflow, use the aws-actions/configure-aws-credentials action with role-to-assume pointing to the IAM role ARN and aws-region set. No AWS access key or secret key is stored anywhere in GitHub secrets.
GCP implementation. Create a Workload Identity Pool and Provider in GCP for the GitHub Actions OIDC endpoint. Map GitHub token claims to Google Cloud identities. Bind the Workload Identity user to a service account with the required permissions. In the workflow, use google-github-actions/auth with workload_identity_provider and service_account parameters.
Azure implementation. Use Azure Federated Credentials on an Azure App Registration. Configure a federated credential that trusts token.actions.githubusercontent.com for the specific repository and entity (branch, environment, or tag). In the workflow, use azure/login@v1 with client-id, tenant-id, and subscription-id (no client-secret required when using federated credentials).
Briefings like this, every morning before 9am.
Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.
Approach 2: HashiCorp Vault Dynamic Secrets for Database and API Credentials
HashiCorp Vault's dynamic secrets engine generates database credentials on-demand with configurable TTLs. Each credential generation creates a unique username and password that Vault manages the lifecycle of -- rotating before TTL expiration and revoking at the lease end.
Vault database dynamic secrets setup:
- Enable the database secrets engine:
vault secrets enable database - Configure a database connection:
vault write database/config/prod-postgres plugin_name=postgresql-database-plugin connection_url="postgresql://{{username}}:{{password}}@prod-db:5432/appdb" allowed_roles="deploy-role" username="vault-admin" password="..." - Create a role that defines the credential lifetime and SQL permissions:
vault write database/roles/deploy-role db_name=prod-postgres creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}' IN ROLE app_readonly;" default_ttl="15m" max_ttl="1h" - The pipeline authenticates to Vault (using the OIDC/JWT auth method bound to the pipeline's identity token), reads
vault read database/creds/deploy-role, and receives a unique username and password valid for 15 minutes.
Vault authentication from CI/CD: Use the Vault JWT/OIDC auth method with the CI/CD platform's OIDC token as the authentication mechanism. This makes the pipeline's Vault authentication itself dynamic -- the pipeline does not have a static Vault token stored in GitHub secrets. The JWT auth method validates the CI/CD OIDC token and issues a Vault token scoped to the specific policy for the pipeline's role.
For pipelines that need a static Vault token as a bootstrap credential: Use a short-lived approle credential (role_id + secret_id) stored in GitHub secrets, with secret_id rotation configured in Vault. The role_id is not sensitive (it is public); the secret_id is sensitive but is a single-use token that Vault can rotate automatically.
Approach 3: AWS IAM for Pipeline Database Credentials (No Vault Required)
For AWS-hosted pipelines deploying to AWS-hosted databases, the AWS IAM database authentication feature provides dynamic credential generation without Vault. RDS and Aurora support IAM authentication, which generates database tokens from IAM credentials rather than storing database passwords.
Setup for AWS IAM database authentication:
- Enable IAM authentication on the RDS instance or Aurora cluster.
- Create an IAM policy that allows
rds-db:connectfor the specific DB instance and database user. - Attach the policy to the IAM role assumed by the CI/CD pipeline (via OIDC federation as described in Approach 1).
- In the pipeline, use
aws rds generate-db-auth-tokento generate a 15-minute authentication token using the pipeline's current IAM credentials. The token is used as the database password in the connection string.
This approach eliminates the database password entirely for AWS-hosted databases. The database authentication uses the pipeline's IAM identity, which is already dynamic (via OIDC federation), making the database credential chain fully dynamic with no stored secrets.
For non-AWS databases in AWS pipelines: AWS Secrets Manager supports automatic rotation for RDS, Redshift, DocumentDB, and custom secrets with Lambda rotation functions. While not strictly dynamic secrets (the credential is fetched at pipeline start rather than generated uniquely per run), automatic rotation with 30-day intervals reduces the credential lifetime significantly versus manual rotation. This is the "static secrets with automated rotation" approach from the decision framework -- appropriate for lower-privilege or legacy-system credentials.
Monitoring Dynamic Secret Usage: Detecting Abuse
Dynamic secrets reduce the risk of credential compromise but do not eliminate it. A pipeline with a 15-minute TTL credential can still be used maliciously during those 15 minutes if the pipeline is triggered by a malicious actor or if the credential is extracted during the pipeline run.
Vault audit logging. Enable Vault audit logging for all credential generation events. Each dynamic credential generation records: the authentication method used, the policy that permitted the generation, the role or path accessed, the issuing IP address, and the generated credential identifier (without the secret itself). Alert on credential generation from unexpected authentication sources (IP addresses outside your CI/CD runner network, unexpected auth method usage) and on credential generation volume spikes (more generations in an hour than typical for the repository).
AWS CloudTrail for OIDC role assumptions. Every time a GitHub Actions workflow assumes an AWS IAM role via OIDC, CloudTrail records: AssumeRoleWithWebIdentity with the repository name, workflow name, and assumed role ARN. Alert on assumptions from unexpected repositories (a repository that should not have access to the production deployment role), unexpected workflow names (a new workflow file in the repository that was not in the allowlist), and assumptions outside normal business hours for your CI/CD workflows.
Anomaly detection for dynamic credential usage pattern. If a pipeline typically generates one set of database credentials per run and runs 10 times per day, an anomaly is 50 credential generations in one hour. Configure a SIEM alert or CloudWatch metric that fires when dynamic credential generation volume exceeds 2 standard deviations from the rolling 7-day average. Volume spikes may indicate a pipeline running in an abnormal loop, a build farm misconfiguration, or a compromised workflow being triggered repeatedly.
Migrating From Static to Dynamic: The Transition Sequence
Migrating from static secrets to dynamic injection does not require a big-bang cutover. A staged migration reduces risk and allows validation at each step.
Stage 1: Inventory and classify all pipeline secrets. List every secret currently stored in your CI/CD platform (GitHub Actions secrets, GitLab CI variables, Jenkins credentials). Classify each by the decision framework: which should move to dynamic injection (high-privilege production credentials), which should stay as static with automated rotation (low-privilege test credentials), and which can be eliminated (unused secrets from decommissioned integrations).
Stage 2: Implement zero-credential cloud access first. The OIDC federation approach for cloud deployments is the highest-impact, lowest-disruption migration. The change: replace AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY GitHub secrets with IAM OIDC trust configuration and the configure-aws-credentials action. This requires no changes to the pipeline's downstream operations -- the workflow still has valid AWS credentials at the point where it needs them. Test in a staging workflow before migrating the production deployment workflow.
Stage 3: Migrate highest-privilege database credentials to dynamic generation. After cloud access is dynamic, migrate production database credentials to Vault dynamic secrets or AWS IAM database authentication. Run parallel validation: the same integration tests passing with both the old static credential and the new dynamic credential before removing the static credential from GitHub secrets.
Stage 4: Implement automated rotation for remaining static secrets. For secrets that stay as static (legacy systems, third-party APIs without OIDC support), implement automated rotation via Vault secret sync, AWS Secrets Manager rotation, or a custom rotation Lambda. Rotation should occur at a maximum 90-day interval with automatic propagation to the CI/CD platform's secret store.
The bottom line
Dynamic secret injection in CI/CD changes the credential compromise risk profile from "indefinitely valid, manually rotated, shared across all workflows" to "minutes-valid, automatically revoked, scoped to the specific pipeline run." The tradeoff is implementation complexity -- which is worth paying for high-privilege production credentials (cloud deployment access, production database credentials) and not worth paying for low-privilege non-production credentials where static secrets with automated rotation are sufficient. The four approaches -- cloud OIDC federation (zero-credential cloud deployments), Vault dynamic secrets (database and API credentials), AWS IAM database authentication (AWS-native dynamic database access), and automated rotation for remaining static secrets -- together produce a pipeline environment where the most dangerous credentials are the shortest-lived ones and the easiest ones to generate are the most scoped.
Frequently asked questions
What is the difference between static secrets and dynamic secrets in CI/CD?
Static secrets are long-lived credentials stored in the CI/CD platform's secret store (GitHub Actions encrypted secrets, GitLab CI variables) and retrieved by each pipeline run. They are valid indefinitely, shared across all workflows in the repository, and require manual rotation. Dynamic secrets are generated uniquely for each pipeline run at execution time, are valid for a short TTL (typically 15 minutes to 1 hour), are scoped to the specific pipeline context (repository, branch, workflow), and are automatically revoked when the pipeline completes. A compromised dynamic credential from a specific run is useful only until its TTL expires.
When should I use dynamic secrets versus static secrets in a CI/CD pipeline?
Use dynamic secrets for credentials that provide write, delete, or administrative access to production systems (production database passwords, cloud deployment credentials, production Kubernetes access), credentials where compromise would expose customer data or financial systems, and credentials used in high-frequency pipelines that run multiple times per day. Static secrets with automated rotation are sufficient for read-only access to non-production systems, lower-privilege credentials with limited blast radius, and systems that do not support dynamic credential generation. For AWS, GCP, and Azure cloud deployments from GitHub Actions or GitLab CI, OIDC federation eliminates stored credentials entirely (zero-credential pipelines).
How do I implement zero-credential AWS deployments from GitHub Actions?
Use GitHub Actions OIDC federation with AWS IAM. Create an IAM OIDC Identity Provider in AWS for `token.actions.githubusercontent.com`. Create an IAM role with a trust policy that permits assumption by the OIDC provider with conditions matching your repository and branch. In the GitHub Actions workflow, use the `aws-actions/configure-aws-credentials` action with `role-to-assume` set to the IAM role ARN. No AWS access key or secret key is stored anywhere in GitHub secrets -- the pipeline authenticates using GitHub's signed OIDC token, which AWS verifies using GitHub's published JWKS endpoint.
How do HashiCorp Vault dynamic database credentials work?
Vault's database secrets engine generates unique database credentials on-demand when the pipeline requests them. The pipeline authenticates to Vault (using the CI/CD platform's OIDC token via Vault's JWT auth method -- no stored Vault token required), reads a database role path, and receives a unique username and password valid for the configured TTL (typically 15 minutes). Vault creates this user in the database with the permissions defined in the role's creation SQL statement. When the TTL expires, Vault automatically revokes the credential by dropping the database user. Each pipeline run gets a unique credential that no other run shares.
How do I detect dynamic secret abuse in CI/CD pipelines?
Three monitoring controls detect dynamic secret abuse: Vault audit logging (enable audit for all credential generation events, alert on generation from unexpected authentication sources or IP addresses outside your CI/CD runner network), AWS CloudTrail for OIDC role assumptions (every AssumeRoleWithWebIdentity event records the repository, workflow, and assumed role -- alert on assumptions from unexpected repositories or workflow names), and volume anomaly detection (alert when dynamic credential generation volume exceeds 2 standard deviations from the rolling 7-day average, which may indicate a compromised workflow running in an abnormal loop).
How do I migrate from static secrets to dynamic injection without breaking pipelines?
Use a staged migration: first, implement OIDC federation for cloud deployments (replacing stored AWS/GCP/Azure credentials -- this is highest-impact and lowest-disruption because the downstream pipeline operations do not change). Second, migrate highest-privilege database credentials to Vault dynamic secrets or AWS IAM database authentication, running parallel validation with both the old static and new dynamic credentials before removing the static credential. Third, implement automated rotation for remaining static secrets (legacy systems, third-party APIs without OIDC support) at a maximum 90-day rotation interval. Inventory all pipeline secrets and classify by privilege level before starting migration to identify what should move to dynamic versus what should stay static with rotation.
What is AWS IAM database authentication and how does it eliminate stored database passwords?
AWS IAM database authentication allows RDS and Aurora databases to accept authentication tokens generated from IAM credentials instead of stored database passwords. When the pipeline uses OIDC federation to assume an IAM role (no stored credential), the pipeline calls `aws rds generate-db-auth-token` using its current IAM credentials to generate a 15-minute authentication token. This token is used as the database password in the connection string. The result: the database credential chain is fully dynamic with no stored secrets anywhere -- the pipeline's IAM identity (from OIDC federation) generates the database token, which is valid for 15 minutes and then automatically expires.
Sources & references
Free resources
Critical CVE Reference Card 2025–2026
25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.
Ransomware Incident Response Playbook
Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.
Get threat intel before your inbox does.
50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.
Unsubscribe anytime. We never sell your data.

Founder & Cybersecurity Evangelist, Decryption Digest
Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.
Win a $2,495 Black Hat pass.
Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.
