Skip to main content

CodeBuild Project Invoked in Last 90 Days

Overview

This check identifies AWS CodeBuild projects that have not been used (invoked) in the past 90 days, or have never been built at all. Unused projects represent "stale infrastructure" that can create security and operational risks.

Risk

If this check fails, you have dormant CodeBuild projects that may pose security risks:

Potential consequences:

  • Unused IAM roles attached to the project retain permissions that could be exploited
  • Webhooks or source credentials may remain active and vulnerable to abuse
  • Environment variables may contain secrets that become forgotten and unrotated
  • Stale buildspec configurations could have outdated or insecure dependencies
  • Unnecessary costs from associated resources (like reserved capacity)

Severity: Medium

Remediation Steps

Prerequisites

  • Access to the AWS Console with permissions to view and manage CodeBuild projects, or
  • AWS CLI installed and configured with appropriate credentials
Required IAM permissions

Your IAM user or role needs the following permissions:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"codebuild:ListProjects",
"codebuild:BatchGetProjects",
"codebuild:ListBuildsForProject",
"codebuild:StartBuild",
"codebuild:DeleteProject"
],
"Resource": "*"
}
]
}

For production, scope the Resource to specific project ARNs.

AWS Console Method

You have two options depending on whether the project is still needed:

Option A: If the project is still needed (invoke a build)

  1. Open the AWS CodeBuild console
  2. Find the project flagged in the Prowler finding
  3. Select the project by clicking on its name
  4. Click Start build (orange button in the top right)
  5. Review the build configuration and click Start build again to confirm
  6. Wait for the build to complete (this updates the "last invoked" timestamp)

Option B: If the project is no longer needed (delete it)

  1. Open the AWS CodeBuild console
  2. Find the project flagged in the Prowler finding
  3. Select the checkbox next to the project name
  4. Click Delete in the top menu
  5. Type the project name to confirm deletion
  6. Click Delete

Warning: Deleting a project is permanent. The build history is retained, but the project configuration is lost. Make sure you have the buildspec and configuration documented elsewhere if you might need it later.

AWS CLI method

Check when a project was last used:

# List recent builds for a project
aws codebuild list-builds-for-project \
--project-name <your-project-name> \
--sort-order DESCENDING \
--region us-east-1

# Get detailed project info including last modified date
aws codebuild batch-get-projects \
--names <your-project-name> \
--region us-east-1 \
--query 'projects[0].{name:name,created:created,lastModified:lastModified}'

Option A: Start a build to update the last invoked timestamp:

aws codebuild start-build \
--project-name <your-project-name> \
--region us-east-1

Option B: Delete an unused project:

aws codebuild delete-project \
--name <your-project-name> \
--region us-east-1

Script to find all inactive projects:

#!/bin/bash
REGION="us-east-1"
DAYS_THRESHOLD=90
CUTOFF_DATE=$(date -d "-${DAYS_THRESHOLD} days" +%s 2>/dev/null || date -v-${DAYS_THRESHOLD}d +%s)

echo "Checking CodeBuild projects not invoked in the last ${DAYS_THRESHOLD} days..."
echo "Cutoff date: $(date -d "@${CUTOFF_DATE}" 2>/dev/null || date -r ${CUTOFF_DATE})"
echo "---"

# Get all projects
PROJECTS=$(aws codebuild list-projects --region "$REGION" --output text --query 'projects[]')

for PROJECT in $PROJECTS; do
# Get the most recent build
LATEST_BUILD=$(aws codebuild list-builds-for-project \
--project-name "$PROJECT" \
--sort-order DESCENDING \
--max-items 1 \
--region "$REGION" \
--query 'ids[0]' \
--output text 2>/dev/null)

if [ "$LATEST_BUILD" == "None" ] || [ -z "$LATEST_BUILD" ]; then
echo "INACTIVE: $PROJECT (never built)"
else
# Get build details to check timestamp
BUILD_TIME=$(aws codebuild batch-get-builds \
--ids "$LATEST_BUILD" \
--region "$REGION" \
--query 'builds[0].startTime' \
--output text 2>/dev/null)

if [ -n "$BUILD_TIME" ]; then
BUILD_EPOCH=$(date -d "$BUILD_TIME" +%s 2>/dev/null || date -jf "%Y-%m-%dT%H:%M:%S" "$BUILD_TIME" +%s 2>/dev/null)
if [ "$BUILD_EPOCH" -lt "$CUTOFF_DATE" ]; then
echo "INACTIVE: $PROJECT (last build: $BUILD_TIME)"
fi
fi
fi
done
CloudFormation

