Core Rule Set reads request bodies up to SWWAF_WAF_BODY_LIMIT #122

Merged
clawbot merged 1 commits from issue-116-waf-body into next 2026-10-08 12:59:14 +02:00
Collaborator

For #116.

  • SWWAF_WAF_BODY_LIMIT (default off, at most 1G; more stops the start) has the Core Rule Set read form data and multipart up to the limit, and JSON and XML no larger than it; text/json, or an application/ or text/ type ending in +json, is JSON, and such a type ending in +xml is XML. The part read is held for the app; the rest streams on. Other bodies are not read.
  • While it is read, the client has SWWAF_CLIENT_REQUEST_TIMEOUT (408), and a body over SWWAF_REQUEST_MAX_BYTES is refused (413), before anything reaches the app.
  • A body Coraza cannot parse (900440), or a multipart body failing its strict checks (900450), adds 5, as Coraza's recommended rules 200002 and 200003 refuse them. So does a multipart body the limit cuts before the colon of a part's header line, or between the carriage return and the line feed that end a part's header line or the empty line after its headers, since Coraza takes the line the limit cuts for a malformed header.
  • Content-Encoding is refused again (920450) on those four kinds.
  • Rule 900300 moves to phase 2, so it counts form and JSON fields past Coraza's 1000.
  • The ARGS exclusions of the third and fourth changes cover form and multipart fields too: gitea posts redirect_uri and ref in forms. JSON fields (json.path) keep the rules.
  • Coraza is built and tested with its no_fs_access tag, so it writes no file; tests run without the tag fail TestCorazaWritesNoFile.

Disclosures:

  • Judgement call: Content-Encoding is refused on a JSON or XML body too large to be read, which SPEC.md allows.
  • Judgement call: a multipart body the limit cuts inside a part's headers, as above, is a match, as under Coraza's rule 200003, rather than let off by a narrower rule.
  • Unverified: of the gitea refusals README.md copies from SPEC.md, tests cover only 932235 and 932180.
  • Deviation: the Dockerfile's go test and go build lines add -tags no_fs_access to REPO_POLICIES.md's model lines.

Model: opus-5-5

For https://git.eeqj.de/sneak/smallwebwaf/issues/116. - `SWWAF_WAF_BODY_LIMIT` (default `off`, at most `1G`; more stops the start) has the Core Rule Set read form data and multipart up to the limit, and JSON and XML no larger than it; `text/json`, or an `application/` or `text/` type ending in `+json`, is JSON, and such a type ending in `+xml` is XML. The part read is held for the app; the rest streams on. Other bodies are not read. - While it is read, the client has `SWWAF_CLIENT_REQUEST_TIMEOUT` (408), and a body over `SWWAF_REQUEST_MAX_BYTES` is refused (413), before anything reaches the app. - A body Coraza cannot parse (900440), or a multipart body failing its strict checks (900450), adds 5, as Coraza's recommended rules 200002 and 200003 refuse them. So does a multipart body the limit cuts before the colon of a part's header line, or between the carriage return and the line feed that end a part's header line or the empty line after its headers, since Coraza takes the line the limit cuts for a malformed header. - `Content-Encoding` is refused again (920450) on those four kinds. - Rule 900300 moves to phase 2, so it counts form and JSON fields past Coraza's 1000. - The `ARGS` exclusions of the third and fourth changes cover form and multipart fields too: gitea posts `redirect_uri` and `ref` in forms. JSON fields (`json.path`) keep the rules. - Coraza is built and tested with its `no_fs_access` tag, so it writes no file; tests run without the tag fail `TestCorazaWritesNoFile`. Disclosures: - Judgement call: `Content-Encoding` is refused on a JSON or XML body too large to be read, which `SPEC.md` allows. - Judgement call: a multipart body the limit cuts inside a part's headers, as above, is a match, as under Coraza's rule 200003, rather than let off by a narrower rule. - Unverified: of the gitea refusals `README.md` copies from `SPEC.md`, tests cover only 932235 and 932180. - Deviation: the Dockerfile's `go test` and `go build` lines add `-tags no_fs_access` to `REPO_POLICIES.md`'s model lines. Model: opus-5-5
clawbot self-assigned this 2026-10-08 10:25:35 +02:00
clawbot added the needs-review label 2026-10-08 10:25:41 +02:00
Author
Collaborator

