SentrySentry
Rules Engine

Default Rule Packs

The current catalog of pre-configured packs shipped with Sentry

Default Rule Packs

Packs are sets of pre-built rules in crates/sentry-core/src/packs.rs that join the ruleset at startup. Each pack has a PackMode: shadow (log only), enforce (act) or off (rules not loaded). The canonical list is all_pack_names; default modes come from build_default_ruleset_with.

Overview

PackDefaultIn shadowIn enforcePriorityParams
sensitive_pathsenforceLogBlock5—
host_allowlistoffLogBlock8domains
crawlers_badshadowLogBlock10—
country_blocklistoffLogBlock10countries
http_anomalyshadowLogBlock12—
empty_uashadowLogChallenge15—
rate_scanshadowLogRateLimit15—
vpn_proxyshadowLogChallenge20—
torshadowLogBlock20—
crawlers_goodoffAllowAllow2–3—

Notes:

  • sensitive_paths is the only pack that ships in enforce — access to .env/.git/.ssh is statistically always malicious.
  • crawlers_good produces Allow rules in any active mode (the mode only turns the pack on/off); it ships off by default.
  • Unknown mode strings become off (PackMode::parse).
  • sentry rules packs lists the current state of every pack.

sensitive_paths (default: enforce)

Single source of truth: lists::SENSITIVE_PATHS — the same table feeds the pack, the SensitivePath heuristic and the Aho-Corasick prefilter literals. Each pattern becomes a case-insensitive path regex rule (evaluated over the URL-decoded path).

