Documentation & Tools →
Sign In
← Back to Blog

Your Noisy Rule Has 200 False Positives a Day. Don't Suppress the Field That's Making Noise.

9 June 2026 Detection Engineering 9 min read
TWO WAYS TO QUIET THE SAME NOISY RULE SUPPRESS THE NOISY FIELD "encoded PowerShell is noisy, exclude the hosts that run it" Noise gone. So is the detection. The attacker uses encoded PowerShell on exactly the hosts you excluded. Silent false negative SCOPE TO ATTACKER BEHAVIOUR "encoded PowerShell is normal; encoded + network + no parent shell is what the attack looks like" Noise gone. Detection sharper. The admin's encoded command lacks the combination. The attacker's has it. True positive preserved Same noise reduction. Opposite effect on the thing the rule was built to catch.

There's a detection rule somewhere in your library generating 200 alerts a day, and every one of them is a false positive. Your analysts have learned to close it without reading it. That rule is worse than useless now: it's training your team to dismiss the alert that one day will be real.

So you tune it. And the fastest tuning move, the one almost everyone reaches for first, is to find the field that's generating the noise and exclude it. The rule fires on encoded PowerShell, your build servers run encoded PowerShell all day, so you add where DeviceName !in (build servers). Alert volume drops to zero. Problem solved.

You've just cut a hole and told the attacker where it is. The build servers are high-value targets precisely because they run arbitrary code as a matter of course. You excluded the noisiest hosts, which are often the ones an attacker most wants to land on, and you did it in a way that leaves no trace in the alert stream. Nobody will ever file a ticket telling you the rule stopped covering them.

This is the central tension of detection tuning. Noise reduction and coverage pull in opposite directions when you tune the wrong way, and the wrong way is almost always easier. The skill is reducing noise while keeping, or sharpening, the detection. That means tuning to the attacker's behaviour, not away from the field that happens to be loud.

Why suppression feels right and is usually wrong

A false positive and a true positive often share a field value. That's the whole problem. Your admin runs powershell -enc to deploy a config. Your attacker runs powershell -enc to pull down a second stage. The encoded-command field is identical in both. If you tune by suppressing that field, or by excluding the accounts and hosts that produce the benign version, you remove the benign and malicious cases together, because at the level you're filtering they are the same event.

Suppression treats the symptom (this field is noisy) instead of the cause (this rule can't tell benign from malicious because it's only looking at one dimension). A rule that fires on a single suspicious attribute will always be noisy, because single attributes are rarely suspicious on their own. Encoded PowerShell is not malicious. A service account authenticating at 2am is not malicious. An outbound connection to a cloud IP is not malicious. Each one is normal somewhere in your environment, which is exactly why a rule built on any one of them alone drowns you.

The fix runs the other way: instead of removing the normal cases, you add the dimensions that separate the attacker's version from everyone else's.

There's a statistical reason this works, and it's worth understanding rather than taking on faith. Each individual condition has a high base rate: encoded PowerShell happens thousands of times a week, Office processes spawn children constantly, outbound connections are continuous. A rule on any one of them inherits that base rate as noise. But the conditions are close to independent in benign activity, so their co-occurrence is rare: the probability of all three lining up by coincidence is the product of three already-uncommon events, which collapses to near zero. In attacker activity they are not independent, they are causally linked, because the malicious chain produces all three by design. That asymmetry, common together only when an attack causes them, is the entire basis of high-fidelity detection. A single attribute fires on everything that produces it. A combination fires only when something causes all of it at once, and in your environment the thing that does that is the attack.

Scope to the combination, not the attribute

Real attacker behaviour is a combination of conditions that rarely co-occur in benign activity. Your admin's encoded PowerShell has a parent process of cmd.exe or a deployment agent, runs on a known schedule, and doesn't immediately open a network connection to an external host. The attacker's encoded PowerShell has a parent process of winword.exe or outlook.exe, runs at an unusual time, and reaches out to a freshly registered domain within seconds.

