Back to blog
AWSBest PracticesCloud SecurityIncident ResponseMonitoring & Logging

GuardDuty Not Enabled: Closing the Blind Spots in Your AWS Account

Disabled GuardDuty leaves AWS regions blind to credential theft and crypto mining. Learn why it matters and how to enable it everywhere with CLI, Terraform, and policy-as-code.

TL;DR

This check flags any AWS region where GuardDuty is disabled or suspended, leaving you blind to credential theft, crypto mining, and reconnaissance activity. Turn it on in every region with aws guardduty create-detector --enable and centralize findings in a delegated administrator account.

GuardDuty is one of those services that quietly earns its keep. It does not block traffic, rotate keys, or harden anything. What it does is watch. It ingests your CloudTrail logs, VPC Flow Logs, and DNS query logs, runs them through threat intelligence feeds and anomaly models, and tells you when something looks wrong. When it is switched off in a region, that region is dark. An attacker operating there has one fewer thing to worry about.

The account_guardduty check looks at every region in scope and reports any where GuardDuty is either never enabled or has been explicitly suspended. Both states mean the same thing in practice: nobody is watching.


What this check detects

Lensix queries the GuardDuty API in each region and inspects the detector status. A region passes only if an active detector exists. The check fails in two situations:

  • No detector exists in the region. GuardDuty was never turned on there.
  • A detector exists but is suspended. Someone disabled monitoring without deleting the detector, often to save cost or during an investigation that was never reverted.

Note: GuardDuty is a regional service. Enabling it in us-east-1 does nothing for eu-west-1. Each region needs its own detector, which is exactly why this check runs per region rather than per account.

The suspended state is the sneaky one. A detector ID is still present, dashboards still load, and a quick glance suggests everything is fine. But suspended detectors stop analyzing data entirely. This check treats suspended the same as missing because the security outcome is identical.


Why it matters

GuardDuty catches the kinds of attacks that are otherwise invisible until the damage is done. A few concrete examples of what goes unnoticed when a region is dark:

  • Stolen credentials in use. GuardDuty flags UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration when EC2 instance credentials suddenly start making API calls from an external IP. This is one of the most common signs of a compromised instance, and without GuardDuty you would likely learn about it from your AWS bill.
  • Crypto mining. The CryptoCurrency:EC2/BitcoinTool.B finding fires when an instance talks to a known mining pool. Attackers love unmonitored regions precisely because mining can run for weeks before anyone notices.
  • Reconnaissance. Findings like Recon:IAMUser/MaliciousIPCaller show an attacker probing your account from a known-bad source, usually a precursor to a larger attack.
  • S3 data exfiltration. With S3 protection enabled, GuardDuty detects anomalous access patterns against your buckets.

The business risk is straightforward. Attackers deliberately seek out regions that organizations forget about. A team operating mainly in us-east-1 may never look at ap-south-1, which makes it the perfect place to spin up mining instances or stage exfiltration. If GuardDuty is off there, your detection window is effectively unlimited.

Warning: GuardDuty pricing is based on the volume of CloudTrail events and VPC Flow / DNS log data it analyzes. In high-traffic accounts this can be a meaningful line item. That said, leaving regions unmonitored to save money is a false economy. A single crypto mining incident usually costs more than a year of GuardDuty.


How to fix it

Console

  1. Open the GuardDuty console and switch to the affected region using the region selector in the top right.
  2. If you see a welcome screen, click Get Started, then Enable GuardDuty.
  3. If the detector is suspended, go to Settings and click Resume GuardDuty.

AWS CLI

To enable GuardDuty in a single region, create a detector:

aws guardduty create-detector \
  --enable \
  --finding-publishing-frequency FIFTEEN_MINUTES \
  --region eu-west-1

If a detector already exists but is suspended, update it instead of creating a new one. First find the detector ID, then re-enable monitoring:

DETECTOR_ID=$(aws guardduty list-detectors \
  --region eu-west-1 \
  --query 'DetectorIds[0]' --output text)

