Curated feed¶
The Exosys Curated Domain Lists are a signed, on-box category feed — malware, phishing, gambling, social media, streaming and 60+ more — that ships with every edition and lets you write .policy rules against a category instead of maintaining your own domain lists. This page gets it running on a fresh install and shows how to write policy against it. For the full attribute grammar see Managed categories; for every [feed] config key see engine reference.
How it's delivered¶
The feed is a single signed file (.egsf, /var/lib/enforcegate/managed.egsf by default) loaded into memory at engine boot. There is no per-request cloud lookup — matching a URL against a category never leaves the box, and a deployment stays fully air-gapped after the file is in place. See architecture for how the file itself is produced and verified.
Getting that file onto disk has two paths:
- Automatic delivery — the engine polls the Exosys Control Server for newer feed generations itself and hot-swaps them in with no restart. This is the fastest path to a working feed on a fresh install and the one below.
- Manual file drop — for air-gapped deployments with no outbound path to the Control Server at all. Contact support to obtain a feed file, copy it to the configured path, then apply it with
request feed reload— no engine restart needed.
Enabling on a fresh install¶
A fresh install needs nothing done — from 2026.56.0, automatic delivery ships on by default. The engine primes its first poll about 90 seconds after boot; on a fresh install there is no local file yet, so if that first attempt doesn't land a feed it retries every 60 seconds (up to five attempts) rather than waiting out the full interval, so you typically have a feed within a few minutes of first boot. Confirm it loaded:
> show feed
Feed loaded: yes
Generation: 3
Sealed at: 2026-09-09 14:22:10 UTC (1789054930) — 3m ago
Categories: 61
Domains indexed: 42118003
Entitlement: licensed
Loaded from: control server (applied in memory — no on-disk copy)
Feed file: /var/lib/enforcegate/managed.egsf (offline drop path — not currently in use)
Auto-update: on
Last checked: 2026-09-09 14:22:10 UTC — 3m ago (updated to generation 3)
Last installed: 2026-09-09 14:22:10 UTC — 3m ago (generation 3 (61 categories, 42118003 domains))
Next check: 2026-09-09 20:28:10 UTC — in 5h 57m
Entitlement: licensed confirms the feed is active for your licence. See show feed for what the other entitlement states mean. Don't want to wait even a few minutes? Pull a generation on demand:
Upgrading an existing deployment does not change this. If you installed before 2026.56.0, your [feed] section already has auto_update written to disk (false, by default at the time), and an upgrade never overwrites a value that's already there — the new on-by-default behaviour only applies to a [feed] section that doesn't exist yet. Enable it explicitly if you want it:
$ eghost feed auto-update on
Automatic feed delivery: off -> on. Recreate the engine to apply? [y/N]: y
See the full enabling automatic updates reference for every tuning knob, and eghost feed for the verb.
Air-gapped deployments
Turn automatic delivery off — eghost feed auto-update off, or ENFORCEGATE_FEED_AUTO_UPDATE=false in .env — and use the manual file-drop path above instead. Nothing about writing policy against categories changes; the feed just arrives by hand rather than over the network.
Default update interval¶
With automatic delivery on, the engine checks for a newer generation every 6 hours (poll_interval_seconds, default 21600), spread by up to ±10 minutes of jitter (poll_jitter_seconds, default 600) so a fleet of engines doesn't hit the Control Server in the same instant. Both are .env-overridable — see [feed] for the full key list. A poll that fails for any reason — network blip, an unreachable Control Server — leaves the currently-loaded feed enforcing exactly as before; it is never dropped.
Categories¶
match-category: gates a rule on one or more of these tokens. Coverage grows over time as new categories clear our precision bar for shipping, so treat this as the vocabulary rather than a promise every token is populated on your loaded generation — show feed reports your generation's live category count, and show feed lookup <domain> tells you exactly what the feed says about one domain before you write a rule against it.
| Group | Categories |
|---|---|
| Security threats | malware, phishing, cryptojacking, crypto_scam |
| Filter evasion & dual-use tools | proxy_evasion, hacking, remote_access |
| Disposable / abuse-prone infrastructure | disposable_infra, file_sharing, url_shortener |
| Adult & mature | adult, dating, gambling, drugs, alcohol_tobacco, weapons |
| Legal but high-liability | piracy, violence, hate_extremism, ai_abuse |
| Controversial / advocacy | abortion, politics, political_extremism, cult_sect |
| Privacy & advertising | data_broker, advertisements |
| Uncertain | suspicious, gray_market |
| Business & general-interest | finance, search_engines, business, government, technology, health, education, travel, job_search, defense, aviation, ai_tools, history, associations |
| Lifestyle & entertainment | social_networks, streaming, podcasts, games, shopping, webmail, news, sports, religion, cryptocurrency, outdoor_recreation, supplements, pharmacy, chat, music, events, blogs |
| No real content | parked, unknown |
Writing policy against a category¶
A rule matches when the requested domain carries any of its listed categories. Put category rules early in your rule set (lower file-number prefix) if you want them to win over broader match-domain-list or match-uri-prefix rules — see rule files and evaluation order.
Single category:
block-gambling: {
match-category: gambling
action: deny
description: Exosys curated feed — gambling
}
Multiple categories on one rule — use this when several categories should get the same treatment, rather than duplicating the rule:
deny-security-threats: {
match-category: [ "malware", "phishing", "cryptojacking", "crypto_scam" ]
action: deny
description: Exosys curated feed — known-bad infrastructure
}
Different categories, different actions — this is the common real-world shape: hard-block what's unambiguous, and gate the judgment calls behind a warning instead:
deny-security-threats: {
match-category: [ "malware", "phishing", "cryptojacking", "crypto_scam" ]
action: deny
description: Known-bad — no exceptions
}
warn-gambling-drugs: {
match-category: [ "gambling", "drugs", "alcohol_tobacco" ]
action: warn
description: Proceed with acknowledgement
}
deny-social-during-hours: {
match-category: social_networks
time-window: "Mon-Fri 09:00-17:00"
action: deny
description: Social media blocked during business hours
}
That last rule composes match-category: with time-window: — every other rule dimension (match-client-ip:, match-method:, ack_scope:) composes the same way, and all four actions (permit / deny / warn / aup) are available.
Tuning confidence and freshness per rule¶
Every category entry in the feed carries a confidence score and an age (how long ago it was classified). The [feed] block sets the deployment-wide floor for both — see min_confidence / max_age_bucket / unknown_age — and a rule can tighten either one for itself with min-confidence: and max-age:. A rule can only tighten, never loosen below the deployment floor.
deny-gambling-strict: {
match-category: gambling
min-confidence: 2
max-age: 2
action: deny
description: Only act on gambling classifications we're most sure of and were made recently
}
| Attribute | Range | Meaning |
|---|---|---|
min-confidence: |
0–3 |
Reject a categorisation below this confidence bucket. 0 = 0.80–0.90, 1 = 0.90–0.95, 2 = 0.95–0.99, 3 = 0.99+. Higher means fewer false positives, at the cost of missing some genuine matches. |
max-age: |
0–5 |
Reject a categorisation older than this bucket. 0 = under 1 day, 1 = under 7 days, 2 = under 30 days, 3 = under 90 days, 4 = under 365 days, 5 = any known age (the default — no staleness restriction). |
Omit either attribute to inherit the [feed] global default for that threshold — min-confidence and max-age are independent, so tightening one does not require setting the other.
See also¶
- Managed categories — the full
match-category:grammar reference. [feed]— every configuration key, includingunknown_ageand the automatic-delivery tuning knobs.show feed/show feed lookup/request feed reload— inspecting and applying the loaded feed.- Policy recipes — more drop-in
.policyexamples.