Files
smallwebwaf/docs/rules.md
T
sneak 3543a9f616
check / check (push) Successful in 3m15s
Remove what is about deploying behind Gitea (closes #209)
Delete the Gitea compose setup, its document, its two scripts and their
make targets. Documents and tests no longer use Gitea as the example
deployment. The Core Rule Set exclusions for Gitea's false positives in
internal/waf stay, with their comments and tests.

Model: opus-5-5
2026-11-07 02:01:53 +00:00

2.9 KiB

Rule files

The format of a rule file, and the default file the image ships. "Rule files" in SPEC.md says how the files are read, watched and mounted, and what each action leads to.

The format

A rule is a line of four fields separated by spaces or tabs: an id, a target, an action and a regex. The regex runs to the end of the line. Blank lines and lines starting with # are ignored.

# id           target      action  regex
env-file       path        ban     (?i)^/\.env(\.[a-z]+)?$
scanner-agent  user_agent  ban     (?i)\b(sqlmap|nikto|nuclei|wpscan)\b
  • The id is letters, digits, - and _, unique across all files. The log line, the metrics, the alerts and a ban's notes name the rule by it.
  • The target is what the regex is matched against:
    • path: the path without the query;
    • uri: the path and the query together;
    • query: the query as sent;
    • method, host, user_agent and referer;
    • header:<Name>: any one request header but Host and Transfer-Encoding.
  • The action is log, block or ban.
  • The regex is in Go's syntax, RE2. It matches anywhere in the target unless anchored with ^ and $. (?i) at its front makes it ignore case.

The default file

The image ships one file, share/rules.d/00-default.rules, installed as /etc/smallwebwaf/rules.d/00-default.rules:

# 00-default.rules: probes no real visitor sends, anchored at the site root

# id             target      action  regex
env-file         path        ban     (?i)^/\.env(\.[a-z]+)?$
vcs-dir          path        ban     (?i)^/\.(git|svn|hg|bzr)(/|$)
secrets-dir      path        ban     (?i)^/\.(aws|ssh|docker|kube)/
secret-file      path        ban     (?i)^/\.(htpasswd|htaccess|npmrc|netrc|pgpass|git-credentials|bash_history|DS_Store)$
editor-dir       path        ban     (?i)^/\.(vscode|idea)/
backup-file      path        ban     (?i)^/[^/]+\.(php(\.[a-z0-9]+|~)|sql(\.[a-z0-9]+)?)$
log-file         path        ban     (?i)^/(debug|error|access)\.log$
compose-file     path        ban     (?i)^/(docker-)?compose\.ya?ml$
php-shell        path        ban     (?i)^/(shell|c99|r57|wso|alfa)\.php$
scanner-agent    user_agent  ban     (?i)\b(sqlmap|nikto|nuclei|masscan|zgrab|wpscan)\b
path-traversal   uri         block   (\.\./){2,}
empty-agent      user_agent  log     ^$

A file of your own

servewaf reads the rule files in its own container. Rules of your own go in a file named to sort after the default, such as 50-site.rules:

# 50-site.rules: WordPress probes, which this site never serves
wp-probe         path        ban     (?i)^/(wp-login\.php|xmlrpc\.php|wp-admin/)

A Dockerfile built on the smallwebwaf image, for servewaf to run from, adds it:

COPY 50-site.rules /etc/smallwebwaf/rules.d/50-site.rules

Or mount it there. A path rule applies on every site behind that servewaf.