Indicators Are Perishable

Every IOC you ingest starts dying the moment it is published. The C2 server gets burned and reassigned. The phishing domain lapses and gets parked. The compromised WordPress host gets cleaned. Meanwhile your blocklist still remembers all of them as hostile.

Most teams obsess over IOC collection and ignore IOC retirement. The result is predictable: a blocklist that grows forever, a SIEM that matches on ancient indicators, and analysts burning hours on alerts about infrastructure that changed hands two years ago.

An indicator without an expiration policy is not intelligence. It is a liability with a timestamp.


Shelf Life by Indicator Type

Not all IOCs age at the same rate. The decay rate maps roughly to how cheap the artifact is for an attacker to rotate, and how quickly the underlying resource gets recycled by the legitimate internet.

IOC type Typical useful life Why it decays
File hash (SHA-256) Effectively forever, but narrow Never becomes benign, but attackers recompile constantly, so it stops matching anything new
URL (full path) Hours to days Phishing kits and payload paths rotate fastest of all
Domain Days to months Registrations lapse, domains get sinkholed, parked, or re-registered by innocents
IP address Hours to weeks Cloud IPs recycle in minutes; VPS churn is constant; shared hosting was never exclusive
Email address Days to weeks Free-mail accounts get suspended and recreated in bulk
Mutex / registry key Months to years Tied to malware family code, changes only on rework
TTP / behavior Months to years Expensive for the adversary to retrain and retool

Two distinct failure modes hide in this table, and they need different handling:

  • Hashes go stale but never go bad. A SHA-256 of malware is malware forever. Keep it for retro-hunting and forensics indefinitely, just stop expecting it to fire on fresh activity.
  • Network indicators go bad, not just stale. An IP or domain can flip from malicious to benign. This is the class that must be actively expired, because yesterday's C2 can be tomorrow's customer login portal.

The Real Cost of Stale Blocklists

The damage from old network indicators is concrete, not theoretical.

Shared infrastructure false positives. A huge share of malicious hosting sits on shared platforms: CDN edges, cloud load balancers, shared web hosts. Blocking the IP of a phishing page served through a CDN means blocking every other site behind that edge node. Six months later, the phishing page is long gone and you are still dropping traffic to hundreds of legitimate tenants.

Cloud IP recycling. When an attacker's VPS is terminated, the address returns to the provider pool. The next customer to receive it might be a SaaS product your finance team uses. Your firewall does not know that. Your finance team will let you know.

Alert queue pollution. Every stale indicator that still matches something produces triage work. An analyst spends twenty minutes proving that a 2023 Emotet domain now resolves to a parking page. Multiply by thousands of aged indicators and you have built a machine that manufactures false positives on schedule.

Erosion of trust. Once analysts learn that intel-matched alerts are usually wrong, they start closing them on autopilot. That is exactly the reflex that lets the one live indicator slip through.


Confidence Decay Models

The fix is to treat confidence as a function of time, not a constant. Three models cover most needs.


Hard expiry

Every indicator gets a time-to-live at ingestion based on its type. When the TTL lapses, the indicator drops out of blocking and alerting. Simple, predictable, and supported by almost every TIP and SIEM. The downside: a cliff. An indicator is fully trusted on day 29 and gone on day 31.


Linear decay

Confidence declines by a fixed amount per day until it crosses a floor. A domain ingested at confidence 90 losing 3 points per day falls below a blocking threshold of 60 after ten days, and below an alerting threshold of 30 after twenty. Smooth, easy to reason about, easy to implement in a scheduled job.


Exponential decay

Confidence halves every fixed interval, mirroring how sighting probability actually behaves: most indicator matches happen shortly after publication, then tail off fast. MISP implements this pattern as decaying models with a configurable half-life per indicator type. If you run MISP, this is available today without custom code.

Whichever model you choose, one rule overrides it: a fresh sighting resets the clock. If your telemetry or a trusted feed observes the indicator active again, restore confidence to its initial value and restart decay. Aging must reflect the absence of evidence, not just the passage of time.


A Practical Decay Policy

Here is a starting policy a small team can deploy this week. Numbers are deliberately conservative; tune them against your own false-positive data.

Type        Initial  Decay              Block below  Delete/archive
----------  -------  -----------------  -----------  -----------------
URL         90       -10/day            60           14 days
IP          80       -5/day             60           30 days
Domain      85       -2/day             60           90 days
Email       80       -5/day             n/a (alert)  30 days
Hash        95       none               n/a (alert)  never (archive)
Mutex/TTP   90       review at 180d     n/a (hunt)   manual review

Modifiers
  Sighting in own telemetry ......... reset to initial
  Present in 3+ independent feeds ... +10 initial
  Resolves to CDN / shared hosting .. never auto-block, alert only
  KEV-linked campaign indicator ..... halve decay rate

Three details in that policy matter more than the exact numbers:

  1. CDN and shared-hosting indicators never auto-block. Enrich at ingestion, check ASN and hosting type, and route anything on shared infrastructure to alert-only. This is where enrichment pays for itself: pasting an indicator into mlab.sh shows you the ASN, hosting classification, and passive DNS history before you commit it to a blocklist, and the same checks run over the API for automated pipelines.
  2. Expired does not mean deleted. Move aged indicators to an archive tier that supports retro-hunting and incident scoping. During an investigation, a two-year-old C2 domain in proxy logs from the right time window is gold.
  3. The policy needs a feedback loop. Every false positive traced to a stale indicator should shorten the TTL for that type or source. Every true positive on an old indicator should lengthen it. A decay policy that is never adjusted is just a guess with a cron job.

Scoring the Source, Not Just the Indicator

Decay rates should also depend on where the indicator came from. A feed that republishes other feeds with a week of lag deserves a shorter TTL and a lower initial confidence than indicators extracted from your own incident response. Track per-source true-positive and false-positive counts, even roughly. Within a quarter you will know which feeds earn their ingestion cost and which ones only feed the decay pipeline.


Collect indicators like a librarian, expire them like a bouncer. The blocklist that only ever grows is not protecting you, it is aging against you.