Back to Checks
aws

CloudWatch log group has a retention policy of at least the configured minimum days or never expires

cloudwatch_log_group_retention_policy_specific_days_enabled
Service: cloudwatchSeverity: medium
OfficialBuilt-inVerified
Categories:loggingforensics-ready
Resource Type:AwsLogsLogGroup

CloudWatch Log Groups are assessed for a retention period at or above the configured threshold (e.g., 365 days) or for being set to never expire. Log groups with shorter retention are identified.

Risk

Short log retention erodes audit evidence. Adversaries can wait out the window, creating gaps in detection, forensics, and compliance reporting. This degrades the availability of historical logs and the integrity of incident timelines.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks cloudwatch_log_group_retention_policy_specific_days_enabled

Recommendation

Define a minimum retention baseline (e.g., >=365 days) aligned to legal and investigative needs. Apply it consistently with documented exceptions. Automate enforcement, monitor changes, and restrict who can modify retention under least privilege and defense in depth.

Remediation

CLI

aws logs put-retention-policy --log-group-name <LOG_GROUP_NAME> --retention-in-days <DAYS>

Terraform

# Set retention on a CloudWatch Log Group
resource "aws_cloudwatch_log_group" "<example_resource_name>" {
  name              = "<example_resource_name>"
  retention_in_days = <DAYS> # Critical: set to at least the required minimum to pass the check
}

NativeIaC

# CloudFormation: set retention on a CloudWatch Log Group
Resources:
  <example_resource_name>:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: "<example_resource_name>"
      RetentionInDays: <DAYS>  # Critical: sets log retention to the required minimum to pass the check

Other

1In the AWS Console, go to CloudWatch > Log groups
2Select the target log group
3In the Expire events after/Retention column, click the current value
4Choose a retention value >= <DAYS> or select Never expire
5Click Save

Check Code

from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.cloudwatch.logs_client import logs_client


class cloudwatch_log_group_retention_policy_specific_days_enabled(Check):
    def execute(self):
        findings = []

        # log_group_retention_days, default: 365 days
        specific_retention_days = logs_client.audit_config.get(
            "log_group_retention_days", 365
        )
        if logs_client.log_groups:
            for log_group in logs_client.log_groups.values():
                report = Check_Report_AWS(metadata=self.metadata(), resource=log_group)
                if (
                    log_group.never_expire is False
                    and log_group.retention_days < specific_retention_days
                ):
                    report.status = "FAIL"
                    report.status_extended = f"Log Group {log_group.name} has less than {specific_retention_days} days retention period ({log_group.retention_days} days)."
                else:
                    report.status = "PASS"
                    if log_group.never_expire is True:
                        report.status_extended = f"Log Group {log_group.name} comply with {specific_retention_days} days retention period since it never expires."
                    else:
                        report.status_extended = f"Log Group {log_group.name} comply with {specific_retention_days} days retention period since it has {log_group.retention_days} days."
                findings.append(report)
        return findings