Skip to main content
MEDIUMECRCost Optimization

ECR Lifecycle Policy Missing

ecr-lifecycle-policy-missing

What this rule checks

Detects ECR repositories without a lifecycle policy to clean up old images.

How to fix it

  1. 1Define a LifecyclePolicy to expire untagged or excess image versions
FlaggedThe repository has no LifecyclePolicy, so old and untagged images accumulate indefinitely and drive up storage cost. The check flags any ECR repository without a lifecycle policy.
import { App, Stack } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ecr from 'aws-cdk-lib/aws-ecr';

// FLAGGED: repository with no lifecycle policy.
new ecr.CfnRepository(this, 'Repo', {
  repositoryName: 'app',
  imageTagMutability: 'IMMUTABLE',
});
FixedAdding a LifecyclePolicy with a LifecyclePolicyText clears the finding. Untagged images are now expired automatically after 14 days, keeping storage bounded.
import { App, Stack } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ecr from 'aws-cdk-lib/aws-ecr';

// FIXED: lifecycle policy expires untagged images after 14 days.
new ecr.CfnRepository(this, 'Repo', {
  repositoryName: 'app',
  imageTagMutability: 'IMMUTABLE',
  lifecyclePolicy: {
    lifecyclePolicyText: JSON.stringify({
      rules: [
        {
          rulePriority: 1,
          selection: { tagStatus: 'untagged', countType: 'sinceImagePushed', countUnit: 'days', countNumber: 14 },
          action: { type: 'expire' },
        },
      ],
    }),
  },
});

CDK Insights pinpoints the exact file and line in your CDK source for every finding, so you can jump straight to the fix.

Affected resource types

AWS::ECR::Repository

AWS documentation

Read the AWS guidance

Intentional? Suppress this finding

Sometimes a flag is deliberate — a genuinely public endpoint, say. You can dismiss ecr-lifecycle-policy-missing and the reason is kept in the report, not silently hidden.

In .cdk-insights.json:

{
  "ignoreRules": [
    { "id": "ecr-lifecycle-policy-missing", "reason": "Why this is intentional" }
  ]
}

Or inline in your CDK code:

Validations.of(scope).acknowledge({
  id: 'cdk-insights::ecr-lifecycle-policy-missing',
  reason: 'Why this is intentional',
});

Use the rule ID ecr-lifecycle-policy-missing shown above — not the CDK-* ID from SARIF / GitHub code scanning. To dismiss every finding on one construct instead, use ignorePaths. Suppression docs →

Catch this in your stack

$ npx cdk-insights scan

CDK Insights runs this and 118+ other rules locally against your synthesised CDK app — free, no account, your code never leaves your machine.

More ECR rules