aws guardduty update-detector \
  --detector-id "$DETECTOR_ID" \
  --enable \
  --region eu-west-1

To enable GuardDuty across every region in one pass, loop over the active region list:

for region in $(aws ec2 describe-regions \
  --query 'Regions[].RegionName' --output text); do
  echo "Enabling GuardDuty in $region"
  aws guardduty create-detector \
    --enable \
    --finding-publishing-frequency FIFTEEN_MINUTES \
    --region "$region" 2>/dev/null \
    || echo "  detector may already exist in $region"
done

Tip: Set --finding-publishing-frequency FIFTEEN_MINUTES rather than the default of six hours. Faster publishing means findings reach your SIEM or alerting pipeline while the incident is still active, not after the attacker has finished.

Terraform

For a single region, the resource is minimal:

resource "aws_guardduty_detector" "main" {
  enable                       = true
  finding_publishing_frequency = "FIFTEEN_MINUTES"

  datasources {
    s3_logs {
      enable = true
    }
  }
}

To cover all regions in Terraform, define a provider alias per region and a detector resource for each. This is verbose by hand, so most teams manage it through AWS Organizations instead, covered in the next section.


How to prevent it from happening again

Enabling GuardDuty region by region does not scale, and it leaves you exposed every time AWS launches a new region. The durable fix is to manage GuardDuty at the organization level.

Use a delegated administrator and auto-enable

From your management account, delegate GuardDuty administration to a dedicated security account:

aws guardduty enable-organization-admin-account \
  --admin-account-id 111122223333

Then, from the delegated admin account, turn on auto-enrollment so every existing and future member account gets a detector automatically:

DETECTOR_ID=$(aws guardduty list-detectors \
  --query 'DetectorIds[0]' --output text)

aws guardduty update-organization-configuration \
  --detector-id "$DETECTOR_ID" \
  --auto-enable-organization-members ALL

Note: You still need to repeat the delegated admin and auto-enable configuration in each region, because GuardDuty remains regional even under Organizations. A small Terraform module or a script that iterates over regions handles this cleanly and gives you a single place to add new regions later.

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

If you provision accounts or regions through Terraform, add a policy check that fails the pipeline when an aws_guardduty_detector is missing or has enable = false. With Open Policy Agent and Conftest against a Terraform plan:

package main

deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "aws_guardduty_detector"
  resource.change.after.enable == false
  msg := sprintf("GuardDuty detector %s must be enabled", [resource.address])
}

Run a continuous check

Policy-as-code only catches drift that flows through your pipeline. Someone with console access can still suspend a detector by hand. A continuous control like the Lensix account_guardduty check closes that gap by scanning the live state of every region on a schedule and alerting you when reality diverges from policy.


Best practices

  • Enable every region, not just the ones you use. Unused regions are where attacks hide. The cost of monitoring an idle region is near zero because there is little activity to analyze.
  • Centralize findings. Route GuardDuty findings through EventBridge to a SIEM, Security Hub, or a Slack channel. A finding nobody sees is no better than no finding at all.
  • Turn on the optional protection plans. S3 protection, EKS audit log monitoring, RDS protection, and Lambda network monitoring each cover attack surfaces the base service does not. Enable the ones that match your stack.
  • Build a response runbook. Decide in advance what happens when InstanceCredentialExfiltration fires. Automated isolation of the affected instance through EventBridge and Lambda turns detection into containment.
  • Review suppression rules periodically. Teams often suppress noisy findings and forget. Audit suppression filters so a legitimate threat is not silently hidden.

Danger: Never run delete-detector as a way to silence noise. Deleting a detector discards its configuration and stops all analysis immediately, with no record of past findings. If you genuinely need to pause monitoring, use the suspend state so it can be resumed, and set a reminder to turn it back on.

GuardDuty is cheap insurance against expensive surprises. The hard part is not enabling it, it is making sure it stays enabled everywhere, forever. Automate the rollout, gate it in your pipeline, and run a continuous check so that the day someone forgets a region or suspends a detector, you find out in minutes rather than after the bill arrives.