Back to blog
AWSBest PracticesCloud SecurityMonitoring & LoggingOperations & Compliance

CloudTrail Log Validation Disabled: Why It Matters and How to Fix It

Learn why CloudTrail log file validation matters, the tampering risks it prevents, and how to enable it with CLI, Terraform, SCPs, and policy-as-code gates.

TL;DR

This check flags any CloudTrail trail that has log file validation turned off, which means you cannot cryptographically prove your audit logs were not tampered with. Fix it by enabling validation with aws cloudtrail update-trail --name your-trail --enable-log-file-validation.

CloudTrail is the closest thing AWS has to a flight recorder. Every API call, every console action, every DeleteBucket and AttachUserPolicy ends up there. But logs are only useful in an investigation if you can trust them. If an attacker who gained access to your account can quietly delete or edit log files to cover their tracks, your audit trail becomes worthless at the exact moment you need it most.

Log file validation closes that gap. This check catches trails where it is disabled.


What this check detects

The check inspects every CloudTrail trail in your account and flags any that do not have log file validation enabled. When validation is on, CloudTrail does two things:

  • It generates a hash for every log file it delivers to S3.
  • Every hour it writes a signed digest file that lists the log files delivered in that period along with their hashes. The digest is signed with a private key owned by AWS.

With those digests in place, you can later run a verification command and AWS will tell you whether any log file was modified, deleted, or inserted after delivery. Without validation, you have no cryptographic way to detect tampering. You are simply trusting that the files in the bucket are the same ones CloudTrail wrote.

Note: Log file validation is a separate setting from S3 bucket encryption or object lock. Those protect the logs at rest and prevent deletion, but validation is what lets you prove integrity after the fact. They complement each other rather than replace each other.


Why it matters

Audit logs have one job during a security incident: tell you the truth about what happened. An attacker who lands in your account knows this, which is why log tampering and log deletion are standard parts of the playbook. The MITRE ATT&CK framework tracks this under "Indicator Removal" for good reason.

Consider a realistic chain of events:

  1. An attacker obtains credentials through a leaked access key or a compromised CI runner.
  2. They escalate privileges and start poking around your environment.
  3. Knowing CloudTrail is watching, they download the relevant log files from the S3 bucket, strip out the lines that mention their activity, and re-upload the edited files.

If validation is off, that edited file sits in the bucket looking completely legitimate. Your incident responders pull the logs weeks later, see nothing suspicious during the relevant window, and close the case. The attacker keeps their foothold.

With validation on, the same edited file no longer matches the hash recorded in the signed digest. The moment you run verification, AWS reports the file as modified. You have proof of tampering, a narrowed time window, and a strong signal that something is very wrong.

Warning: Validation alone does not prevent tampering, it only makes tampering detectable. To actually block deletion or modification, pair it with S3 Object Lock and a tightly scoped bucket policy. More on that below.

There is also a compliance angle. PCI DSS, HIPAA, SOC 2, and FedRAMP all expect audit logs to be protected against unauthorized modification. Log file validation is one of the cleanest ways to satisfy those requirements, and auditors increasingly ask for it by name.


How to fix it

Enabling validation is a low-risk, non-disruptive change. It does not alter how logs are delivered or affect any existing data, it just starts producing digest files going forward.

Using the AWS CLI

First, find which trails are affected:

aws cloudtrail describe-trails \
  --query 'trailList[?LogFileValidationEnabled==`false`].[Name,HomeRegion]' \
  --output table

Then enable validation on a specific trail:

aws cloudtrail update-trail \
  --name your-trail-name \
  --enable-log-file-validation

Confirm it took effect:

aws cloudtrail get-trail-status --name your-trail-name
aws cloudtrail describe-trails \
  --query 'trailList[?Name==`your-trail-name`].LogFileValidationEnabled'

Using the AWS Console

  1. Open the CloudTrail console and go to Trails.
  2. Select the trail you want to update.
  3. In the General details section, choose Edit.
  4. Find Log file validation and set it to Enabled.
  5. Save changes.

Using Terraform

If you manage CloudTrail through Terraform, the fix is a single argument:

resource "aws_cloudtrail" "main" {
  name                          = "org-audit-trail"
  s3_bucket_name                = aws_s3_bucket.cloudtrail.id
  enable_log_file_validation    = true
  is_multi_region_trail         = true
  include_global_service_events = true
}

