# Operating GuardDuty to Suppress False Positives and Noise: The Correct Use of Suppression Rules, Trusted IP Lists, and Threat Lists

> A tuning implementation guide to suppressing Amazon GuardDuty's noise and false positives at production quality. We use the 3 tools — Suppression Rules (auto-archiving known noise), trusted IP/entity lists (not emitting findings from known legitimate sources), and threat lists (emitting findings from known malicious sources) — by a symptom→correct-tool mapping. A suppressed finding doesn't reach Security Hub/S3/Detective/EventBridge, nor does it become correlation material for Extended Threat Detection — we explain, in real Terraform/CLI code, the trap where too-broad suppression makes a Critical attack sequence wholly invisible, and the reactive, minimal-scope, IaC-centric operational rules.

- Published: 2026-06-27
- Author: 友田 陽大
- Tags: セキュリティ, AWS, GuardDuty, 運用設計, Terraform
- URL: https://tomodahinata.com/en/blog/aws-guardduty-suppression-rules-trusted-ip-threat-lists-tuning-guide
- Category: Amazon GuardDuty in production
- Pillar guide: https://tomodahinata.com/en/blog/aws-guardduty-threat-detection-multi-account-terraform-eventbridge-guide

## Key points

- Noise is the enemy of response, but wrong tuning 'hides the attack along with it.' 3 tools, 3 roles — Suppression Rules (auto-archive known-noise finding patterns), trusted IP/entity lists (don't emit findings from known legitimate sources), threat lists (emit findings from known malicious sources)
- A suppressed finding isn't sent to Security Hub CSPM, S3, Detective, or EventBridge, and doesn't trigger a Malware Protection for EC2 scan. But the finding itself is generated and stored for 90 days as archived (referenceable via service.archived = true)
- The biggest trap: Extended Threat Detection doesn't use archived findings (including those auto-archived by suppression) as attack-sequence correlation material. Broad suppression that erases a whole type makes a Critical multi-stage attack invisible. Suppress reactively, narrowed to a specific behavior
- List limits: 1 trusted entity + 1 trusted IP list, max 6 threat lists (per account × region). IPv4 only, public addresses/domains only, trusted takes priority over threat. Re-activation required after editing the S3 file (about 15 min, up to 40 min). Applies to all plans except Runtime Monitoring
- Cost misconception: a Suppression Rule does not lower GuardDuty cost (billing is by analysis volume, not the number of findings). A trusted list reduces findings but the data is still analyzed. Tuning is not a cost-optimization tool

---

"We put in GuardDuty and the alerts wouldn't stop ringing. So we muted them all" — it's a line I hear fairly often when consulted on AWS security operations.

And this is usually **a dangerous move.** A vulnerability scanner's periodic port scan, SSH brute force against a bastion, communication via an on-prem GW — legitimate operations do mass-produce findings, and the dashboard fills with red. But do "erase the whole type because it's noisy," and **the Critical attack sequence that finding was supposed to bundle gets erased along with it.** Noise is the enemy of response, but **wrong tuning hides the attack itself** — this is the theme running through this article.

This article is a **spoke** that digs Chapter 7 "Suppressing false positives and noise" of the [GuardDuty production-design pillar article](/blog/aws-guardduty-threat-detection-multi-account-terraform-eventbridge-guide) to a depth that can stand on its own. GuardDuty tuning has 3 tools, and each has **a completely different role.** Get this usage wrong and the worst happens: noise doesn't decrease, cost doesn't decrease, and only the detection capability gets shaved. Conversely, use them correctly and you get an operation where **"only the findings that should be responded to remain, and the attack context is not lost."** As subject matter, I'll mix in the viewpoint of my experience cross-implementing IAM, observability, and DR on a [serverless payment platform](/case-studies/payment-platform-reliability) on multi-account AWS — where, **because it handles actual money, carbon credits, and local currencies, "missing a real breach buried in noise" was not permitted.**

> **The rules of this article**: the specs, limits, and behavior of Suppression Rules, trusted lists, and threat lists are based on the **AWS official documentation (as of June 2026).** Since list caps, supported formats, and scope of application are revised, always check the latest official information before going to production. And one more iron rule — **tuning must never be tilted in the direction of "making real attacks invisible."** Suppress reactively (only what you've confirmed to be a repeated false positive), with minimal scope, and via IaC rather than a console click (reviewable, reproducible).

---

## 0. Mental model: 3 tools, 3 jobs

Before starting the design, let me fix in one line that the 3 tools **each solve a different problem.** Confusing them is the cause of nearly every accident.

> **GuardDuty has 3 tuning tools. A Suppression Rule erases "known harmless finding patterns," a trusted list doesn't emit findings from "known legitimate sources," and a threat list emits findings from "known malicious sources."**

| Tool | Problem it solves | What it affects | Official behavior |
| --- | --- | --- | --- |
| **Suppression Rule** | **Known finding patterns** that legitimate operations generate are noisy | **Auto-archives** new findings matching a finding **type + narrowing attributes** | Archives new findings matching the filter condition. Doesn't send to Security Hub/S3/Detective/EventBridge |
| **Trusted IP / entity list** | Findings are emitted from communication from **known legitimate sources** (your fixed IPs, monitoring SaaS) | **Doesn't generate findings** about activity from the listed IPs/domains | Doesn't generate findings for entries on the trusted list |
| **Threat list** | You want to detect **sources you've judged "malicious" yourself** | **Generates findings** on activity to the listed IPs/domains/hashes | Generates findings on activity involving entries on the threat list |

Let me make the difference of the 3 even clearer.

1. **A Suppression Rule looks at "the finding side."** It's a downstream filter saying "if a finding of **this type comes out under this condition**, it's harmless, so archive it." For example, "if `Recon:EC2/Portscan` comes from your vulnerability scanner's AMI, it's harmless." GuardDuty **generates the finding first, then** archives it (which is why, as described later, the analysis cost doesn't change).
2. **A trusted list looks at "the source side."** It's an upstream filter saying "this IP/domain is trustworthy, so **don't generate** a finding in the first place." For example, "don't make communication from your fixed egress IP into a finding."
3. **A threat list is the flip side of a trusted list.** "This IP/domain/hash is malicious, so **generate** a finding if it's involved." It's the tool for bringing your own threat intelligence into GuardDuty's detection.

Grasp these 3 points and tuning organizes into the branch: **"① Is the noise's identity a 'finding pattern' or a 'source'? → ② A pattern → suppress; a source → trusted list → ③ Want to add your own detection? → threat list."** And the constraint running through the whole — **whichever you use, you must not make real attacks (especially the multi-stage attacks Extended Threat Detection bundles) invisible.** Let me dig in, in order.

---

## 1. Deep dive on Suppression Rules: what happens and what doesn't

This is the most misunderstood tool. If you think "suppression = erase the finding," you **end up thinking you've erased even what isn't erased** — that's the entrance to an accident.

### 1.1 A suppression rule's true nature is "a filter with action = ARCHIVE"

The official definition is simple. A Suppression Rule is **a rule that auto-archives matching new findings by a combination of filter attributes and values (criteria).** Use GuardDuty's filter feature itself with `action` set to `ARCHIVE`, and it becomes a suppression rule (in Terraform's `aws_guardduty_filter`, `action = "ARCHIVE"`).

The "2-condition pattern" the official explicitly states is the basic form of the design. Place **a finding type in the first condition, and a scope-narrowing attribute** (AMI, tag, IP, etc.) in the second condition. This isn't coincidental — all the official's recommended examples take this form.

```bash
# 抑制ルールは「action=ARCHIVE のフィルタ」。CLI/API では create-filter で作る。
# 公式の2条件パターン: ①finding 型 + ②スコープを絞る属性。
# 例: 自社の脆弱性スキャナ（特定 AMI）が出す Recon:EC2/Portscan だけを抑制する。
aws guardduty create-filter \
  --detector-id "$DETECTOR_ID" \
  --name "suppress-portscan-from-vuln-scanner" \
  --action ARCHIVE \
  --rank 1 \
  --finding-criteria '{
    "Criterion": {
      "type": { "Equals": ["Recon:EC2/Portscan"] },
      "resource.instanceDetails.imageId": { "Equals": ["ami-0a7a207083example"] }
    }
  }'
```

> **Filter spec (official, key points)**: one filter can specify **at minimum 1, at maximum 50 attributes**, and `Equals`/`NotEquals` are **at most 50 values per attribute.** **Different attributes are AND**, and multiple values of the same attribute are evaluated as AND/OR. So the above example is the AND of "type is Portscan **and** AMI matches" — which is why **the scope is narrowly bounded.** This is the decisive difference from dangerous "type-only" suppression.

### 1.2 What happens and doesn't happen to a "suppressed finding" (the most important fact)

This is the core of this chapter. Get the official behavior precisely wrong, and you misoperate.

| What **doesn't happen** to a suppressed finding (not sent / not triggered) | What **happens** to a suppressed finding (remains) |
| --- | --- |
| **Not sent** to AWS Security Hub CSPM | The finding itself **is generated** (analysis doesn't stop) |
| **Not exported** to Amazon S3 | Stored as **archived** |
| **Not sent** to Amazon Detective | Stored in GuardDuty for **90 days**, viewable anytime during that period |
| **Not sent** to Amazon EventBridge (= auto-response doesn't fire either) | Referenceable via the console's **Archived** or the API `ListFindings` `service.archived = true` |
| **Doesn't trigger** a malware scan of Malware Protection for EC2 | (= doesn't become ETD correlation material. Detailed in Chapter 3) |

To borrow the official's expression directly — **"A suppressed finding isn't sent to AWS Security Hub CSPM, Amazon S3, Amazon Detective, or Amazon EventBridge. Even if you've enabled Malware Protection for EC2, a suppressed finding doesn't trigger a malware scan."** On the other hand, **"GuardDuty keeps generating findings even when a suppression rule matches, but automatically marks them as archived. An archived finding is stored in GuardDuty for 90 days and is viewable anytime during that period."**

This asymmetry is the essence of suppression. **"It drops off the notification/integration paths, but as data it isn't erased."** So —

```bash
# 抑制で消したつもりの finding を、archived として掘り起こして監査する。
# service.archived = true が「抑制された（またはユーザーがアーカイブした）finding」の母集合。
aws guardduty list-findings \
  --detector-id "$DETECTOR_ID" \
  --finding-criteria '{ "Criterion": { "service.archived": { "Equals": ["true"] } } }'
```

> **Implication for design**: suppression is a tool to "quiet the dashboard and notifications," not a tool to "**stop detection**." Since findings remain for 90 days, **you can audit later for "whether a real one was mixed into what suppression had erased."** However — as we'll see in the next chapter, because **Extended Threat Detection doesn't use this archived data as correlation material**, you can't conclude "it's safe because it remains."

### 1.3 In multi-account, "only the administrator" can create suppressions

The official Note is clear — **in a multi-account environment, only the GuardDuty administrator (delegated administrator) can create suppression rules.** A member account's staff can't erase noise on their own. This is rather desirable behavior for governance: **"who erased which detection" is consolidated into the delegated-administrator account**, narrowing the subject of review and audit to one place. How to set up a delegated administrator in an organization is handled in the [multi-account-governance spoke article](/blog/aws-guardduty-multi-account-organizations-delegated-administrator-terraform-guide).

### 1.4 The official's representative suppression use cases (all "type + narrowing" 2-condition)

These are the representative use cases the official lists, after explicitly stating **"create them reactively, only for findings you've confirmed to be a repeated false positive."** What they have in common is that they are, without exception, **the 2-condition "type + scope attribute"** — there's not a single example of erasing by type alone.

| Use case | First condition (type) | Second condition (narrowing) | Why it's harmless |
| --- | --- | --- | --- |
| Egress via on-prem GW | `UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS` | **API caller IPv4 address** (the on-prem GW's IP/CIDR) | A legitimate configuration egressing inward via Outposts or VPC VPN. Add conditions for multiple IPs |
| Vulnerability scanner's port scan | `Recon:EC2/Portscan` | **Instance image ID** (the scanner's AMI) or **Tag** | Your vulnerability-assessment tool is intentionally port-scanning |
| SSH brute force against a bastion | `UnauthorizedAccess:EC2/SSHBruteForce` | **Instance tag value** (a tag identifying the bastion) | A bastion being hit from outside is the expected behavior |
| An intentionally public web server | `Recon:EC2/PortProbeUnprotectedPort` | **Instance tag key** (a tag identifying the public server) | A web server having public ports is normal |
| coredns DNS duplicates (Runtime) | DNS-family Runtime findings like `Trojan:Runtime/*!DNS` | **Executable path** or **Executable SHA-256** (the DNS server pod's process) | K8s has coredns etc. resolving DNS as pods, so **DNS events come out doubly** from the pod side and the server pod side |

Let me add a note only on the last coredns case. According to the official, because a Kubernetes cluster runs a DNS server like `coredns` as a pod, **two DNS events are recorded per DNS lookup** (pod-derived and server-pod-derived), generating **duplicate findings** like `Backdoor:Runtime/C&CActivity.B!DNS`. Narrow this by `executablePath` or `executableSha256` (optionally a third condition of `Kubernetes container image`) and suppress it — this too is a good example of **narrowing down to the process level**, not "type only."

```bash
# coredns 由来の DNS finding 重複を、DNS サーバ pod のプロセスに絞って抑制。
# 型だけで消すと本物の C&C 通信まで消える。executableSha256 で「自分の coredns」に限定する。
aws guardduty create-filter \
  --detector-id "$DETECTOR_ID" \
  --name "suppress-coredns-dns-duplicates" \
  --action ARCHIVE \
  --rank 2 \
  --finding-criteria '{
    "Criterion": {
      "type": { "Equals": ["Backdoor:Runtime/C&CActivity.B!DNS"] },
      "service.runtimeDetails.process.executableSha256": { "Equals": ["<your-coredns-sha256>"] }
    }
  }'
```

---

## 2. Managing Suppression Rules with IaC (Terraform)

Creating a suppression rule by clicking in the console is **an anti-pattern.** You can't review "who erased which detection, when, why, under what condition," and you can't reproduce it. Since suppression is **a change that shaves detection capability**, it should be the operation that most needs review. So, with IaC.

```hcl
# 抑制ルール = action = "ARCHIVE" の aws_guardduty_filter。
# action の許容値は "ARCHIVE"（抑制）か "NOOP"（通常フィルタ）。
# 公式の2条件パターンを criterion 2つで表現する。
resource "aws_guardduty_filter" "suppress_scanner_portscan" {
  name        = "suppress-portscan-from-vuln-scanner"
  detector_id = aws_guardduty_detector.this.id
  action      = "ARCHIVE" # ← これが「フィルタ」を「抑制ルール」にする
  rank        = 1         # フィルタの適用順（小さいほど先に評価）

  # なぜ消すかを description に必ず残す（レビューと棚卸しのための監査証跡）。
  description = "Vuln scanner (AMI ami-0a7a2070...) intentionally port-scans; benign. Reactive, scoped by imageId."

  finding_criteria {
    # 第1条件: finding 型を1つに固定（型を丸ごと広く消さない）。
    criterion {
      field  = "type"
      equals = ["Recon:EC2/Portscan"]
    }
    # 第2条件: スキャナの AMI に限定（ここが無いと全 Portscan を消す危険な抑制になる）。
    criterion {
      field  = "resource.instanceDetails.imageId"
      equals = ["ami-0a7a207083example"]
    }
  }
}
```

Let me state this code's design decisions explicitly.

- **`action = "ARCHIVE"` is the body of suppression.** Terraform's `aws_guardduty_filter` `action` is a choice of `"ARCHIVE"` (suppress) or `"NOOP"` (a normal filter that saves but doesn't archive). If you want to suppress, `ARCHIVE`.
- **Always 2 or more criteria.** As per the official pattern, "type + narrowing." Finishing with one `type`-only criterion makes **that the most dangerous suppression of "erasing a whole type"** (the trap in Chapter 3).
- **Leave "why, and the grounds it's reactive" in `description`.** Since suppression is an operation that shaves detection, always leave an audit trail by which a reviewer can judge "was this really a repeated false positive."
- **Be mindful of the application order with `rank`.** The evaluation order when there are multiple filters. Manage it mindful of narrow-scope ones so a suppression rule doesn't unintentionally sweep in broad findings.

> **Verification path (official)**: that the suppression rule you made erases "only the targeted findings" and doesn't erase "anything else" can be verified by firing samples of each type with `create-sample-findings` and comparing the findings that fall to `service.archived = true` against those that reach EventBridge (samples can be distinguished by the `[SAMPLE]` prefix and `service.additionalInfo.sample = true`). The principle of "build the verification path first" takes effect most for changes that **erase** detection.

---

## 3. THE trap: too-broad suppression blinds Extended Threat Detection

This is **the most important passage** in this article. The real danger of a suppression rule isn't "noise decreases too much," but **"erasing the attack context itself along with the noise."**

### 3.1 The behavior the official explicitly states

Let me quote the official Note precisely — **"When correlating events for an attack sequence, Extended Threat Detection doesn't consider archived findings. This includes findings that were automatically archived by a Suppression Rule."**

In other words, the mechanism by which [Extended Threat Detection (ETD)](/blog/aws-guardduty-threat-detection-multi-account-terraform-eventbridge-guide) "correlates weak signals over a 24-hour window to bundle a multi-stage attack into one Critical attack sequence" **cannot use suppression-archived findings as material.** As we saw in Chapter 1, a suppressed finding remains in GuardDuty for 90 days — but **"remaining" and "usable for correlation" are different.**

### 3.2 The concrete example the official gives (whole-type suppression of EKS)

The official even gives a concrete example — **"If you create a suppression rule that archives all EKS-cluster-related findings rather than targeting a specific known activity, GuardDuty becomes unable to detect, using those findings, the attack sequence 'a threat actor abuses a container → obtains a privileged token → accesses sensitive resources.'"**

Drawn as a picture, it's this.

```text
                              ┌─ Individual finding A (weak signal) ─┐
  Attack chain (multi-stage) ─┼─ Individual finding B (weak signal) ─┼─→ ETD correlates → AttackSequence (Critical 9.0-10.0)
                              └─ Individual finding C (weak signal) ─┘
                                          ▲
       A broad suppression rule that "archives all EKS findings by type"
                                          │
                              A・B・C fall into archived
                                          │
                                          ▼
                       ETD doesn't use archived as correlation material
                                          │
                                          ▼
              AttackSequence can never be bundled again ("no material") — made invisible
```

**Thinking you erased false positives, you've made the most serious Critical multi-stage attack undetectable with your own hands** — this is the trap of suppression rules. An individual finding looks like a "moderately suspicious operation," so you're tempted to erase it broadly. But each one of them is, for ETD, the **material** that bundles the attack sequence.

### 3.3 The official's recommendation, and the "do / don't" dropped into operations

The official recommends 2 points — **① you may keep using suppression rules to reduce alerts from known trusted activity. ② But narrow suppression rules to "a specific behavior you don't want GuardDuty to surface findings for."** Plus, as a best practice, **"create them reactively, only for findings you've confirmed to be a repeated false positive in your own environment."** "Erasing in advance just in case" is clearly forbidden.

Dropped into operational rules, it's this (the same philosophy as the [audit table in the ETD spoke article](/blog/aws-guardduty-extended-threat-detection-attack-sequence-findings-guide). That one handles the same trap from the ETD side, this article from the tuning side).

| ✅ Suppression you may do (scope-narrowed) | ❌ Suppression you must not do (whole type) |
| --- | --- |
| `Recon:EC2/Portscan` **limited to the scanner's AMI/tag** | Suppress `Recon:*` by type across all accounts |
| `UnauthorizedAccess:EC2/SSHBruteForce` **limited to a specific bastion's tag** | Suppress EKS/S3-related findings **broadly with no resource specified** |
| `InstanceCredentialExfiltration.OutsideAWS` **limited to the on-prem GW's fixed IP** | **Preemptively** suppress a type that could become attack-sequence material |

**The iron rule is "limit suppression to pinpoints narrowed by resource/IP/tag. Erasing a whole type is the act of putting out ETD's eyes."** Then how do you "quiet just the noise by type"? — **the answer is not suppression (= archive = invisible to ETD), but "quieting just the notification" with [the EventBridge notification-side filter](/blog/aws-guardduty-eventbridge-automated-remediation-incident-response-guide).** If you achieve "don't flow to Slack" with the EventBridge rule's `severity` numeric match or type routing, **the finding stays active inside GuardDuty and lives on as ETD correlation material.**

> **One-line summary of the use distinction**: **"erase detection" → suppression (but pinpoint) / "quiet just notification" → EventBridge filter.** The majority of noise reduction is actually enough with the latter. Think of suppression as a last resort used only for "narrowable noise that is structurally confirmed to be a false positive."

### 3.4 Take inventory of existing suppression rules (audit script)

"Is there any too-broad suppression" should be inventoried periodically. Among `action = ARCHIVE` filters, the danger sign is those whose `criterion` is **type (`type`) only** with no resource narrowing.

```bash
# 委任管理者アカウントで実行：全フィルタを列挙し、action=ARCHIVE のものを監査する。
# criterion が type だけ（resource.* / IP / タグ無し）の抑制が「型丸ごと」の危険信号。
DETECTOR_ID="$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)"

for FILTER in $(aws guardduty list-filters --detector-id "$DETECTOR_ID" \
                  --query 'FilterNames[]' --output text); do
  echo "=== ${FILTER} ==="
  aws guardduty get-filter --detector-id "$DETECTOR_ID" --filter-name "$FILTER" \
    --query '{name:Name, action:Action, criterion:FindingCriteria.Criterion}'
done
```

> **Audit focus**: look for ones where `action` is `ARCHIVE` and the `Criterion` key is `type` **only.** Suppression that erases especially EKS / S3 / IAM families by type is highly likely to be making the corresponding attack sequences (`AttackSequence:EKS/CompromisedCluster`, `S3/CompromisedData`, `IAM/CompromisedCredentials` respectively) invisible. If found, either narrow with a resource specification, or stop suppressing and move to the notification-side filter.

---

## 4. Deep dive on trusted lists and threat lists: entity lists and IP lists

The 3rd and 4th tools are lists. Where suppression looks at "the finding side," lists look at **"the source side"** — "don't emit findings from this IP/domain (trusted) / do emit (threat)."

### 4.1 Entity list (recommended) vs legacy IP list

The official presents 2 implementations and **recommends the entity list.**

| | **Entity list (recommended)** | **Legacy IP list** |
| --- | --- | --- |
| What you can list | **IP addresses, domain names, SHA-256 file hashes** | **IP addresses only** |
| Permission model | **Direct S3 access + a single IAM permission** (doesn't bloat IAM policy size across multiple regions) | **Service-linked role (SLR).** Needs IAM policy updates per region |
| Hashes | SHA-256 possible **only in a threat entity list** (not in a trusted list) | No hashes |

> **Implication for design**: for new builds, it's **the entity list, no question.** A legacy IP list takes only IPs, and **bloats the IAM policy by the number of regions** on an SLR basis. The entity list gets by with a single IAM permission and can handle domains and hashes (threat list only). The official also guides a migration procedure (add and activate an entity list, then deactivate/delete the corresponding IP list).

### 4.2 List limits (official, precisely)

This is the place where **you must absolutely not invent numbers.** Precisely, the limits the official explicitly states:

| Limit | Value (official) |
| --- | --- |
| Trusted entity list | **1** per account × region |
| Trusted IP list | **1** per account × region |
| Threat lists (entity + IP) | **max 6** per account × region |
| IP version | **IPv4 only** (IPv6 unsupported) |
| Target addresses/domains | **Publicly routable IPs/domains only** |
| Max file size | **35 MB** |
| Propagation time | Activate/deactivate/delete completes in **about 15 min** (up to **40 min** in some cases) |

> **The per-list entry count is "to be checked in the official"**: the cap on how many IPs/domains you can list in one list **is not written** in this guide's table. The official says "the quota differs between an entity list and an IP list" and defers the details to [GuardDuty quotas](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_limits.html). **If the entry-count cap relates to your requirements, always check the latest value on the quotas page** (writing a concrete number here would quickly become stale and misinformation).

### 4.3 Difference in scope of application (beware DNS) and priority

Lists have a scope of "which findings they affect," and it **differs between an entity list and an IP list.** Get this wrong and you have the accident of "I put a malicious DNS domain in an IP list but it has no effect."

| | Entity list | IP list |
| --- | --- | --- |
| CloudTrail findings | Applies | Applies |
| VPC Flow Logs findings | Applies | Applies |
| **Route 53 Resolver DNS query log findings** | **Applies** | **Doesn't apply** |

As per the official — **an entity list's entries apply to CloudTrail, VPC Flow Logs, and Route 53 Resolver DNS query log findings. An IP list's entries apply to CloudTrail and VPC Flow Logs but don't apply to DNS query log findings.** This is another reason that if you deal with domains (if you want it to affect DNS), it's **the entity list, no question.**

The official also explicitly states priority — **if you put the same IP/domain in both a trusted list and a threat list, the trusted list takes priority.** GuardDuty doesn't generate a finding. To avoid the accident of "registered as malicious, but it's also in another trusted list and isn't detected," make **whether entries collide between trusted and threat** a managed item.

Further, **an application-plan exception** — lists affect the whole of foundational data sources + protection plans, but **only Runtime Monitoring is an exception (not applied).** Understand that Runtime Monitoring's process/system-call detection is not subject to trusted/threat overriding by lists.

### 4.4 The operation of multi-account and "re-activation"

There are 2 operational pitfalls.

1. **In multi-account, only the administrator manages lists.** As per the official — **in a multi-account environment, only the GuardDuty administrator account can manage lists, and the settings are automatically applied to member accounts.** Findings are generated for malicious IPs/domains on the administrator's threat sources, and not generated for those on the administrator's trusted sources — this takes effect across all members. Like suppression rules, **governance is consolidated to the administrator.**
2. **After editing a file in S3, always re-activate.** The official explicitly states — **after adding or updating entries in the list's S3 bucket, you must re-activate the list.** If you assume "it reflects automatically because I overwrote S3," you get a state where (together with the 15–40 min in 4.2) **the new entries aren't in effect.** In IaC, it's safest to **link "updating the S3 object" and "re-activating the list" in one apply.**

### 4.5 Managing trusted IP / threat lists with IaC (Terraform)

Because the entity list is a new feature, **as of June 2026 there's (still) no dedicated resource in the AWS provider** — `aws_guardduty_ipset` (trusted IP) and `aws_guardduty_threatintelset` (threat) are the IP-list / threat-list equivalents. **If you want to fully manage the entity list in Terraform, always check the latest provider for the existence of a dedicated resource** (if absent, manage with an S3 object + API/CLI and build re-activation into the pipeline). Here I show it with the 2 resources that certainly exist.

```hcl
# ── 信頼 IP リスト（aws_guardduty_ipset）──
# 自社の固定 egress IP など「正規ソース」を登録。ここからは finding を生成しない。
# format の許容値: TXT | STIX | OTX_CSV | ALIEN_VAULT | PROOF_POINT | FIRE_EYE
resource "aws_guardduty_ipset" "trusted" {
  detector_id = aws_guardduty_detector.this.id
  name        = "corporate-egress"
  format      = "TXT"
  # S3 上のリストファイル。中身を更新したら activate を打ち直す必要がある（4.4 参照）。
  location    = "https://s3.amazonaws.com/${aws_s3_object.trusted_ips.bucket}/${aws_s3_object.trusted_ips.key}"
  activate    = true # Active にして初めて検知に反映される
}

# ── 脅威リスト（aws_guardduty_threatintelset）──
# 自前で「悪性」と判断した IP を登録。一致すると .Custom メカニズムで finding が出る。
resource "aws_guardduty_threatintelset" "custom_threats" {
  detector_id = aws_guardduty_detector.this.id
  name        = "org-custom-threat-feed"
  format      = "TXT"
  location    = "https://s3.amazonaws.com/${aws_s3_object.threat_ips.bucket}/${aws_s3_object.threat_ips.key}"
  activate    = true
}

# リストファイル本体。content のハッシュが変わると Terraform が差分を検知し、
# 依存する ipset/threatintelset の再 apply（= 再アクティベート）が走るよう構成する。
resource "aws_s3_object" "trusted_ips" {
  bucket  = aws_s3_bucket.sec_config.id
  key     = "guardduty/trusted-ips.txt"
  content = "198.51.100.0/24\n203.0.113.10\n" # IPv4 のみ・公開アドレスのみ
}
```

> **Dropping re-activation into IaC**: if you build dependencies so that, as above, "changing the S3 object's `content` (or `etag`) → re-applying the ipset/threatintelset" chains, you can **guarantee 4.4's "re-activate after editing" without relying on manual work.** You can structurally eliminate the typical accident of overwriting S3 by hand and agonizing over "it doesn't reflect."

---

## 5. Decision framework: symptom → correct tool

Let me summarize the 3 (+1) tools so far into a table you can **reverse-look-up from "the noise symptom."** It's the quick reference you should open first in the tuning field.

| Symptom (the noise's identity) | Correct tool | Concrete measure | The alternative you must not do |
| --- | --- | --- | --- |
| Your scanner's periodic port scan is noisy | **Suppression Rule** | ARCHIVE `Recon:EC2/Portscan` narrowed by AMI/tag | Suppress `Recon:*` by type (blinds ETD) |
| SSH brute force against a bastion is the expected behavior | **Suppression Rule** | ARCHIVE `SSHBruteForce` narrowed by bastion tag | Suppress by type |
| Findings come out from your fixed egress IP's communication | **Trusted list** | Register the IP in a trusted entity/IP list | Suppress the type from that IP (erases other sources too) |
| DNS queries to a monitoring SaaS's domain are noisy | **Trusted entity list** | Register the domain in a trusted **entity** list (an IP list doesn't affect DNS) | Put it in a trusted IP list (DNS not applied, no effect) |
| You want to detect an IP/domain you've judged "malicious" yourself | **Threat list** | Register in a threat entity/IP list (made into a finding via `.Custom`) | Suppression (the opposite-direction tool) |
| You want to detect by a known malware hash | **Threat entity list** | Register the SHA-256 in a **threat** entity list | Trusted list/IP list (no hash support) |
| "Want to quiet just the noise by type" (want to keep the attack context) | **EventBridge notification filter** | [Filter by the notification rule's severity/type](/blog/aws-guardduty-eventbridge-automated-remediation-incident-response-guide). Keep the finding in GuardDuty | Suppression (archive = invisible to ETD) |

### 5.1 Correcting the cost misconception (the most important money talk)

Finally, let me crush the **most common misconception** — **"suppressing noise makes GuardDuty cheaper" is wrong.**

[GuardDuty's billing occurs against "the volume of logs analyzed"](/blog/aws-guardduty-cost-optimization-pricing-finops-guide) (the number of CloudTrail events, VPC/DNS GB, vCPU-hours, etc.). **You're not billed by the number of findings.** So:

- **A Suppression Rule doesn't lower cost by a single yen.** As in Chapter 1, a suppressed finding **is generated too** (analysis hasn't stopped). Archiving only "drops it off the notification path"; the analysis volume is unchanged.
- **A trusted list doesn't reduce the analysis volume either.** It only **doesn't generate** a finding about a trusted source; **the log analysis of that traffic itself is performed.** Findings decrease, but the data is still analyzed and billed.

> **Conclusion**: **tuning (suppression, lists) is a tool for "noise reduction, false-positive reduction, and detection-accuracy adjustment," not a tool for "cost reduction."** If you want to lower GuardDuty's cost, attack with **protection-plan selection** (limiting Runtime Monitoring to important workloads, etc.), not suppression — for details, see the [cost-optimization spoke article](/blog/aws-guardduty-cost-optimization-pricing-finops-guide). Cut off the **double misconception** of "alerts are noisy → suppression makes it cheaper" right here.

---

## 6. The tuning runbook: measure → identify → apply at minimal scope → review

Now that the tools and decision axes are in place, let me drop them into a **repeatable operational procedure.** The principles are idempotent, reviewable, and IaC-centric.

### Step 1. Measure (take a baseline of the noise)

First, quantify "what, how much, from where" is noisy. Don't make suppressions by feel.

```bash
# 直近のアクティブな finding を型別に集計し、ノイズの上位を特定する。
# （ListFindings → GetFindings で型を取得して集計するのが基本。ここは骨子）
aws guardduty list-findings --detector-id "$DETECTOR_ID" \
  --finding-criteria '{ "Criterion": { "service.archived": { "Equals": ["false"] } } }' \
  --query 'FindingIds' --output text
# 取得した finding を GetFindings で型・ソース IP・リソースまで割り、上位ノイズを定量化する。
```

### Step 2. Identify (a "pattern" or a "source," reactive?)

For each top noise, decide the tool with Chapter 0's branch.

- **The same finding type comes out repeatedly on a specific resource (AMI/tag)** → Suppression Rule (type + narrowing). **And there must be reactive grounds that "it was confirmed to be a repeated false positive."**
- **It comes out from a specific legitimate source IP/domain** → trusted list (an entity list if a domain or DNS is involved).
- **You just want to quiet it by type (keep the attack context)** → not suppression, but an EventBridge notification filter.

### Step 3. Apply at minimal scope (IaC)

Write the decided tool into IaC at **the narrowest possible scope** (as in Chapters 2 and 4.5). For suppression, always the 2-condition "type + resource narrowing," with the reactive grounds in `description`. For lists, link the S3 update and re-activation.

### Step 4. Review (haven't you blinded ETD?)

After applying, always confirm **"hasn't this change erased attack-sequence material."**

- With 3.4's audit script, inventory whether `action=ARCHIVE` and `type`-only filters have increased.
- Confirm whether the suppressed type could become material for `AttackSequence:*` (be especially careful with EKS/S3/IAM families). If it could, **switch from suppression to a notification filter.**
- Confirm there's no entry collision (the same IP in both) between the trusted/threat lists (to prevent the accident where trusted takes priority).

> **Idempotency and reviewability**: this runbook completes in **code and CLI** at every step. Both suppression rules and lists converge to the same state no matter how many times you run Terraform's `apply` (idempotent), and the `plan` diff **becomes the subject of review as-is.** You can structurally eliminate the worst silent change in security operations: "someone was quietly erasing detection in the console." This is the same idea as guaranteeing "correctness with a mechanism rather than carefulness" in a payment platform.

---

## 7. Summary: the GuardDuty tuning cheat sheet

A quick reference for when you're unsure.

- **3 tools, 3 jobs**: **Suppression Rule** = auto-archive known harmless **finding patterns** / **trusted list** = don't emit findings from known legitimate **sources** / **threat list** = emit findings from known malicious **sources.** "Pattern or source" decides the tool.
- **What happens / doesn't to a suppressed finding**: **not sent** to Security Hub CSPM, S3, Detective, or EventBridge, and Malware Protection for EC2 **doesn't trigger** either. But the finding **is generated** and **stored for 90 days as archived** (referenceable via `service.archived = true`). **Suppression doesn't stop detection, only notification.**
- **Suppress with the 2-condition "type + narrowing"**: all the official's use cases are 2-condition, type + AMI/tag/IP/process. **A `type`-only suppression is the most dangerous.**
- **THE trap (most important)**: **ETD doesn't use archived (including auto-archived by suppression) findings as correlation material.** Broad suppression erasing EKS etc. by type makes `AttackSequence:*` (Critical 9.0-10.0) wholly invisible. Suppress **reactively, narrowed to a specific behavior.** If you just want to quiet by type, use **the EventBridge notification filter, not suppression.**
- **For lists, the entity list is recommended**: IP/domain/SHA-256 (hashes only in a **threat** list), a single IAM permission. A legacy IP list is IP-only, SLR. **1 trusted entity + 1 trusted IP, max 6 threat lists** (account × region). **IPv4 only, public addresses/domains only, 35 MB, re-activate after editing (about 15 min, up to 40 min).**
- **Scope of application**: an entity list applies to CloudTrail/VPC/**DNS**, an IP list to CloudTrail/VPC only (**DNS not applied**). **Trusted takes priority over threat.** Lists apply to all plans except Runtime Monitoring.
- **Multi-account**: both suppression rules and lists are managed by **only the delegated administrator** (governance consolidated).
- **Discard the cost misconception**: **neither suppression nor a trusted list lowers GuardDuty cost** (billing is by analysis volume, not the number of findings). Cost reduction is by protection-plan selection.
- **Runbook**: measure → identify pattern/source (reactive?) → apply at minimal scope in IaC → review whether you've blinded ETD. **With Terraform/CLI, not a console click.**

GuardDuty tuning isn't "the work of silencing noisy alerts." It's **a precise operation that shaves only the noise without shaving detection capability — "leaving only the findings that should be responded to, and losing none of the attack context."** The biggest pitfall is erasing the material of a Critical attack sequence along with the noise. That's exactly why — **suppress pinpoint, reactively, with IaC** — takes effect.

On a multi-account [serverless payment platform](/case-studies/payment-platform-reliability), I **cross-implemented the IAM, observability, and DR of a platform handling actual money, carbon credits, and local currencies**, and guaranteed "correctness" with **the structure and idempotency of code** rather than operational carefulness. I design GuardDuty tuning with the same philosophy — **① first quantify the noise, ② select the tool by pattern or source, ③ drop it into IaC at minimal scope, ④ guarantee with review that ETD isn't blinded.** I structurally prevent the accident of "muting everything" and erasing the attack too.

**"My GuardDuty's alerts are noisy but I don't know what's safe to erase" — from the design of Suppression Rules and trusted/threat lists, the narrowing of suppression that doesn't blind ETD, the use distinction with EventBridge notification filters, to IaC-ification and the audit mechanism, I can accompany you fast and safely with one person × generative AI (Claude Code).** Feel free to consult us, even from the requirements-organizing stage.

---

### Reference (Official Documentation)

- [Suppression rules in GuardDuty](https://docs.aws.amazon.com/guardduty/latest/ug/findings_suppression-rule.html) — suppression = auto-archive, where it isn't sent (Security Hub/S3/Detective/EventBridge), 90-day storage, `service.archived`, administrator-only creation, the interaction with ETD, representative use cases (the 2-condition type + narrowing), reactive recommendation
- [Customizing threat detection with entity lists and IP address lists](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_upload-lists.html) — entity list (recommended) vs IP list, trusted/threat caps (1/1/max 6), IPv4 only, public addresses only, the DNS application difference, trusted priority, re-activation (15–40 min), 35 MB, the Runtime Monitoring exception, supported formats
- [Filtering findings in GuardDuty](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_filter-findings.html) — filter attributes 1–50, `Equals`/`NotEquals` max 50 values, attributes are AND, the precise JSON field names of `type`/`resource.instanceDetails.imageId`/`tags.key`/`tags.value`/`service.action.awsApiCallAction.remoteIpDetails.ipAddressV4` etc., `service.archived`
- [aws_guardduty_filter (Terraform AWS Provider)](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/guardduty_filter) — `action` (`ARCHIVE`/`NOOP`), `rank`, `finding_criteria { criterion { field, equals/not_equals/... } }`
- [aws_guardduty_ipset / aws_guardduty_threatintelset](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/guardduty_ipset) — IaC management of trusted IP list/threat list (`format`, `location`, `activate`). Check the latest provider for the existence of a dedicated entity-list resource
- [GuardDuty quotas](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_limits.html) — the precise latest values of quotas not written in the body, such as the entry count per list
