Join our Newsletter — 33% off our NHI Course
Home› Guides› OWASP Core Rule Set Guide: Deploy, Tune and…
Guide Web & API Security

OWASP Core Rule Set Guide: Deploy, Tune and Govern CRS Safely

PDF for newsletter subscribers · free to read online

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 27 October 2026 14 min read
On this page

The OWASP Core Rule Set (CRS) protects a large share of the web, yet many deployments run it with thresholds raised, paranoia levels unset or rule exclusions nobody can explain. CRS is a generic attack detection rule set for WAF engines that speak ModSecurity's SecLang, including ModSecurity v2, libModSecurity v3 and OWASP Coraza, and it is also offered inside many CDN and cloud WAF services. This guide goes beyond our general WAF guide into how CRS itself works: rule file structure, anomaly scoring, paranoia levels, rule exclusions, the configuration baseline in crs-setup.conf, who should be allowed to change it and how to log and measure it. It is for engineers who run or tune CRS and for security leads who own WAF change control.

Key takeaways

  • Keep the default thresholds. CRS defaults are an inbound anomaly threshold of 5 and an outbound threshold of 4; the CRS documentation warns that raising them permanently lets a substantial number of attacks bypass the rule set.
  • Paranoia level and threshold are separate controls. The paranoia level decides how many rules run; the threshold decides how many matches are needed to block. Do not trade one for the other.
  • Tune with exclusions, never by editing rules. Use configure-time or runtime rule exclusions, as narrow as possible, placed in the correct file so they survive upgrades.
  • Stay on a supported release. The project supports the two latest point releases and a v4.25.x LTS line until Q3 2027; the v3.3.x branch reached end of life in Q3 2026.
  • Treat WAF configuration as privileged access. Whoever can add an exclusion or set the sampling percentage to 0 can switch protection off, so change rights and API tokens need the same control as production admin access.

What CRS is: engines, versions and support

