Back to blog
AWSBest PracticesCloud SecurityOperations & ComplianceServerless

CodeBuild Uses Public Source Provider: Securing Your Build Sources

Learn why AWS CodeBuild projects sourcing from GitHub or Bitbucket widen your supply chain attack surface, plus step-by-step remediation and prevention.

TL;DR

This check flags CodeBuild projects that pull source from public providers like GitHub or Bitbucket instead of an internal source such as CodeCommit or S3. Public sources widen your supply chain attack surface and depend on third-party availability and credentials. Migrate sensitive builds to an internal mirror or lock down the connection with scoped tokens and webhook filters.

AWS CodeBuild is happy to build from wherever you point it: a GitHub repo, a Bitbucket repo, an S3 bucket, or AWS CodeCommit. That flexibility is convenient during early development, but it quietly couples your build pipeline to infrastructure you do not control. When a CodeBuild project sources from GitHub or Bitbucket, your build process now trusts a third party for code integrity, availability, and credential handling.

This Lensix check, cicd_codebuildsource, looks at the source configuration of each CodeBuild project and flags any project whose source type is a public provider rather than an internal AWS source.


What this check detects

CodeBuild projects define a primary source with a type field. The check inspects that value and raises a finding when it is set to one of the public providers:

  • GITHUB
  • GITHUB_ENTERPRISE
  • BITBUCKET

Internal sources that pass the check include CODECOMMIT, S3, and NO_SOURCE (used for buildspec-only or container-driven workflows).

Note: This is a posture check, not an accusation that something is broken. Plenty of teams build from GitHub deliberately. The point is to make that choice visible and ensure it is intentional, scoped, and reviewed rather than left over from a quick proof of concept.


Why it matters

The build stage is one of the most sensitive parts of any pipeline. CodeBuild runs with an IAM service role that frequently has permission to push images to ECR, deploy with CloudFormation, read secrets, and write to S3. Whatever feeds that build has an implicit line into your AWS account.

Supply chain exposure

When source lives on a public provider, an attacker who compromises that provider account, a maintainer's credentials, or a personal access token can inject code that runs inside your build environment. Modified build scripts can exfiltrate the service role's temporary credentials, plant backdoors in artifacts, or tamper with container images before they ship.

Warning: A CodeBuild project triggered by a pull request webhook will, by default, build code from forks and branches that have not been reviewed. Without a webhook filter, an outside contributor can run arbitrary commands in your build environment simply by opening a PR.

Credential sprawl

GitHub and Bitbucket integrations rely on OAuth tokens or personal access tokens stored in CodeBuild or AWS Secrets Manager. These tokens often carry broad repo scopes, do not rotate automatically, and outlive the engineer who created them. Each one is a long-lived credential to a system outside your blast radius controls.

Availability and compliance

If GitHub has an outage, your deployments stop. For regulated workloads, an external dependency in the build chain can complicate audit boundaries because the code provenance now sits outside your account and outside your logging.


How to fix it

You have two broad paths: move the source into an AWS-internal provider, or keep the public provider but tighten how CodeBuild connects to it. Pick based on how sensitive the workload is.

Option 1: Mirror the repository into CodeCommit

For high-trust pipelines, an internal mirror gives you a source that lives inside your account boundary. Create a CodeCommit repo and push your code into it.

aws codecommit create-repository \
  --repository-name my-service \
  --repository-description "Internal mirror of my-service"

# Mirror the existing GitHub repo
git clone --mirror https://github.com/my-org/my-service.git
cd my-service.git
git remote add codecommit \
  https://git-codecommit.us-east-1.amazonaws.com/v1/repos/my-service
git push codecommit --mirror

Then update the CodeBuild project to source from CodeCommit:

aws codebuild update-project \
  --name my-service-build \
  --source type=CODECOMMIT,location=https://git-codecommit.us-east-1.amazonaws.com/v1/repos/my-service