Verifying log integrity later

Once validation has been running for a while, this is how you actually use it during an investigation. The command checks the digests and log files for the period you specify and reports any that fail verification:

aws cloudtrail validate-logs \
  --trail-arn arn:aws:cloudtrail:us-east-1:111122223333:trail/org-audit-trail \
  --start-time 2024-01-01T00:00:00Z

Tip: Don't wait for an incident to learn the verification workflow. Run validate-logs in a controlled exercise so your responders already know what a clean result looks like and how long it takes. A practiced team is a fast team.


Hardening beyond the basics

Validation tells you when logs were tampered with. To stop tampering from succeeding at all, lock down the destination bucket. Here is a starting point for the bucket policy that denies deletion and prevents anyone but CloudTrail from writing:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyLogDeletion",
      "Effect": "Deny",
      "Principal": "*",
      "Action": ["s3:DeleteObject", "s3:PutObject"],
      "Resource": "arn:aws:s3:::my-cloudtrail-bucket/*",
      "Condition": {
        "StringNotEquals": {
          "aws:PrincipalServiceName": "cloudtrail.amazonaws.com"
        }
      }
    }
  ]
}

For genuinely tamper-proof storage, enable S3 Object Lock in compliance mode with a retention period. Once an object is written, not even the account root can delete or overwrite it until retention expires.

Danger: S3 Object Lock in compliance mode is irreversible for the retention duration. You cannot shorten the retention period, and you cannot delete locked objects, even as root. Test it on a non-production bucket first and pick a retention period you can live with.


How to prevent it from happening again

Enabling validation once is easy. Keeping it enabled across every trail, in every account, as your org grows is the real challenge. Bake it into your guardrails.

Catch it in CI/CD with policy-as-code

If your trails live in Terraform, fail the pipeline when validation is missing. Here is a Checkov-style approach. Checkov already ships the rule CKV_AWS_36 for exactly this:

checkov -d . --check CKV_AWS_36

Or write an OPA/Conftest policy if you prefer Rego:

package terraform.cloudtrail

deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "aws_cloudtrail"
  not resource.change.after.enable_log_file_validation
  msg := sprintf("CloudTrail '%s' must have log file validation enabled", [resource.address])
}

Enforce it organization-wide with an SCP

A Service Control Policy can prevent anyone from creating or updating a trail without validation, no matter how they do it:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "RequireLogValidation",
      "Effect": "Deny",
      "Action": ["cloudtrail:CreateTrail", "cloudtrail:UpdateTrail"],
      "Resource": "*",
      "Condition": {
        "Bool": {
          "cloudtrail:LogFileValidationEnabled": "false"
        }
      }
    }
  ]
}

Tip: If you run AWS Control Tower or deploy a central organization trail, validation is on by default and managed for you. A single org-level trail with delegated administration is far easier to keep consistent than per-account trails that drift over time.

Detect drift continuously

Guardrails catch new mistakes. Continuous monitoring catches the trail someone disabled manually during a 2am debugging session. AWS Config has a managed rule, cloud-trail-log-file-validation-enabled, that flags non-compliant trails. Lensix runs this check (account_cloudtraillogvalidation) across your accounts automatically, so you get a single view of every trail that slips out of compliance without wiring up Config rules yourself.


Best practices

  • Enable validation on every trail, no exceptions. There is no meaningful cost or performance reason to leave it off.
  • Use a single multi-region organization trail rather than scattered per-account trails. Fewer trails means fewer things to misconfigure.
  • Store logs in a dedicated, locked-down account. The bucket should live in a separate security or log-archive account that workload teams cannot touch.
  • Combine validation with Object Lock and a deny-delete bucket policy so logs are both tamper-proof and tamper-evident.
  • Practice the verification workflow. Run validate-logs during tabletop exercises so it is muscle memory, not a manual page you read during a crisis.
  • Alert on trail changes. Create an EventBridge rule on UpdateTrail and StopLogging events so any attempt to weaken logging pages someone immediately.

Log file validation is one of those settings that costs nothing, takes seconds to enable, and quietly becomes the most valuable feature you own the day you have to investigate a breach. Turn it on everywhere, lock down the bucket, and gate it in your pipelines so it never slips off again.