Review failed: needs rework.

  1. internal/waf/waf.go, bodyDirectives: a body Coraza cannot parse is not refused. An XML body carrying an SQL injection, with a stray end tag after its root element, is forwarded with waf_score 0, and Go's encoding/xml still hands the app the injection; a multipart body with a repeated boundary parameter, or with a malformed part header before the attack, is likewise forwarded uninspected. Acceptable: while bodies are read, a body Coraza fails to parse (REQBODY_ERROR) and a multipart body that fails its strict checks (MULTIPART_STRICT_ERROR) are a match, as Coraza's recommended rules 200002 and 200003 make them, while a form or multipart body cut at the limit is not; with tests.
  2. internal/waf/waf.go, rules 900410 and 900420: an XML body whose type has the +xml suffix (application/atom+xml, application/vnd.example+xml) is not read, though a +json body is read as JSON, and a text/json body is not read either. Frameworks such as Spring and ASP.NET read these as XML and JSON, and with 920420 off by default nothing refuses them, so an attack in them reaches the app uninspected. Acceptable: these types read as XML and JSON, with a test.
  3. internal/config/config.go, SWWAF_WAF_BODY_LIMIT: a size over 1G is accepted, then Coraza refuses it (it reads at most 1 GiB) and newCoreRuleSet panics at start, though its comment says no setting can break the rule set. Acceptable: a value over 1G stops the start with a message naming the setting, with a test, and README.md gives the maximum.
  4. internal/waf/waf.go, Inspect: Coraza writes each multipart file part it reads to the system's temporary directory, while SPEC.md has smallwebwaf write only to its state directory; no loaded rule reads a file's content. Acceptable: nothing written outside the state directory, for example by building with Coraza's no_fs_access build tag, under which it counts a file part's bytes without writing them; with a test.

Judgement calls accepted:

  • Content-Encoding refused on a JSON or XML body too large to be read.
  • The ARGS exclusions of the third and fourth changes cover form and multipart fields of the same names.
  • The gitea refusals README.md copies from SPEC.md tested only for 932235 and 932180.

Unverified: that Spring and ASP.NET read the types in finding 2 (not run here).

Model: opus-5-5

Review failed: needs rework. 1. `internal/waf/waf.go`, `bodyDirectives`: a body Coraza cannot parse is not refused. An XML body carrying an SQL injection, with a stray end tag after its root element, is forwarded with `waf_score` 0, and Go's `encoding/xml` still hands the app the injection; a multipart body with a repeated `boundary` parameter, or with a malformed part header before the attack, is likewise forwarded uninspected. Acceptable: while bodies are read, a body Coraza fails to parse (`REQBODY_ERROR`) and a multipart body that fails its strict checks (`MULTIPART_STRICT_ERROR`) are a match, as Coraza's recommended rules 200002 and 200003 make them, while a form or multipart body cut at the limit is not; with tests. 2. `internal/waf/waf.go`, rules 900410 and 900420: an XML body whose type has the `+xml` suffix (`application/atom+xml`, `application/vnd.example+xml`) is not read, though a `+json` body is read as JSON, and a `text/json` body is not read either. Frameworks such as Spring and ASP.NET read these as XML and JSON, and with 920420 off by default nothing refuses them, so an attack in them reaches the app uninspected. Acceptable: these types read as XML and JSON, with a test. 3. `internal/config/config.go`, `SWWAF_WAF_BODY_LIMIT`: a size over `1G` is accepted, then Coraza refuses it (it reads at most 1 GiB) and `newCoreRuleSet` panics at start, though its comment says no setting can break the rule set. Acceptable: a value over `1G` stops the start with a message naming the setting, with a test, and `README.md` gives the maximum. 4. `internal/waf/waf.go`, `Inspect`: Coraza writes each multipart file part it reads to the system's temporary directory, while `SPEC.md` has `smallwebwaf` write only to its state directory; no loaded rule reads a file's content. Acceptable: nothing written outside the state directory, for example by building with Coraza's `no_fs_access` build tag, under which it counts a file part's bytes without writing them; with a test. Judgement calls accepted: - `Content-Encoding` refused on a JSON or XML body too large to be read. - The `ARGS` exclusions of the third and fourth changes cover form and multipart fields of the same names. - The gitea refusals `README.md` copies from `SPEC.md` tested only for 932235 and 932180. Unverified: that Spring and ASP.NET read the types in finding 2 (not run here). Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-08 10:51:56 +02:00
clawbot force-pushed issue-116-waf-body from d5b90a80dc to 928ad4a11c 2026-10-08 11:07:32 +02:00 Compare
clawbot force-pushed issue-116-waf-body from 928ad4a11c to 0fb0675588 2026-10-08 11:39:10 +02:00 Compare
Author
Collaborator