CRS is an OWASP project that publishes rules, not a WAF engine. It runs on engines compatible with a subset of SecLang, and the order of inclusion is always the engine configuration (modsecurity.conf or coraza.conf), then crs-setup.conf, then the rules/*.conf files.

Engine or platformCRS compatibility (per CRS documentation)Notes
ModSecurity v2 (Apache)Reference implementation; passes 100% of CRS unit testsProject now under the OWASP Foundation (transferred January 2024)
ModSecurity v3 (libModSecurity, mainly Nginx)Fails 2 to 4% of CRS unit tests due to bugs and implementation gapsUsed in production with Nginx; CRS recommends v2 with Apache where possible
OWASP Coraza (Go)Passes 100% of the CRS v4 test suiteRuns on Caddy and Traefik, with an HAProxy SPOA connector
Cloud and CDN WAFsUsually a subset of CRS rules and features, often transposed into the provider's own engineCheck which CRS version is offered and whether paranoia level and thresholds can be set

Release status as checked in the CRS repository on 27 October 2026: the latest release is v4.30.0 (2 October 2026), the security policy supports the two latest point releases plus the v4.25.x LTS line until Q3 2027, and releases are GPG signed. The LTS line receives only security fixes, critical regression fixes and critical false positive fixes. Note one naming trap the CRS documentation calls out: a cloud provider's managed rule group named "core rule set" is not necessarily based on OWASP CRS. See the Web Application Firewall Guide for WAF deployment models and the wider rule set choice.

How the rule set is organised

Rules live in numbered files; the number is also the rule ID prefix (for example rule 920160 is in the protocol enforcement file). CRS reserves IDs 900,000 to 999,999; IDs 1 to 99,999 are reserved for local use, which is where your own exclusions and custom rules belong.

File rangePurposeExamples
REQUEST-900, RESPONSE-999 (.example)Your exclusion rules before and after CRSApplication-specific exclusions
REQUEST-901, 905Initialisation and common exceptionsDefault values, sampling (rules 901410, 901450)
REQUEST-911, 913, 920, 921, 922Method enforcement, scanner detection, protocol enforcement, protocol attacks, multipart attacksNon-numeric Content-Length (920160), charset allow-list (920480)
REQUEST-930 to 934Local and remote file inclusion, remote code execution, PHP, generic attacksAI coding assistant directories such as .claude/ and .cursor/ in the restricted paths data used by the LFI rules
REQUEST-941 to 944XSS, SQL injection, session fixation, Java attacksMore than 50 rules cover SQL injection
REQUEST-949Inbound blocking evaluationCompares the inbound anomaly score with the threshold
RESPONSE-950 to 956Data leakage (SQL, Java, PHP, IIS, Ruby) and web shellsError messages and web shell output in responses
RESPONSE-959, 980Outbound blocking evaluation and correlationOutbound threshold check

Rules carry tags such as attack-protocol, paranoia-level/1 and capec identifiers, which is what makes tag-based exclusions and reporting possible.

How decisions are made: anomaly scoring and paranoia levels

In the default anomaly scoring mode, detection is decoupled from blocking. Each matching rule adds to a transaction score (a critical match adds 5 by default); after all request rules run, rule file 949 blocks the request if the inbound score meets or exceeds the inbound threshold; after response rules, file 959 does the same for the outbound score, stopping the response even though the backend has already processed the request. Self-contained mode, the CRS 2 behaviour, acts on the first match and logs only the first threat.

Paranoia levelCRS project descriptionTypical fit
PL 1Baseline security with minimal false positives; CRS for everybody on the internetBrochure sites, low-risk services
PL 2Adequate when real user data is involved; expect false positives to tuneOnline shops, applications with personal data
PL 3Online banking level; false positives accepted and expectedFinancial and sensitive data
PL 4For "crown jewels", at your own risk, with many false positivesNarrow, high-value admin endpoints

The CRS documentation suggests an internal policy mapping data risk class to a minimum paranoia level (no personal data to PL 1, personal data to PL 2, sensitive financial data to PL 3). To raise the level on a tuned system without reducing protection, set the detection paranoia level (tx.detection_paranoia_level) one step above the blocking paranoia level (tx.blocking_paranoia_level): higher-level rules then log without contributing to blocking, you tune the new false positives, and only then raise the blocking level.

How identity and access work in a CRS deployment

CRS has no user accounts of its own: it is configuration files loaded by an engine, or a rule set exposed through a cloud console. Access control therefore lives in three places, and each needs an owner.

  • Configuration source: crs-setup.conf, the 900 and 999 exclusion files and any plugins, ideally in a version-controlled repository with mandatory review. Anyone with merge rights can disable protection.
  • Engine host or ingress: the web server, reverse proxy or Kubernetes ingress controller that loads the rules. Shell or cluster-admin access here bypasses repository review entirely.
  • Managed console or API: where CRS runs inside a CDN or cloud WAF, the provider's IAM roles decide who can change paranoia level, thresholds and exclusions.

CRS also inspects identity-related traffic. The session fixation rules (file 943) look for cookie values being set in HTML and session ID parameter names arriving with an off-domain or missing referer, restricted header lists cover method override headers such as X-HTTP-Method-Override, and the restricted files data now blocks requests for AI coding assistant directories and configuration files that can hold API keys. None of this replaces authentication controls in the application.

Admin roles and privileged access

RoleShould be able toShould not be able to
WAF rule authorPropose exclusions and custom rules in the local ID range through a pull requestMerge their own changes or edit CRS rule files directly
WAF approver (security)Approve exclusions, threshold and paranoia level changesDeploy outside the pipeline
Platform operatorDeploy approved releases and roll backChange thresholds or sampling outside change control
Application ownerRequest exclusions with evidence (rule ID, parameter, URI)Approve exclusions for their own application
Break-glassSet tx.sampling_percentage to 0 or switch the engine to detection only during an outageLeave the change in place without a time limit and review

Map these roles to least privilege (NIST SP 800-53 AC-6) and configuration change control (CM-3). See the Privileged Access Management Guide for how to put admin consoles and hosts behind just-in-time access.

Integrations, API tokens and service accounts

Modern CRS deployments are driven by automation: CI pipelines that run the CRS regression tests, infrastructure as code that pushes WAF policies to a CDN, and log shippers that send audit logs to a SIEM. Each of these holds a non-human credential.

  • Deployment tokens: scope CDN or cloud WAF API tokens to the WAF policy resources only, store them in a secrets manager, and rotate them. A token that can edit WAF policy can also delete it.
  • Pipeline identities: prefer short-lived workload identity federation for the pipeline that applies WAF changes over static keys. See the Secrets Management Guide.
  • Log shipping accounts: audit logs contain request bodies, cookies and sometimes credentials. The log shipper's account needs write access to the log store, not read access to everything else.
  • Release verification: verify the GPG signature of each CRS release before deployment so a tampered rule set cannot enter the pipeline.

WAF providers are themselves a target. In the Imperva Breach 2019, an administrative AWS API key on an exposed internal instance gave an attacker access to a database snapshot that included Cloud WAF customers' API keys and SSL certificates for a subset of accounts. Rotate any credentials you have given a WAF provider when the provider reports an incident.

Rolling out and tuning CRS

  1. Baseline the engine: load the engine's recommended configuration, then crs-setup.conf, then the rules, on a supported engine version.
  2. Choose the start mode: either use sampling (rule 900400, tx.sampling_percentage) to apply CRS to 1% of traffic and increase in steps to 100%, or run in blocking mode from the start with very high anomaly thresholds and lower them iteratively, the method CRS documentation describes.
  3. Start at PL 1 unless a risk class mapping requires more, and set the detection paranoia level one step higher to see what is coming.
  4. Tune false positives from logs: identify rule ID, variable and URI, then write the narrowest exclusion. Prefer removing one variable from one rule for one location (ctl:ruleRemoveTargetById) over removing a rule globally (SecRuleRemoveById). Use the 1 to 99,999 ID range.
  5. Place exclusions correctly: configure-time exclusions must come after CRS is included (the RESPONSE-999 file); runtime exclusions go before CRS (the REQUEST-900 file). Misplaced exclusions silently do nothing.
  6. Use plugins for application exclusions: CRS v4 ships rule exclusion plugins for common applications, loaded before and after CRS, and they can be enabled per host or application.
  7. Lower thresholds to defaults (5 inbound, 4 outbound) and keep them there.
  8. Test before each upgrade against recorded traffic or the CRS test suite, then upgrade in a canary.

Rollback: the fastest documented rollback is setting tx.sampling_percentage to 0, which bypasses the WAF for every request (and any other rule sets loaded in the same engine). Use it only as a time-limited break-glass action with an incident ticket.

Hardening baseline: crs-setup.conf settings that matter

Setting (rule ID)VariableBaseline
Paranoia level (900000)tx.blocking_paranoia_level, tx.detection_paranoia_levelSet explicitly per application risk class
Anomaly thresholds (900110)tx.inbound_anomaly_score_threshold, tx.outbound_anomaly_score_threshold5 and 4; raise only temporarily during tuning
Early blocking (900120)tx.early_blockingOff by default; when enabled, scores are also evaluated at the end of phases 1 and 3 so blocking happens earlier
Allowed methods (900200)tx.allowed_methodsDefault GET HEAD POST OPTIONS; add PUT, PATCH or DELETE only for APIs that need them
Allowed content types (900220)tx.allowed_request_content_typeRestrict to what the application accepts
Allowed HTTP versions (900230)tx.allowed_http_versionsRemove versions you do not serve
Restricted extensions and headers (900240, 900250)tx.restricted_extensions, tx.restricted_headers_basicKeep defaults; add backup and config extensions specific to your stack
Argument and upload limits (900300 to 900350)tx.max_num_args, tx.arg_length, tx.max_file_size and othersSet from real application limits
Sampling (900400)tx.sampling_percentage100 in steady state

Engine settings such as SecRuleEngine, SecRequestBodyAccess and SecAuditEngine are not set by CRS; they belong to the engine configuration and must be hardened there. Without request body access, CRS cannot inspect POST bodies at all.

Logging and detection

By default CRS logs to the web server error log and writes detailed transactions to the engine audit log. Ship both to the SIEM, alert on configuration changes, and protect the audit log because it holds request payloads.

  • Blocked requests by rule ID and paranoia level: spikes in one rule usually mean a new false positive or a targeted attack.
  • Rule 901450 entries: these show requests that bypassed CRS because of sampling; any in steady state mean sampling is not at 100.
  • Configuration drift: alert when thresholds, paranoia level or sampling differ from the approved baseline.
  • Exclusion inventory: number of active exclusions, their age and owner.

Metrics: percentage of in-scope applications at their target paranoia level; percentage running default thresholds; false positive rate per thousand requests after tuning; median time to approve an exclusion request; days behind the latest supported CRS release; exclusions older than 12 months without review.

In framework terms, CRS supports NIST SP 800-53 SC-7 Boundary Protection, SI-10 Information Input Validation and SI-4 System Monitoring; NIST CSF 2.0 PR.IR-01 and DE.CM-01; and the MITRE D3FEND technique Inbound Traffic Filtering. It is a mitigation layer against MITRE ATT&CK T1190 Exploit Public-Facing Application, not a fix for the vulnerability. For time-bound protection while a patch is pending, see the Virtual Patching and Compensating Controls Guide.

Common misconfigurations

  • Permanently raised thresholds: a threshold of 10 or more means attack categories covered by a single rule can never block.
  • Editing CRS rule files: changes are lost on upgrade and cannot be audited; use exclusions and the local ID range instead.
  • Global rule removal for one false positive: removing an SQL injection rule everywhere because one search field triggers it.
  • Exclusions in the wrong file: configure-time directives placed before the CRS include have no effect.
  • Running end-of-life releases: v3.3.x and older are no longer supported, and recent releases have fixed bypasses (v4.30.0 included fixes for path-based command injection and charset allow-list bypasses).
  • Assuming a managed "CRS" is full CRS: many integrations offer a subset of rules and do not expose paranoia levels or thresholds.
  • Detection only forever: leaving the engine in detection-only mode after the pilot provides logging but no protection.

Practitioner checklist

  • Confirm every CRS deployment is on a supported release or the v4.25.x LTS line, and verify release signatures.
  • Record the engine and version for each deployment and note known CRS compatibility gaps.
  • Set blocking and detection paranoia levels per application from a written risk class mapping.
  • Restore default anomaly thresholds (5 inbound, 4 outbound) after tuning, and alert on any change.
  • Keep all exclusions in version control, in the correct file, in the local ID range, each with an owner and ticket.
  • Restrict who can merge WAF changes, deploy them and use break-glass sampling or detection-only switches.
  • Scope, vault and rotate API tokens used by pipelines and log shippers.
  • Ship error and audit logs to the SIEM and protect them as sensitive data.
  • Run the CRS test suite or recorded traffic before upgrades and deploy through a canary.
  • Review the exclusion inventory every quarter and remove stale exclusions.

Standards and references

Related NHI Mgmt Group resources: Web Application Firewall Guide · Virtual Patching and Compensating Controls Guide · WAF and WAAP Buyer's Guide · SQL Injection Prevention Guide · Web Shell Response Playbook

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 27 October 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.