CloudFormation cannot directly "invoke" a build or manage build history. However, you can use CloudFormation to define your CodeBuild projects with proper lifecycle management.

Best practice: Include a description or tag indicating when the project was created and its intended use:

AWSTemplateFormatVersion: '2010-09-09'
Description: CodeBuild project with lifecycle tracking

Parameters:
ProjectName:
Type: String
Description: Name of the CodeBuild project

Resources:
CodeBuildProject:
Type: AWS::CodeBuild::Project
Properties:
Name: !Ref ProjectName
Description: "Created via CloudFormation - review quarterly for continued need"
ServiceRole: !GetAtt CodeBuildRole.Arn
Source:
Type: NO_SOURCE
BuildSpec: |
version: 0.2
phases:
build:
commands:
- echo "Build invoked at $(date)"
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0
Artifacts:
Type: NO_ARTIFACTS
Tags:
- Key: "CreatedDate"
Value: !Sub "${AWS::StackName}-creation"
- Key: "Owner"
Value: "<your-team-name>"
- Key: "ReviewDate"
Value: "Quarterly"

CodeBuildRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AWSCodeBuildDeveloperAccess

To delete an unused project, delete the CloudFormation stack that created it.

Terraform

Similar to CloudFormation, Terraform cannot directly invoke builds. Use tags to track project lifecycle:

variable "project_name" {
description = "Name of the CodeBuild project"
type = string
}

variable "owner_team" {
description = "Team responsible for this project"
type = string
}

resource "aws_codebuild_project" "main" {
name = var.project_name
description = "Managed by Terraform - review quarterly for continued need"
service_role = aws_iam_role.codebuild.arn

source {
type = "NO_SOURCE"
buildspec = <<-BUILDSPEC
version: 0.2
phases:
build:
commands:
- echo "Build invoked at $(date)"
BUILDSPEC
}

environment {
type = "LINUX_CONTAINER"
compute_type = "BUILD_GENERAL1_SMALL"
image = "aws/codebuild/amazonlinux2-x86_64-standard:5.0"
}

artifacts {
type = "NO_ARTIFACTS"
}

tags = {
Owner = var.owner_team
ManagedBy = "Terraform"
ReviewDate = "Quarterly"
}
}

resource "aws_iam_role" "codebuild" {
name = "${var.project_name}-codebuild-role"

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "codebuild.amazonaws.com"
}
Action = "sts:AssumeRole"
}
]
})
}

resource "aws_iam_role_policy_attachment" "codebuild" {
role = aws_iam_role.codebuild.name
policy_arn = "arn:aws:iam::aws:policy/AWSCodeBuildDeveloperAccess"
}

To delete an unused project, remove it from your Terraform configuration and run terraform apply.

Verification

After remediation, verify the fix was successful:

  1. If you ran a build: In the CodeBuild console, check that the project now shows a recent "Last build status" with today's date
  2. If you deleted the project: Confirm the project no longer appears in the CodeBuild console project list
  3. Re-run the Prowler check to confirm:
    prowler aws --check codebuild_project_older_90_days -r us-east-1
CLI verification

Verify a project has recent builds:

aws codebuild list-builds-for-project \
--project-name <your-project-name> \
--sort-order DESCENDING \
--max-items 1 \
--region us-east-1

The output should show a build ID from today.

Verify a project was deleted:

aws codebuild batch-get-projects \
--names <your-project-name> \
--region us-east-1

If deleted, the project will appear in the projectsNotFound array.

Additional Resources

Notes

  • Build history is preserved: When you delete a CodeBuild project, the build logs and history are retained in CloudWatch Logs and S3 (if configured). Only the project definition is removed.

  • Consider archiving instead: If you are unsure whether you need the project, export its buildspec and configuration before deleting. You can recreate it later if needed.

  • Review associated resources: Before deleting a project, check for:

    • Webhooks connected to source repositories (GitHub, Bitbucket, etc.)
    • IAM roles that may be shared with other projects
    • S3 buckets used for artifacts or cache
    • CloudWatch log groups with build logs
  • Implement regular reviews: Set up a quarterly review process to identify and clean up unused CodeBuild projects. Consider using AWS Config rules or custom scripts to automate detection.

  • Least privilege: If you decide to keep a project, review its IAM role permissions and remove any that are no longer needed.