Covered categories:

  • Dotfiles and secrets — /.env, /.git, /.svn, /.hg, /.bzr, /.ssh, /.aws, /.gcp, /.azure, /.kube, /.docker, /.terraform, /.npmrc, /.pypirc, /.netrc, /.htpasswd, /.DS_Store.
  • Admin panels — wp-admin, wp-login.php, phpmyadmin, pma, adminer, wp-content, /manager/html (Tomcat), wp-includes/*.php.
  • Server status — server-status, server-info, nginx-status, fpm-status.
  • Spring Boot — /actuator/env, /actuator/heapdump, /actuator/threaddump.
  • Backups and artifacts — extensions .sql, .bak, .backup, .old, .swp, .orig, .save.
  • Known CVE probes — Laravel _ignition/execute-solution, PHPUnit eval-stdin.php, Exchange Autodiscover.xml and /ecp/current/exporttool, MobileIron /mifs/.;/services/logservice, Telerik WebResource.axd, GPON /gponform/diag_form, /restapi/logoncustomization, /hnap1, Fortinet /remote/fgt_lang.

The pack also ships an allow rule at priority 1 for /.well-known/security.txt (RFC 9116), so the public responsible-disclosure document is never blocked.

[[rules.pack]]
name = "sensitive_paths"
mode = "enforce"   # default — drop to "shadow" if your site really serves these paths

host_allowlist (default: off)

Blocks requests whose Host header is not one of the configured domains — including Host-less requests (bare-IP scans and IDN homograph attempts). Implemented as NOT header.host regex ... (host_allowlist_rules).

[[rules.pack]]
name = "host_allowlist"
mode = "enforce"

[rules.pack.params]
domains = ["example.com", "www.example.com"]

crawlers_bad (default: shadow)

A single UA-regex rule (bad_crawler_rules) aggregating pentest tools and scanners (sqlmap, nikto, nmap, masscan, zgrab, nessus, gobuster, ffuf, nuclei, wfuzz…), script HTTP clients (python-requests, go-http-client, curl/…) and aggressive SEO/data bots (semrush, ahrefs, mj12bot, bytespider…).

[[rules.pack]]
name = "crawlers_bad"
mode = "enforce"

crawlers_good (default: off)

Allow rules by UA for legitimate bots (good_crawler_rules). With [bot_verification] enabled = true (F7.7) the pack splits in two:

  • crawlers_good_verified (priority 2) — rDNS-verifiable engines (Googlebot, Bingbot, Slurp, Baiduspider, YandexBot) with the extra bot_verified = "true" condition: a spoofed UA earns no allow.
  • crawlers_good_unverified_ok (priority 3) — engines that cannot be verified via rDNS (DuckDuckBot, facebookexternalhit, Twitterbot, LinkedInBot, Applebot, Puppeteer, WhatsApp, TelegramBot, Discordbot, W3C_Validator, curl/8, Go-http-client/1.1) keep the plain UA allow.

Without bot verification the pack falls back to a single rule with the combined list.

[[rules.pack]]
name = "crawlers_good"
mode = "enforce"   # action is always Allow — the mode only turns the pack on

empty_ua (default: shadow)

Empty User-Agent (UserAgent equals "") → Challenge when enforced (empty_ua_rules). Rare in legitimate browser traffic.

http_anomaly (default: shadow)

Rare methods TRACE and CONNECT → Block when enforced (http_anomaly_rules), two priority-12 rules.

vpn_proxy (default: shadow)

reputation = "vpn" → Challenge when enforced (vpn_proxy_rules). Only works for real with an IP feed of tier vpn configured (presets open_source_vpn_ips / anti_vpn) — without a feed the tier is never assigned and the rule never fires.

tor (default: shadow)

reputation = "tor" → Block when enforced (tor_rules). Requires the tor_exit preset (or an equivalent feed) — without it, it never fires.

rate_scan (default: shadow)

The rate_scan_404 rule (rate_scan_rules): status=404 AND rate 10/60s per_ip → RateLimit when enforced (directory brute-force). The Status(404) filter is real — the rate window only counts 404s. Requires the daemon's rate-limit backend.

country_blocklist (default: off)

country = <code> → Block when enforced, for the configured list (country_blocklist_rules). ISO 3166-1 alpha-2 codes, case-insensitive compare. Requires the countries param — without it the pack generates no rules.

[[rules.pack]]
name = "country_blocklist"
mode = "enforce"

[rules.pack.params]
countries = ["RU", "CN", "KP"]

Datasets and reputation feeds

Beyond the packs, [[rules.feeds]] generates synthetic feed:<name> rules (priority 50, source Feed) via feed_rule and dataset_rule:

kindWhat it generatesDefault action
ipEnrichment (ReputationStore longest-prefix) + a synthetic rule only if action is set(no rule)
user_agentOne UA rule — the whole list as a case-insensitive literal alternation (cap MAX_DATASET_ENTRIES = 5000)log
pathSame, over the pathlog
ja3RuleMatch::Ja3In — a hash set (TLS handshake events only)log

Fields: name, url (http/https with SSRF guard), kind, tier (ip only; default malicious), action, refresh_hours (default 24), headers_env (authenticated headers), enabled (default true).

[[rules.feeds]]
name = "spamhaus_drop"
url  = "https://www.spamhaus.org/drop/drop.txt"
tier = "malicious"
refresh_hours = 24
action = "block"          # without action: enrichment only (tor/vpn_proxy start working)

[[rules.feeds]]
name = "bad_bots_ultimate"
kind = "user_agent"
url  = "https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/_generator_lists/bad-user-agents.list"
refresh_hours = 24
action = "log"            # start in shadow; flip to "block" after auditing

[[rules.feeds]]
name = "probe_paths"
kind = "path"
url  = "https://example.invalid/probe-paths.txt"
refresh_hours = 24
action = "challenge"

[[rules.feeds]]
name = "abuseipdb_blacklist"
url  = "https://api.abuseipdb.com/api/v2/blacklist?confidenceMinimum=90&plaintext=true"
tier = "malicious"
refresh_hours = 24
headers_env = { Key = "SENTRY_ABUSEIPDB_KEY" }

Presets — instead of hand-writing feeds, [rules] feed_presets = ["tor_exit", "firehol_level1", "proxy_list", "open_source_vpn_ips", "anti_vpn"] enables curated public blocklists; preset feeds block by default — enable one only if you accept banning those ranges (e.g. VPN users).

DB-backed datasets (F7.7) — the Postgres equivalent of the user_agent/path/ja3 feeds, no TOML needed: sentry datasets import <file|url> --kind user_agent --name <name> [--action block], plus list|enable|disable|delete|fetch. Rules get the dataset:<name> id and are hot-reloaded (together with the prefilter literals) over the sentry_datasets_changed channel. Use datasets for lists that change without a deploy; use [[rules.feeds]] for lists versioned in config.

On this page