Mitigating CI/CD Credential Exfiltration via OIDC Federation in AWS

Alexander Hose on August 14, 20266 min. read

Abstract

Continuous Integration and Continuous Delivery (CI/CD) pipelines represent a high-value target in cloud infrastructure attacks. Empirical analysis of cloud security incidents indicates that long-lived AWS Identity and Access Management (IAM) access keys provisioned for automated pipelines are frequently exposed through log aggregation, untrusted dependency execution, or repository metadata leaks.

This article evaluates the architectural transition from static IAM credentials to OpenID Connect (OIDC) federation with AWS Security Token Service (STS). We analyze the cryptographic token exchange protocol, dissect the role of subject (sub) claim constraints in multi-tenant environments, and reference baseline implementation rules codified in AWS-IAM-005: Enforce OIDC for VCS CI/CD Connections to AWS.

bash
+---------------------------------------------------------------------------------------------------+
|                         CI/CD AUTHENTICATION ARCHITECTURE: STATIC VS. FEDERATED                   |
+---------------------------------------------------------------------------------------------------+
|                                                                                                   |
|  1. STATIC CREDENTIAL PATTERN (HIGH RISK)                                                         |
|  [VCS Secret Store] ----(Permanent Key)----> [CI Runner] ----(Direct AWS API)----> [AWS Services] |
|  * Exposure Window: Indefinite                                                                    |
|  * Key Attributes: Stored at rest, broad scope, manual rotation cycles                            |
|                                                                                                   |
|  2. OIDC FEDERATION PATTERN (ZERO STANDING PRIVILEGE)                                             |
|  [CI Runner] ----(1. Request JWT)--------> [VCS OIDC Provider (GitHub/GitLab)]                    |
|  [CI Runner] <---(2. Signed OIDC JWT)----  [VCS OIDC Provider]                                    |
|  [CI Runner] ----(3. STS AssumeRoleWithWebIdentity + JWT)--> [AWS STS Endpoint]                   |
|  [CI Runner] <---(4. 15-Minute Temporary Credentials)------- [AWS STS Endpoint]                   |
|  [CI Runner] ----(5. Scoped API Call)----------------------> [AWS Target Services]                |
|                                                                                                   |
+---------------------------------------------------------------------------------------------------+

1. Threat Model: Static CI/CD Credential Exposure Vectors

Static IAM user credentials (AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY) stored within Version Control Systems present four primary attack vectors:

1.1 Environment Reflection and Log Leakage

Build steps executing debugging scripts, test frameworks, or misconfigured container entrypoints frequently dump process environments to standard output. Once emitted to console logs, credentials are systematically indexed by centralized log forwarders and visible to read-only repository contributors.

1.2 Fork-Based Pull Request Execution

In public or multi-team internal repositories, automated workflows triggered by pull_request events from forks can execute untrusted code in the context of the base repository. Without strict runner isolation, malicious pull requests can extract secrets from memory or environment variables.

1.3 Upstream Supply Chain Ingestion

Build steps dynamically pull thousands of third-party package dependencies (npm, PyPI, Go modules). A compromised dependency executing in pre- or post-install hooks gains direct access to process memory, enabling silent exfiltration of all environment variables to external Command & Control (C2) endpoints.

1.4 Persistent Post-Decommission Access

Static credentials lack automatic invalidation mechanisms. When a repository or service is decommissioned, associated IAM keys often remain active, providing unmonitored backdoors into the cloud environment.


2. Technical Protocol: OIDC Identity Federation via AWS STS

OpenID Connect (OIDC) eliminates stored credentials by establishing an asymmetric cryptographic trust between the Version Control System and AWS STS.

bash
+---------------+              +--------------------+              +-------------------+
|   CI Runner   |              |  VCS OIDC Provider |              |      AWS STS      |
+---------------+              +--------------------+              +-------------------+
        |                                |                                   |
        | 1. Request Job Token           |                                   |
        |------------------------------->|                                   |
        |                                |                                   |
        | 2. Issue Signed JWT (RS256)    |                                   |
        |<-------------------------------|                                   |
        |                                                                    |
        | 3. Call AssumeRoleWithWebIdentity(RoleArn, JWT)                    |
        |------------------------------------------------------------------->|
        |                                                                    |
        |                                | 4. Validate Discovery (.well-known)
        |                                |    and Verify JWT Signature via JWKS
        |                                |<----------------------------------|
        |                                |---------------------------------->|
        |                                                                    |
        |                                | 5. Evaluate IAM Role Trust Policy |
        |                                |    (Check 'aud' and 'sub' claims) |
        |                                                                    |
        | 6. Return Credentials (AccessKey, SecretKey, SessionToken)         |
        |<-------------------------------------------------------------------|

Protocol Execution Stages:

  1. Token Generation: Upon job initialization, the VCS runner requests a cryptographically signed JSON Web Token (JWT) from its internal identity service (token.actions.githubusercontent.com or gitlab.com).
  2. Signature Verification: AWS STS fetches the OpenID Connect discovery document (/.well-known/openid-configuration) and JSON Web Key Set (JWKS) from the VCS provider to verify the token's RS256 signature.
  3. Condition Evaluation: STS parses the claims payload and validates them against the target IAM role's trust policy conditions.
  4. Credential Issuance: Upon successful evaluation, STS generates temporary, least-privilege credentials valid for a configurable duration (900 to 3,600 seconds).

3. Vulnerability Analysis: The Subject (sub) Claim Boundary

The most critical architectural failure mode in OIDC deployment involves incomplete trust policy condition constraints.

The Audience (aud) vs. Subject (sub) Distinction

  • aud (Audience): Identifies the intended recipient of the token (typically sts.amazonaws.com). Validating aud ensures only that the token was minted for AWS, but does not identify the calling repository.
  • sub (Subject): Uniquely identifies the execution context within the identity provider (organization, repository, branch, environment, or commit hash).
json
// VULNERABLE CONFIGURATION: Any GitHub repository can assume this role
{
  "Effect": "Allow",
  "Principal": {
    "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
  },
  "Action": "sts:AssumeRoleWithWebIdentity",
  "Condition": {
    "StringEquals": {
      "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
    }
  }
}
json
// HARDENED CONFIGURATION: Restricted to specific repository, branch, and environment
{
  "Effect": "Allow",
  "Principal": {
    "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
  },
  "Action": "sts:AssumeRoleWithWebIdentity",
  "Condition": {
    "StringEquals": {
      "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
    },
    "StringLike": {
      "token.actions.githubusercontent.com:sub": [
        "repo:enterprise-org/production-service:ref:refs/heads/main",
        "repo:enterprise-org/production-service:environment:production"
      ]
    }
  }
}

Summary & Technical Reference

Transitioning automated deployment pipelines to OIDC web identity federation eliminates the root cause of credential leakage in cloud automation workflows. By binding AWS STS assume-role operations to cryptographically verified subject claims, organizations achieve zero standing privilege across their CI/CD lifecycle.

To review complete Terraform modules, automated AWS CLI audit scripts, and Service Control Policy (SCP) enforcement templates, refer to the full technical control:

šŸ‘‰ AWS-IAM-005: Enforce OIDC for VCS CI/CD Connections to AWS

We value your privacy

We use analytics cookies to understand how visitors interact with our site and to improve the user experience. You can choose to accept or decline these cookies.