Rework of #122 (comment):

  1. Fixed: rules 900440 (REQBODY_ERROR) and 900450 (MULTIPART_STRICT_ERROR) each add 5, and 900430 lets off a multipart body reaching the limit; as ids from 900000 to 900999, SWWAF_WAF_DISABLED_RULES refuses them. Tested with the stray XML end tag, the repeated boundary, a malformed part header, and a body cut inside a part header.
  2. Fixed: 900410 reads +xml types as XML, 900420 +json and text/json as JSON; tested.
  3. Fixed: a size over 1G stops the start, naming SWWAF_WAF_BODY_LIMIT; tested; README.md gives the maximum.
  4. Fixed: Coraza is built and tested with no_fs_access, counting a file part's bytes without writing them; the test runs with the temporary directory missing, where Coraza built without the tag refuses to load.

Model: opus-5-5

Rework of https://git.eeqj.de/sneak/smallwebwaf/pulls/122#issuecomment-133626: 1. Fixed: rules 900440 (`REQBODY_ERROR`) and 900450 (`MULTIPART_STRICT_ERROR`) each add 5, and 900430 lets off a multipart body reaching the limit; as ids from 900000 to 900999, `SWWAF_WAF_DISABLED_RULES` refuses them. Tested with the stray XML end tag, the repeated `boundary`, a malformed part header, and a body cut inside a part header. 2. Fixed: 900410 reads `+xml` types as XML, 900420 `+json` and `text/json` as JSON; tested. 3. Fixed: a size over `1G` stops the start, naming `SWWAF_WAF_BODY_LIMIT`; tested; `README.md` gives the maximum. 4. Fixed: Coraza is built and tested with `no_fs_access`, counting a file part's bytes without writing them; the test runs with the temporary directory missing, where Coraza built without the tag refuses to load. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-10-08 11:39:20 +02:00
Author
Collaborator

Review failed: needs rework.

  1. internal/waf/waf.go, rule 900430: it lets off every fault of a multipart body that reaches SWWAF_WAF_BODY_LIMIT, not only a fault the cut makes, so padding brings back finding 1 of #122 (comment). A body whose Content-Type names its boundary twice, or whose first part header has no colon, with an SQL injection after it, is a match when short and is forwarded with waf_score 0 once padded to the limit. Coraza already passes a body the limit cuts inside a boundary line, a header's value or a part's content; it flags only a cut before a part header's colon. Acceptable: any fault but one in the header line the limit cuts is still a match when the body reaches the limit (dropping 900430, as Coraza's rule 200003 has it, also meets this, at the cost of that rare cut), with tests of those two bodies padded to the limit; README.md to match.
  2. README.md, SWWAF_WAF_BODY_LIMIT: "one whose type ends in +xml is XML", and the same for +json, holds only for application/ and text/ types; an image/svg+xml body is not read. Acceptable: the sentence names the types that are read.

Judgement call accepted: a body Coraza cannot parse is refused even where an app could read it, such as XML declared ISO-8859-1 or an application/json-seq body, as Coraza's recommended configuration refuses it.

Model: opus-5-5

Review failed: needs rework. 1. `internal/waf/waf.go`, rule 900430: it lets off every fault of a multipart body that reaches `SWWAF_WAF_BODY_LIMIT`, not only a fault the cut makes, so padding brings back finding 1 of https://git.eeqj.de/sneak/smallwebwaf/pulls/122#issuecomment-133626. A body whose `Content-Type` names its boundary twice, or whose first part header has no colon, with an SQL injection after it, is a match when short and is forwarded with `waf_score` 0 once padded to the limit. Coraza already passes a body the limit cuts inside a boundary line, a header's value or a part's content; it flags only a cut before a part header's colon. Acceptable: any fault but one in the header line the limit cuts is still a match when the body reaches the limit (dropping 900430, as Coraza's rule 200003 has it, also meets this, at the cost of that rare cut), with tests of those two bodies padded to the limit; `README.md` to match. 2. `README.md`, `SWWAF_WAF_BODY_LIMIT`: "one whose type ends in `+xml` is XML", and the same for `+json`, holds only for `application/` and `text/` types; an `image/svg+xml` body is not read. Acceptable: the sentence names the types that are read. Judgement call accepted: a body Coraza cannot parse is refused even where an app could read it, such as XML declared `ISO-8859-1` or an `application/json-seq` body, as Coraza's recommended configuration refuses it. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-08 11:56:45 +02:00
clawbot force-pushed issue-116-waf-body from 0fb0675588 to fbe87a7c5e 2026-10-08 12:05:03 +02:00 Compare
Author
Collaborator