Tune to that. Instead of removing the noisy field, add the conditions that the benign cases don't satisfy and the malicious ones do. You keep the encoded-command signal and require it to coincide with an anomalous parent process and an outbound connection. The admin's deployment no longer matches because it lacks the parent-process and network conditions. The attacker's chain still matches because it has all three.

Here is the naive version first, the one that generates the 200 daily false positives, written against Defender XDR process telemetry:

// NAIVE: fires on any encoded PowerShell command.
// Hypothesis is too broad: "encoded PowerShell is suspicious."
// Reality: your admins encode commands all day. ~200 FPs/day.
DeviceProcessEvents
| where FileName =~ "powershell.exe"
| where ProcessCommandLine has_any ("-enc", "-encodedcommand", "-e ")

The temptation now is one more line: | where DeviceName !in ("BUILD01", "BUILD02", "DEPLOY01"). Resist it. Add dimensions instead. The tuned version keeps the encoded-command signal and requires it to coincide with a suspicious parent and a near-immediate network egress:

// TUNED: encoded PowerShell is kept as a signal, not removed.
// Hypothesis: encoded command + Office/email parent + outbound
// connection within 60s is the malicious combination, not the
// encoding alone. Admin deployment lacks the parent and network legs.
let encoded = DeviceProcessEvents
    | where FileName =~ "powershell.exe"
    | where ProcessCommandLine has_any ("-enc", "-encodedcommand", "-e ")
    | where InitiatingProcessFileName has_any ("winword.exe", "excel.exe", "outlook.exe", "mshta.exe", "wscript.exe")
    | project DeviceId, Timestamp, ProcessCommandLine, InitiatingProcessFileName, encodedProcessId = ProcessId;
encoded
| join kind=inner (
    DeviceNetworkEvents
    | where RemoteIPType == "Public"
    | project DeviceId, NetTimestamp = Timestamp, RemoteUrl, InitiatingProcessId
) on DeviceId
| where NetTimestamp between (Timestamp .. (Timestamp + 60s))
| project DeviceId, Timestamp, ProcessCommandLine, InitiatingProcessFileName, RemoteUrl

The volume difference is not incremental. A single-attribute encoded-command rule in a mid-size estate produces hundreds of hits a day. The three-condition version, in the same estate, produces a handful per week, and every one is worth an analyst's time. You didn't suppress anything. You described the attack more precisely, and precision is what kills false positives without killing coverage.

Benchmark to compare against
A healthy detection rule sits at a true-positive rate above roughly 1 in 20 of the alerts it raises. If your analysts close 50 instances of the same rule before one is real, the rule is mistraining them, and the next real one gets closed too. Track per-rule disposition. Any rule under a 5% true-positive rate over 30 days is a tuning candidate. The rule may be perfectly correct; its scoping is simply too broad to be actioned, and a correct rule nobody can action is still a liability.

The same logic in Splunk and Sigma

The principle is platform-independent. The point of detection engineering is that you express the attacker's behaviour, then translate it to whatever query language your SIEM speaks. Here is the same tuned hypothesis in SPL, correlating Sysmon process creation (Event ID 1) with network connection (Event ID 3):

`# Same hypothesis: encoded command + Office parent + egress in 60s.`
`# Correlates Sysmon EID 1 (process) with EID 3 (network).`
index=sysmon (EventCode=1 Image="*\\powershell.exe"
  (CommandLine="*-enc*" OR CommandLine="*-encodedcommand*")
  (ParentImage="*winword.exe" OR ParentImage="*excel.exe"
   OR ParentImage="*outlook.exe" OR ParentImage="*mshta.exe"))
  OR (EventCode=3 Image="*\\powershell.exe")
| transaction Computer ProcessGuid maxspan=60s
| search EventCode=1 EventCode=3
| table _time Computer User CommandLine ParentImage DestinationHostname

And as a portable Sigma rule, so the detection lives in version control and converts to any backend rather than being locked to one vendor's console:

# Scope to the combination, not the attribute.
# Network leg correlated in the backend / via aggregation.
title: Encoded PowerShell Spawned by Office or Script Host
status: experimental
logsource:
  category: process_creation
  product: windows
