SWW_APPS: an app's Core Rule Set fixes apply only to the hostnames that serve it #225

Open
clawbot wants to merge 1 commits from issue-220-apps-by-hostname into next
pull from: issue-220-apps-by-hostname
Collaborator

Closes #220.

SWW_APPS names the apps each hostname serves, as the spec on the issue sets out (#220 (comment)). A request gets only its hostname's apps' fixes. Unset, every app's fixes apply to every hostname, as before.

What is gitea's. Three things now count as gitea's fixes:

  • the old fourth change: ten parameters such as path and ref, on every path;
  • the two cookies, gitea_flash and redirect_to;
  • gitea.conf.

The fourth change used to be a load-time SecRuleUpdateTargetById. It is now a per-request ctl rule (900591) in gitea.conf, so a hostname can be left out of it. The other six changes stay global and are renumbered in SPEC.md and waf.go.

How a hostname gets the fixes. Inspect sets the transaction variable app_gitea for a hostname that serves gitea. The first rule of gitea.conf (900590) skips to END_GITEA when that variable is missing. Adding an app takes a .conf file with the same first and last lines, plus one entry in apps in internal/waf/waf.go.

Disclosures:

  • Set empty, SWW_APPS lists no hostname, so no app's fixes apply anywhere. The spec did not cover that case.
  • gitea is the only app so far, so no test can show a hostname being refused another app's fixes.
  • The name becomes SWW_WAF_APPS under the prefix rule in #219.
  • By sneak's order (#220 (comment)), this goes to him after a passing review, not straight to merge.

Model: opus-5-5

Closes https://git.eeqj.de/sneak/smallwebwaf/issues/220. `SWW_APPS` names the apps each hostname serves, as the spec on the issue sets out (https://git.eeqj.de/sneak/smallwebwaf/issues/220#issuecomment-170421). A request gets only its hostname's apps' fixes. Unset, every app's fixes apply to every hostname, as before. **What is gitea's.** Three things now count as gitea's fixes: - the old fourth change: ten parameters such as `path` and `ref`, on every path; - the two cookies, `gitea_flash` and `redirect_to`; - `gitea.conf`. The fourth change used to be a load-time `SecRuleUpdateTargetById`. It is now a per-request `ctl` rule (900591) in `gitea.conf`, so a hostname can be left out of it. The other six changes stay global and are renumbered in `SPEC.md` and `waf.go`. **How a hostname gets the fixes.** `Inspect` sets the transaction variable `app_gitea` for a hostname that serves gitea. The first rule of `gitea.conf` (900590) skips to `END_GITEA` when that variable is missing. Adding an app takes a `.conf` file with the same first and last lines, plus one entry in `apps` in `internal/waf/waf.go`. **Disclosures:** - Set empty, `SWW_APPS` lists no hostname, so no app's fixes apply anywhere. The spec did not cover that case. - gitea is the only app so far, so no test can show a hostname being refused another app's fixes. - The name becomes `SWW_WAF_APPS` under the prefix rule in https://git.eeqj.de/sneak/smallwebwaf/pulls/219. - By sneak's order (https://git.eeqj.de/sneak/smallwebwaf/issues/220#issuecomment-170435), this goes to him after a passing review, not straight to merge. Model: opus-5-5
clawbot added the needs-review label 2026-11-07 13:49:28 +01:00
clawbot self-assigned this 2026-11-07 13:49:31 +01:00
Author
Collaborator

For the reviewer (an Opus review, by sneak's order #220 (comment)):

  • The bar is the spec at #220 (comment), together with the worker's brief at #220 (comment).
  • After a passing review this PR goes to sneak for his own review. It is not merged into next.

Model: opus-5-5

**For the reviewer** (an Opus review, by sneak's order https://git.eeqj.de/sneak/smallwebwaf/issues/220#issuecomment-170435): - The bar is the spec at https://git.eeqj.de/sneak/smallwebwaf/issues/220#issuecomment-170421, together with the worker's brief at https://git.eeqj.de/sneak/smallwebwaf/issues/220#issuecomment-170442. - After a passing review this PR goes to sneak for his own review. It is not merged into `next`. Model: opus-5-5
Author
Collaborator

FAIL: needs-rework.

  1. internal/config/config.go, parseApps (line 1694): a hostname is only trimmed, lowercased and checked for being empty. So SWW_APPS="*.example.com:gitea", git.example.com/:gitea and git example.com:gitea all start without error, yet no request ever matches them. The operator's gitea then gets none of its fixes, with no sign why. A set value that cannot be valid must stop the start. Acceptable:
    • refuse a hostname that is not a valid DNS name, such as one holding *, / or a space, with an error that names it (the package's isZone already checks a DNS name);
    • add those cases to TestInvalidAppsStopsTheStart;
    • add the mistake to the lists of what stops the start in docs/settings.md (line 213) and SPEC.md (line 684).
  2. internal/discriminator/proxy.go (line 229): no test shows SWW_APPS taking effect in discriminator. The new tests pass waf.Params.Apps directly and check only that SWW_APPS parses. Nothing covers the setting reaching the Core Rule Set, or its being matched against the visitor's Host that the question carries. Acceptable: a test in internal/discriminator/coreruleset_test.go that sets SWW_APPS to list gitea for one hostname, sends questions for that hostname and for another, and expects one of gitea's fixes (such as /?path=.gitignore) to pass only on the listed one.

Model: opus-5-5

**FAIL: needs-rework.** 1. `internal/config/config.go`, `parseApps` (line 1694): a hostname is only trimmed, lowercased and checked for being empty. So `SWW_APPS="*.example.com:gitea"`, `git.example.com/:gitea` and `git example.com:gitea` all start without error, yet no request ever matches them. The operator's gitea then gets none of its fixes, with no sign why. A set value that cannot be valid must stop the start. Acceptable: - refuse a hostname that is not a valid DNS name, such as one holding `*`, `/` or a space, with an error that names it (the package's `isZone` already checks a DNS name); - add those cases to `TestInvalidAppsStopsTheStart`; - add the mistake to the lists of what stops the start in `docs/settings.md` (line 213) and `SPEC.md` (line 684). 2. `internal/discriminator/proxy.go` (line 229): no test shows `SWW_APPS` taking effect in `discriminator`. The new tests pass `waf.Params.Apps` directly and check only that `SWW_APPS` parses. Nothing covers the setting reaching the Core Rule Set, or its being matched against the visitor's `Host` that the question carries. Acceptable: a test in `internal/discriminator/coreruleset_test.go` that sets `SWW_APPS` to list gitea for one hostname, sends questions for that hostname and for another, and expects one of gitea's fixes (such as `/?path=.gitignore`) to pass only on the listed one. Model: opus-5-5
Author
Collaborator

For the reworker (an Opus run, within sneak's order #220 (comment)): fix the two findings of the review #225 (comment), as it says.

  1. A hostname in SWW_APPS that is not a valid DNS name stops the start, with an error that names it. Add those cases to TestInvalidAppsStopsTheStart, and add the mistake to the lists of what stops the start in docs/settings.md and SPEC.md.
  2. Add a test in internal/discriminator/coreruleset_test.go that shows SWW_APPS taking effect, matched against the visitor's Host, as the review describes.

Run make check and push. Don't merge: after a passing re-review the PR goes to sneak.

Model: opus-5-5

**For the reworker** (an Opus run, within sneak's order https://git.eeqj.de/sneak/smallwebwaf/issues/220#issuecomment-170434): fix the two findings of the review https://git.eeqj.de/sneak/smallwebwaf/pulls/225#issuecomment-170480, as it says. 1. A hostname in `SWW_APPS` that is not a valid DNS name stops the start, with an error that names it. Add those cases to `TestInvalidAppsStopsTheStart`, and add the mistake to the lists of what stops the start in `docs/settings.md` and `SPEC.md`. 2. Add a test in `internal/discriminator/coreruleset_test.go` that shows `SWW_APPS` taking effect, matched against the visitor's `Host`, as the review describes. Run `make check` and push. Don't merge: after a passing re-review the PR goes to sneak. Model: opus-5-5
clawbot force-pushed issue-220-apps-by-hostname from 766cfceac4 to 365e1a3e01 2026-11-07 14:14:37 +01:00 Compare
Author
Collaborator
  1. Fixed: a hostname in SWW_APPS that isZone refuses stops the start, with an error that names it. *.example.com, git.example.com/ and git example.com are in TestInvalidAppsStopsTheStart, and the mistake is in the lists in docs/settings.md and SPEC.md, now bulleted.
  2. Fixed: TestGiteasFixesApplyOnlyToAHostnameThatServesGitea in internal/discriminator/coreruleset_test.go sets SWW_APPS=a.example:gitea; a question for /?path=.gitignore on a.example is allowed, and on b.example the Core Rule Set refuses it.

Model: opus-5-5

1. Fixed: a hostname in `SWW_APPS` that `isZone` refuses stops the start, with an error that names it. `*.example.com`, `git.example.com/` and `git example.com` are in `TestInvalidAppsStopsTheStart`, and the mistake is in the lists in `docs/settings.md` and `SPEC.md`, now bulleted. 2. Fixed: `TestGiteasFixesApplyOnlyToAHostnameThatServesGitea` in `internal/discriminator/coreruleset_test.go` sets `SWW_APPS=a.example:gitea`; a question for `/?path=.gitignore` on `a.example` is allowed, and on `b.example` the Core Rule Set refuses it. Model: opus-5-5
Author
Collaborator

FAIL: needs-rework.

  1. SPEC.md (line 783): "The parameter and cookie names in these changes and fixes are matched without regard to case, as Coraza matches them." This is false for the cookies. Coraza does not match them: withoutCookies in internal/waf/waf.go (line 506) removes gitea_flash and redirect_to by exact name, so a cookie named GITEA_FLASH is still read. Acceptable: a short sentence that says the parameter names are matched without regard to case and the cookie names exactly.
  2. internal/config/config.go, apps (line 796): the start-up log shows "SWW_APPS":"" in two cases with opposite effects. Unset, every app's fixes apply to every hostname. Set empty, no app's fixes apply anywhere. SPEC.md (line 337) says the settings in effect are logged at start. An operator whose compose file passes SWW_APPS through empty sees the same line as the default, with no sign why gitea's ordinary requests are now refused. Acceptable: the two cases log differently, for example an unset SWW_APPS as null and a set-empty one as "", with both cases tested in internal/config/config_test.go.

Model: opus-5-5

**FAIL: needs-rework.** 1. `SPEC.md` (line 783): "The parameter and cookie names in these changes and fixes are matched without regard to case, as Coraza matches them." This is false for the cookies. Coraza does not match them: `withoutCookies` in `internal/waf/waf.go` (line 506) removes `gitea_flash` and `redirect_to` by exact name, so a cookie named `GITEA_FLASH` is still read. Acceptable: a short sentence that says the parameter names are matched without regard to case and the cookie names exactly. 2. `internal/config/config.go`, `apps` (line 796): the start-up log shows `"SWW_APPS":""` in two cases with opposite effects. Unset, every app's fixes apply to every hostname. Set empty, no app's fixes apply anywhere. `SPEC.md` (line 337) says the settings in effect are logged at start. An operator whose compose file passes `SWW_APPS` through empty sees the same line as the default, with no sign why gitea's ordinary requests are now refused. Acceptable: the two cases log differently, for example an unset `SWW_APPS` as `null` and a set-empty one as `""`, with both cases tested in `internal/config/config_test.go`. Model: opus-5-5
Author
Collaborator

For the reworker (an Opus run, within sneak's order #220 (comment)): fix the two findings of the second review, #225 (comment), as it says, and nothing more.

  1. SPEC.md: say that the parameter names are matched without regard to case and the cookie names exactly.
  2. An unset SWW_APPS and an empty one log differently at start, for example null for unset and "" for empty. Test both cases in internal/config/config_test.go.

Run make check and push. Don't merge. The next review checks these two points and anything the change breaks.

Model: opus-5-5

**For the reworker** (an Opus run, within sneak's order https://git.eeqj.de/sneak/smallwebwaf/issues/220#issuecomment-170434): fix the two findings of the second review, https://git.eeqj.de/sneak/smallwebwaf/pulls/225#issuecomment-170495, as it says, and nothing more. 1. `SPEC.md`: say that the parameter names are matched without regard to case and the cookie names exactly. 2. An unset `SWW_APPS` and an empty one log differently at start, for example `null` for unset and `""` for empty. Test both cases in `internal/config/config_test.go`. Run `make check` and push. Don't merge. The next review checks these two points and anything the change breaks. Model: opus-5-5
clawbot force-pushed issue-220-apps-by-hostname from 365e1a3e01 to 21f7bf6f23 2026-11-07 14:40:41 +01:00 Compare
Author
Collaborator
  1. Fixed: SPEC.md now says the parameter names are matched without regard to case, and the cookie names exactly.
  2. Fixed: an unset SWW_APPS logs as null and an empty one as ""; TestUnsetAndEmptyAppsAreLoggedDifferently in internal/config/config_test.go checks both.

Model: opus-5-5

1. Fixed: `SPEC.md` now says the parameter names are matched without regard to case, and the cookie names exactly. 2. Fixed: an unset `SWW_APPS` logs as `null` and an empty one as `""`; `TestUnsetAndEmptyAppsAreLoggedDifferently` in `internal/config/config_test.go` checks both. Model: opus-5-5
Author
Collaborator

For the reviewer (third review): check the two findings of the second review (#225 (comment)) against the rework, and anything the rework broke. Points the first two reviews did not raise are out of scope unless they break the definition of done.

Model: opus-5-5

**For the reviewer** (third review): check the two findings of the second review (https://git.eeqj.de/sneak/smallwebwaf/pulls/225#issuecomment-170495) against the rework, and anything the rework broke. Points the first two reviews did not raise are out of scope unless they break the definition of done. Model: opus-5-5
Author
Collaborator

PASS: both findings of the second review (#225 (comment)) are fixed, and the rework breaks nothing.

Model: opus-5-5

**PASS:** both findings of the second review (https://git.eeqj.de/sneak/smallwebwaf/pulls/225#issuecomment-170495) are fixed, and the rework breaks nothing. Model: opus-5-5
clawbot removed their assignment 2026-11-07 15:06:29 +01:00
sneak was assigned by clawbot 2026-11-07 15:06:29 +01:00
clawbot added merge-ready and removed needs-review labels 2026-11-07 15:06:29 +01:00
clawbot added needs-rebase and removed merge-ready labels 2026-11-09 02:04:11 +01:00
sneak was unassigned by clawbot 2026-11-09 02:04:11 +01:00
clawbot self-assigned this 2026-11-09 02:04:11 +01:00
Author
Collaborator

For the reworker (rebase only). next moved and internal/config/config.go conflicts. Rebase onto current next, keeping next's line wrapping where a conflict is only wrapping. 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.

Model: opus-5-5

**For the reworker** (rebase only). `next` moved and `internal/config/config.go` conflicts. Rebase onto current `next`, keeping `next`'s line wrapping where a conflict is only wrapping. 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. Model: opus-5-5
clawbot force-pushed issue-220-apps-by-hostname from 21f7bf6f23 to b5364bf282 2026-11-09 03:35:28 +01:00 Compare
clawbot added needs-review and removed needs-rebase labels 2026-11-09 03:35:37 +01:00
Author
Collaborator

Rebased onto next at c66277b, nothing else changed: in internal/config/config.go I kept next's wrapping and wrapped the new errNotAppsEntry to match, and in README.md I took next's settings table and re-added the SWW_APPS row.

Model: opus-5-5

Rebased onto `next` at `c66277b`, nothing else changed: in `internal/config/config.go` I kept `next`'s wrapping and wrapped the new `errNotAppsEntry` to match, and in `README.md` I took `next`'s settings table and re-added the `SWW_APPS` row. Model: opus-5-5
clawbot added merge-ready and removed needs-review labels 2026-11-09 03:48:05 +01:00
clawbot removed their assignment 2026-11-09 03:48:05 +01:00
sneak was assigned by clawbot 2026-11-09 03:48:05 +01:00
clawbot added needs-rebase and removed merge-ready labels 2026-11-09 04:03:35 +01:00
sneak was unassigned by clawbot 2026-11-09 04:03:35 +01:00
clawbot self-assigned this 2026-11-09 04:03:35 +01:00
Author
Collaborator

For the reworker (rebase only). next moved again and this PR conflicts with it. Rebase onto current next. Where a conflict is only the README.md settings table or line wrapping, take next's text and re-add this PR's SWW_APPS row. 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.

Model: opus-5-5

**For the reworker** (rebase only). `next` moved again and this PR conflicts with it. Rebase onto current `next`. Where a conflict is only the `README.md` settings table or line wrapping, take `next`'s text and re-add this PR's `SWW_APPS` row. 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. Model: opus-5-5
clawbot added 1 commit 2026-11-09 05:51:41 +01:00
gitea's fixes (its parameters, its cookies and gitea.conf) now apply
only to a hostname SWW_APPS lists gitea for, or to every hostname while
it is unset. Each app's fixes are one .conf file, whose first rule skips
the rest unless Inspect sets tx.app_<name>, and one entry in apps.

A hostname in SWW_APPS that is not a DNS name, such as *.example.com,
stops the start. Unset, SWW_APPS is logged at start as null; set
empty, as "".

Model: opus-5-5
clawbot force-pushed issue-220-apps-by-hostname from b5364bf282 to 7fcd79c182 2026-11-09 05:51:41 +01:00 Compare
clawbot added needs-review and removed needs-rebase labels 2026-11-09 05:51:54 +01:00
Author
Collaborator

Rebased onto next at 6850cb0, nothing else changed: in README.md I took next's text and re-added this PR's SWW_APPS row and its paragraph on each app's fixes, and in docs/settings.md I kept next's SWW_ERROR_BURST_THRESHOLD text below the SWW_APPS entry.

Model: opus-5-5

Rebased onto `next` at `6850cb0`, nothing else changed: in `README.md` I took `next`'s text and re-added this PR's `SWW_APPS` row and its paragraph on each app's fixes, and in `docs/settings.md` I kept `next`'s `SWW_ERROR_BURST_THRESHOLD` text below the `SWW_APPS` entry. Model: opus-5-5
clawbot added merge-ready and removed needs-review labels 2026-11-09 06:02:53 +01:00
clawbot removed their assignment 2026-11-09 06:02:54 +01:00
sneak was assigned by clawbot 2026-11-09 06:02:54 +01:00
All checks were successful
check / check (push) Successful in 4m25s
You are not authorized to merge this pull request.
This pull request can be merged automatically.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin issue-220-apps-by-hostname:issue-220-apps-by-hostname
git checkout issue-220-apps-by-hostname
Sign in to join this conversation.