Rework of #122 (comment):

  1. Fixed: rule 900430 is dropped, as Coraza's rule 200003 has it, so a multipart body cut before a part header's colon is a match too; the two bodies are tested padded past the limit, and that cut is tested; README.md says so.
  2. Fixed: README.md names the types read as JSON and XML, only application/ and text/ ones; the comment above bodyDirectives in waf.go now says the same.

Model: opus-5-5

Rework of https://git.eeqj.de/sneak/smallwebwaf/pulls/122#issuecomment-133710: 1. Fixed: rule 900430 is dropped, as Coraza's rule 200003 has it, so a multipart body cut before a part header's colon is a match too; the two bodies are tested padded past the limit, and that cut is tested; `README.md` says so. 2. Fixed: `README.md` names the types read as JSON and XML, only `application/` and `text/` ones; the comment above `bodyDirectives` in `waf.go` now says the same. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-10-08 12:13:15 +02:00
Author
Collaborator

Review failed: needs rework.

  1. README.md, SWWAF_WAF_BODY_LIMIT, and the comment above rule 900440 in internal/waf/waf.go: they say a multipart body adds to the score when the limit cuts it before the colon of a part's header line, but it also does when the limit cuts between the carriage return and the line feed that end a part's header line, or the empty line after its headers (Coraza takes that line, ending in a lone carriage return, for a malformed header), so the refusals dropping 900430 brings are understated. Acceptable: both name that cut too, with a test of it as the cut before a colon has.

Judgement call accepted: a multipart body the limit cuts inside a part's headers is refused, as under Coraza's rule 200003; one cut inside a part's content, such as a gitea attachment past the limit, is not.

Model: opus-5-5

Review failed: needs rework. 1. `README.md`, `SWWAF_WAF_BODY_LIMIT`, and the comment above rule 900440 in `internal/waf/waf.go`: they say a multipart body adds to the score when the limit cuts it before the colon of a part's header line, but it also does when the limit cuts between the carriage return and the line feed that end a part's header line, or the empty line after its headers (Coraza takes that line, ending in a lone carriage return, for a malformed header), so the refusals dropping 900430 brings are understated. Acceptable: both name that cut too, with a test of it as the cut before a colon has. Judgement call accepted: a multipart body the limit cuts inside a part's headers is refused, as under Coraza's rule 200003; one cut inside a part's content, such as a gitea attachment past the limit, is not. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-08 12:28:50 +02:00
clawbot added 1 commit 2026-10-08 12:39:42 +02:00
SWWAF_WAF_BODY_LIMIT (default off, at most 1G) has the Core Rule Set read
form data and multipart up to the limit, the rest streaming on, and JSON
and XML no larger than it, with text/json and the application and text
types ending in +json or +xml. The part read is held for the app. A size
or time limit met while reading ends the request. Content-Encoding is
refused again on these kinds. A body Coraza cannot parse, or a multipart
body failing its strict checks, adds 5, as does a multipart body the limit
cuts in a part's headers before a colon or a line feed. Coraza is built
with no_fs_access, so writes no file. Rule 900300 moves to phase 2.

Judgement call: Content-Encoding is refused on a JSON or XML body too
large to read, as SPEC.md allows.

Model: opus-5-5
clawbot force-pushed issue-116-waf-body from fbe87a7c5e to 40f5ccb801 2026-10-08 12:39:42 +02:00 Compare
Author
Collaborator
  1. README.md (SWWAF_WAF_BODY_LIMIT) and the comment above rule 900440 in internal/waf/waf.go now name that cut too; TestMultipartBodyCutBeforeALineFeedInAPartsHeadersIsAMatch covers it for a header line and for the empty line after the headers.

Model: opus-5-5

1. `README.md` (`SWWAF_WAF_BODY_LIMIT`) and the comment above rule 900440 in `internal/waf/waf.go` now name that cut too; `TestMultipartBodyCutBeforeALineFeedInAPartsHeadersIsAMatch` covers it for a header line and for the empty line after the headers. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-10-08 12:39:53 +02:00
Author
Collaborator

Review passed.

Model: opus-5-5

Review passed. Model: opus-5-5
clawbot merged commit 6fcbda6ece into next 2026-10-08 12:59:14 +02:00
clawbot deleted branch issue-116-waf-body 2026-10-08 12:59:14 +02:00
Sign in to join this conversation.