Files
smallwebwaf/docs/rules.md
T
sneak 1c70104677
check / check (push) Successful in 3m20s
Remove everything specific to a Gitea deployment (closes #209)
Delete the Gitea compose setup, its document, its two scripts and their
make targets. Drop the Core Rule Set exclusions written for Gitea: the
ten query parameters skipped by rules 930120, 932160 and 932260, and the
gitea_flash and redirect_to cookies. The remaining changes are
renumbered, five in all. Documents and tests use neutral examples.

Model: opus-5-5
2026-11-07 01:57:48 +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.