Tip: Keep GitHub as the developer-facing remote and run a scheduled Lambda or EventBridge job that mirrors commits into CodeCommit. Engineers keep their familiar workflow while builds always pull from inside your account.

Option 2: Use S3 as the build source

For pipelines that package source into a versioned artifact, S3 is a clean internal source. An upstream stage zips the code and drops it into a bucket that CodeBuild reads.

aws codebuild update-project \
  --name my-service-build \
  --source type=S3,location=my-build-sources/my-service/source.zip

Option 3: Keep the public provider but harden it

If GitHub has to stay, reduce the risk. Use a GitHub App or fine-grained token scoped to a single repo, store it in Secrets Manager, and add a webhook filter so only trusted events trigger builds.

Here is a Terraform example that restricts triggers to pushes on main and pull requests from the same repository, not forks:

resource "aws_codebuild_webhook" "main" {
  project_name = aws_codebuild_project.my_service.name

  filter_group {
    filter {
      type    = "EVENT"
      pattern = "PUSH"
    }
    filter {
      type    = "HEAD_REF"
      pattern = "^refs/heads/main$"
    }
  }

  filter_group {
    filter {
      type    = "EVENT"
      pattern = "PULL_REQUEST_CREATED,PULL_REQUEST_UPDATED"
    }
    filter {
      type    = "ACTOR_ACCOUNT_ID"
      pattern = "^(11111111|22222222)$"
    }
  }
}

Danger: Before you change a project's source type in production, confirm the buildspec path, environment variables, and artifact mappings still line up with the new location. Switching from GitHub to S3 changes the working directory layout, and a mismatched buildspec can deploy a broken or empty artifact straight to production.


How to prevent it from happening again

Manual remediation does not stick. Bake the policy into the places where CodeBuild projects get created.

Catch it in Terraform with a policy check

If you provision CodeBuild with Terraform, an OPA or Conftest rule can block plans that introduce a public source for tagged-sensitive projects.

# policy/codebuild.rego
package main

deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "aws_codebuild_project"
  source := resource.change.after.source[_]
  source.type == "GITHUB"
  not allowed_public(resource)
  msg := sprintf("CodeBuild project '%s' uses a public GitHub source", [resource.address])
}

allowed_public(resource) {
  resource.change.after.tags["allow-public-source"] == "true"
}

Wire it into your pipeline so a plan with an unapproved public source fails the build:

terraform plan -out=plan.tfplan
terraform show -json plan.tfplan > plan.json
conftest test plan.json --policy policy/

Enforce with an SCP guardrail

For accounts that should never source from public providers, you can deny project creation that does not match approved patterns through preventive controls and tagging requirements, then audit continuously rather than relying on a one-time scan.

Tip: Run the Lensix cicd_codebuildsource check on a schedule rather than once. New projects appear constantly, and a continuous scan turns this from a cleanup task into a standing guardrail that surfaces drift the day it happens.


Best practices

  • Treat the build role as a high-value target. Scope its IAM permissions tightly so a compromised build cannot reach beyond what it strictly needs.
  • Prefer internal sources for anything that deploys. Build-and-deploy pipelines deserve the strongest provenance. Reserve public-source builds for low-risk tasks like docs or linting.
  • Always set a webhook filter. Never let unfiltered pull request events trigger builds on a public-source project.
  • Use short-lived, fine-grained tokens. Replace classic personal access tokens with GitHub Apps or fine-grained tokens scoped to one repo, and rotate them on a schedule.
  • Log and monitor build activity. Send CodeBuild logs to CloudWatch and watch for unexpected outbound network calls during builds, which can signal credential exfiltration attempts.
  • Pin your build environment. Use specific image versions and verified buildspec files so the build itself is reproducible and tamper-evident.

Public source providers are not inherently wrong, but they move part of your trust boundary outside AWS. The goal of this check is simple: make every public-source build a deliberate, reviewed decision rather than a default that nobody remembers choosing.