About
A Web Application Firewall (WAF) HTTP filter plugin that provides layer 7 security for web applications using the Coraza WAF engine.
Features
This plugin provides comprehensive web application security:
- OWASP CRS (Core Rule Set): Built-in protection against common web attacks
- Request inspection: Analyzes HTTP requests for malicious patterns and anomalies
- Response inspection: Examines HTTP responses to prevent data leakage
- Flexible rule engine: Supports custom security rules and policies
- Multiple operation modes: Detection-only or active blocking modes
- Detailed logging: Comprehensive audit logging of security events
Security Rules
The WAF comes with support for OWASP CRS, formerly known as ModSecurity Core Rule Set (CRS), as well as
some recommended configurations and allows custom rule configuration for specific security requirements.
It is recommended to review the provided configuration files before deploying, to ensure they align with
the target environment and the expected security posture.
To use the bundled rules, you can include them with the Coraza Include directives as shown in this example:
{
"directives": [
"Include @coraza.conf",
"Include @crs-setup.conf",
"Include @owasp_crs/*.conf"
]
}Available special names are:
| Name | Aliases | Description |
|---|---|---|
@coraza.conf-recommended |
— | Coraza upstream configuration file example |
@coraza.conf |
@recommended.conf, @recommended-conf |
Coraza configuration file tailored for Coraza dynamic module implementation |
@crs-setup.conf.example |
— | CRS upstream configuration file example |
@crs-setup.conf |
@crs-setup-conf |
CRS configuration file tailored for Coraza dynamic module implementation |
@owasp_crs/ |
— | CRS rules directory |
Note: Aliases are provided for backward compatibility, but are deprecated and may be removed in future releases. It is recommended to use the primary names for new configurations.
To create custom rules, refer to the SecLang reference docs.
Mode
The optional mode setting controls which parts of the HTTP exchange are evaluated by the WAF.
Use the narrowest mode that matches your policy to avoid unnecessary processing.
REQUEST_ONLY(default): Inspect request headers, body, and trailers only. This is the best choice for typical OWASP CRS deployments that focus on inbound attack detection.RESPONSE_ONLY: Inspect response headers, body, and trailers only. Use this when you only need outbound inspection, such as detecting sensitive data in responses.FULL: Inspect both request and response phases. Use this when your rules need visibility into both directions of traffic.
{
"mode": "FULL",
"directives": [
"Include @coraza.conf",
"Include @crs-setup.conf",
"Include @owasp_crs/*.conf"
]
}Note: mode only decides which request and response phases are passed to Coraza. It does not enable body access
by itself. For example, FULL allows response-phase evaluation, but response body inspection still requires
directives such as SecResponseBodyAccess On.
Metadata
The plugin emits the following filter dynamic metadata when requests are blocked by the WAF:
| Namespace | Key | Description |
|---|---|---|
io.builtonenvoy.waf |
block_phase |
Phase in which the requests has been blocked. See the execution flow for details on the possible values. |
io.builtonenvoy.waf |
block_rule |
ID of the rule that triggered the block. |
Metrics
The extension exposes the following metrics:
| Metric | Tags | Type | Description |
|---|---|---|---|
waf_tx_total |
- | Counter | Total amount of transactions processed by the WAF. |
waf_tx_blocked |
authority, phase, rule_id |
Counter | Total amount of transactions blocked by the WAF. The rule_id will not be set if the request is not blocked by a concrete rule but by a WAF internal error. |
Per Route Configuration
The extension supports per-route configuration, allowing you to specify different WAF rules and policies for different routes in your application. This is useful for tailoring security measures to specific endpoints or services.
The per-route configuration share the same format as the extension configuration and see Envoy's Dynamic Per Route Configuration for more details on how to set it up.
Usage Examples
SQL Injection Protection
The following example demonstrates how to run the WAF plugin with recommended OWASP CRS rules and test SQL injection protection by sending a malicious payload that should be blocked by the WAF.
By default WAF is configured in DetectionOnly mode, which means it will only log detected attacks without
blocking them. To enable active blocking, this example sets SecRuleEngine On in the configuration. It also
sets SecResponseBodyAccess Off to disable response body inspection as it's not needed for the example.
# Start WAF with recommended OWASP CRS rules and enforcement enabled
boe run --extension coraza-waf --config '
{
"directives": [
"Include @coraza.conf",
"SecRuleEngine On",
"SecResponseBodyAccess Off",
"Include @crs-setup.conf",
"Include @owasp_crs/*.conf"
]
}'
# Try sending a SQL injection payload and see the request rejected
curl -v http://localhost:10000/post -X POST --data "1%27%20ORDER%20BY%203--%2B"
< HTTP/1.1 403 Forbidden
< content-length: 22
< content-type: text/plain
< date: Thu, 12 Feb 2026 10:28:16 GMT
< server: envoy
< CRS plugin from local filesystem
The following example demonstrates how to load a CRS plugin from the local filesystem and run the WAF plugin with recommended OWASP CRS rules.
It first downloads the WordPress rule exclusions plugin to a local file, enables blocking with
SecRuleEngine On, and includes the plugin using Include /tmp/wordpress-plugin.conf. The same SQL injection
payload that would normally be blocked is no longer blocked because the plugin excludes this specific attack
vector.
# Retrieve the file
curl https://raw.githubusercontent.com/coreruleset/wordpress-rule-exclusions-plugin/refs/heads/master/plugins/wordpress-rule-exclusions-before.conf -o /tmp/wordpress-plugin-before.conf
# Start WAF with recommended OWASP CRS rules, enforcement enabled, and loading the plugin file
boe run --extension coraza-waf --config '
{
"directives": [
"Include @coraza.conf",
"SecRuleEngine On",
"SecResponseBodyAccess Off",
"Include @crs-setup.conf",
"Include /tmp/wordpress-plugin-before.conf",
"Include @owasp_crs/*.conf"
]
}'
# Try sending a SQL injection payload and see the request rejected
curl -v "http://localhost:10000/wp-json/wp/v2/posts/1" -X POST -H "Content-Type: application/json" --data '{"content": "SELECT * FROM users WHERE id=1"}'
# The request is no longer blocked by the WAF as the rules in the plugin file are excluding the specific attack vector from being detected
< HTTP/1.1 404 Not Found
< date: Wed, 01 Apr 2026 13:10:33 GMT
< content-type: text/html
< content-length: 233
< server: envoy
...