detection:
  selection_ps:
    Image|endswith: '\powershell.exe'
    CommandLine|contains:
      - '-enc'
      - '-encodedcommand'
  selection_parent:
    ParentImage|endswith:
      - '\winword.exe'
      - '\excel.exe'
      - '\outlook.exe'
      - '\mshta.exe'
      - '\wscript.exe'
  condition: selection_ps and selection_parent
falsepositives:
  - 'Office add-ins that legitimately invoke PowerShell (rare; verify)'
level: high
tags:
  - attack.execution
  - attack.t1059.001

Notice the falsepositives field is not empty and not a dumping ground. It names the one realistic benign case and tells the next engineer to verify rather than blindly exclude it. That field is where good tuning gets documented. When you do need an exclusion, it goes there with a reason, not silently into a !in clause nobody will ever audit.

When an exclusion is actually correct

Scoping to behaviour handles most tuning. But some false positives are genuinely benign activity that is structurally identical to the attack, and no additional dimension separates them. A vulnerability scanner that triggers your port-scan detection is the textbook case: it really is scanning, the rule is right to fire, and there is no behavioural tell that distinguishes the authorised scanner from an attacker except identity.

That's when an exclusion is legitimate. Make it narrow: exclude the specific scanner's service account and source host, never the whole subnet. Pin it to an identity you have independently verified, so that if an attacker compromises a different account on the same host the rule still fires. And record why the exclusion exists, with a review date, because an exclusion with no expiry is a permanent blind spot that outlives the reason it was added.

The exclusion test
Before you add any exclusion, answer one question: if an attacker did exactly what I'm about to exclude, from the thing I'm about to exclude, would I want to know? If yes, you're scoping too broadly. Narrow the exclusion until the answer is no. Excluding a service account on one host can pass this test. Excluding an entire host, subnet, or user group almost never does.

What to do this week

  1. Pull your top five rules by alert volume and calculate each rule's true-positive rate over the last 30 days. Any rule under 5% goes on the tuning list. This is the same per-rule disposition data you need for the silent-rule problem, so build the query once.
  2. Take the noisiest rule and audit its exclusions. For every !in, NOT in, where ... !=, or allow-list, ask the exclusion test above. Anything that would hide a real attack from a high-value host gets reworked into a behavioural condition.
  3. Rewrite that rule to scope on a combination of two or three conditions the attacker satisfies and the benign cases don't, rather than suppressing the noisy field. Use the parent-process and network-egress pattern above as a template.
  4. Move any genuinely necessary exclusions into a documented allow-list with an owner and a review date. An exclusion in the rule body with no comment is a future incident.
  5. Validate that the tuned rule still fires. Run the attack it claims to catch (Atomic Red Team test T1059.001 covers encoded PowerShell execution) in a controlled host and confirm an alert lands. A tuned rule you haven't re-tested is an assumption, and the silent gap between "I tuned it" and "it still works" is exactly where the false negative hides. The Sigma project's detection rule repository and the MITRE ATT&CK technique pages are the reference points for what the tuned behaviour should look like.

Tuning is the act of making a rule precise. Making it quiet is a side effect when you do it right and a disaster when you do it wrong. A quiet rule and a precise rule look identical on the dashboard right up until the moment an attacker uses the exact path you suppressed, and only one of them fires.

Ridgeline Cyber Defence Written by security practitioners. Published weekly on Tuesdays.

Related Articles

2 June 2026

You Deployed 350 Detection Rules. Only 50 Fire Regularly. Are the Other 300 Working?

Most detection libraries are full of rules that have never fired. Silent rules aren't coverage. They're assumptions. Her

20 May 2026

Credential Access Detection Beyond LSASS — The Five Techniques Your Rules Are Missing

LSASS dump detection is table stakes. Kerberoasting, DCSync, DPAPI abuse, SAM extraction, and token theft each need diff

19 May 2026

Is Your Detection Program Effective? And How Would You Know?

Most organizations can't prove their detection program works. Here's what effective looks like and the four numbers that