Skip to content

Commit e39eed1

Browse files
authored
Merge pull request #75 from MDA2AV/feaure/more-tests
Add more tests
2 parents 3775834 + 2e5151a commit e39eed1

14 files changed

Lines changed: 776 additions & 26 deletions

File tree

docs/content/compliance/_index.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ Each test sends a request that violates a specific **MUST** or **MUST NOT** requ
4242
'COMP-ABSOLUTE-FORM',
4343
'COMP-METHOD-CASE','COMP-REQUEST-LINE-TAB',
4444
'COMP-VERSION-MISSING-MINOR','COMP-VERSION-LEADING-ZEROS',
45-
'COMP-VERSION-WHITESPACE','COMP-HTTP12-VERSION',
45+
'COMP-VERSION-WHITESPACE','COMP-VERSION-CASE','COMP-HTTP12-VERSION',
46+
'COMP-LONG-URL-OK','COMP-SPACE-IN-TARGET',
4647
'RFC9112-5.1-OBS-FOLD','RFC9110-5.6.2-SP-BEFORE-COLON',
4748
'RFC9112-5-EMPTY-HEADER-NAME','RFC9112-5-INVALID-HEADER-NAME',
4849
'RFC9112-5-HEADER-NO-COLON',
@@ -57,12 +58,14 @@ Each test sends a request that violates a specific **MUST** or **MUST NOT** requ
5758
'COMP-CHUNKED-EMPTY','COMP-CHUNKED-NO-FINAL',
5859
'COMP-GET-WITH-CL-BODY','COMP-CHUNKED-EXTENSION',
5960
'COMP-CHUNKED-TRAILER-VALID','COMP-CHUNKED-HEX-UPPERCASE',
60-
'COMP-RANGE-POST'
61+
'COMP-RANGE-POST','COMP-RANGE-INVALID',
62+
'COMP-DUPLICATE-CT','COMP-POST-UNSUPPORTED-CT',
63+
'COMP-ACCEPT-NONSENSE'
6164
]},
6265
{ key: 'methods-upgrade', label: 'Methods & Upgrade', testIds: [
6366
'COMP-METHOD-CONNECT',
6467
'COMP-UNKNOWN-TE-501','COMP-EXPECT-UNKNOWN','COMP-METHOD-TRACE',
65-
'COMP-TRACE-WITH-BODY',
68+
'COMP-TRACE-WITH-BODY','COMP-TRACE-SENSITIVE',
6669
'COMP-UPGRADE-POST','COMP-UPGRADE-MISSING-CONN',
6770
'COMP-UPGRADE-UNKNOWN','COMP-UPGRADE-INVALID-VER','COMP-UPGRADE-HTTP10',
6871
'COMP-CONNECTION-CLOSE','COMP-HTTP10-DEFAULT-CLOSE','COMP-HTTP10-NO-HOST'
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
title: "POST-UNSUPPORTED-CT"
3+
description: "POST-UNSUPPORTED-CT test documentation"
4+
weight: 15
5+
---
6+
7+
| | |
8+
|---|---|
9+
| **Test ID** | `COMP-POST-UNSUPPORTED-CT` |
10+
| **Category** | Compliance |
11+
| **Scored** | No |
12+
| **RFC** | [RFC 9110 §15.5.16](https://www.rfc-editor.org/rfc/rfc9110#section-15.5.16) |
13+
| **RFC Level** | MAY |
14+
| **Expected** | `415` or `2xx` |
15+
16+
## What it sends
17+
18+
A POST request with an unrecognized `Content-Type`.
19+
20+
```http
21+
POST / HTTP/1.1\r\n
22+
Host: localhost:8080\r\n
23+
Content-Length: 5\r\n
24+
Content-Type: application/x-nonsense\r\n
25+
\r\n
26+
hello
27+
```
28+
29+
## What the RFC says
30+
31+
> "The 415 (Unsupported Media Type) status code indicates that the origin server is refusing to service the request because the content is in a format not supported by this method on the target resource." — RFC 9110 §15.5.16
32+
33+
The server is not required to reject unsupported content types — it may choose to accept the body regardless of the declared type.
34+
35+
## Why it matters
36+
37+
A server that validates `Content-Type` and returns `415` for unsupported formats provides better API hygiene, helping clients detect misconfigured requests early. A server that ignores unknown content types and processes the body anyway is also valid behavior — many servers treat the body as opaque bytes regardless of the declared type.
38+
39+
## Verdicts
40+
41+
- **Pass** — Server returns `415` (validates content type) or `2xx` (accepts any type)
42+
- **Warn** — Server returns an unexpected status
43+
44+
## Sources
45+
46+
- [RFC 9110 §15.5.16](https://www.rfc-editor.org/rfc/rfc9110#section-15.5.16)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
title: "RANGE-INVALID"
3+
description: "RANGE-INVALID test documentation"
4+
weight: 14
5+
---
6+
7+
| | |
8+
|---|---|
9+
| **Test ID** | `COMP-RANGE-INVALID` |
10+
| **Category** | Compliance |
11+
| **Scored** | No |
12+
| **RFC** | [RFC 9110 §14.2](https://www.rfc-editor.org/rfc/rfc9110#section-14.2) |
13+
| **RFC Level** | MAY |
14+
| **Expected** | `2xx` (ignore) or `416` |
15+
16+
## What it sends
17+
18+
A GET request with a syntactically invalid `Range` header.
19+
20+
```http
21+
GET / HTTP/1.1\r\n
22+
Host: localhost:8080\r\n
23+
Range: bytes=abc-xyz\r\n
24+
\r\n
25+
```
26+
27+
The range value `abc-xyz` does not match the required integer format.
28+
29+
## What the RFC says
30+
31+
> "A server MAY ignore the Range header field." — RFC 9110 §14.2
32+
33+
> "An origin server MUST ignore a Range header field that contains a range unit it does not understand. A proxy MAY discard a Range header field that contains a range unit it does not understand." — RFC 9110 §14.2
34+
35+
> "A server that supports range requests MAY ignore or reject a Range header field that consists of more than two overlapping ranges, or a set of many small ranges that are not listed in ascending order, since both are indications of either a broken client or a deliberate denial-of-service attack." — RFC 9110 §14.2
36+
37+
## Why it matters
38+
39+
A server that receives an unparseable Range value should either ignore it (serve the full resource with `200`) or reject it with `416 Range Not Satisfiable`. Returning `206 Partial Content` with bogus range values could expose unexpected data or cause client-side parsing errors.
40+
41+
## Verdicts
42+
43+
- **Pass** — Server returns `2xx` (ignoring the invalid range) or `416`
44+
- **Warn** — Server returns an unexpected status
45+
46+
## Sources
47+
48+
- [RFC 9110 §14.2](https://www.rfc-editor.org/rfc/rfc9110#section-14.2)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
title: "ACCEPT-NONSENSE"
3+
description: "ACCEPT-NONSENSE test documentation"
4+
weight: 21
5+
---
6+
7+
| | |
8+
|---|---|
9+
| **Test ID** | `COMP-ACCEPT-NONSENSE` |
10+
| **Category** | Compliance |
11+
| **Scored** | No |
12+
| **RFC** | [RFC 9110 §12.5.1](https://www.rfc-editor.org/rfc/rfc9110#section-12.5.1) |
13+
| **RFC Level** | SHOULD |
14+
| **Expected** | `406` preferred, `2xx` acceptable |
15+
16+
## What it sends
17+
18+
A GET request with an `Accept` header requesting a non-existent media type.
19+
20+
```http
21+
GET / HTTP/1.1\r\n
22+
Host: localhost:8080\r\n
23+
Accept: application/x-nonsense\r\n
24+
\r\n
25+
```
26+
27+
## What the RFC says
28+
29+
> "A request without any Accept header field implies that the user agent will accept any media type in response." — RFC 9110 §12.5.1
30+
31+
> "If the header field is present in a request and none of the available representations for the response have a media type that is listed as acceptable, the origin server can either honor the header field by sending a 406 (Not Acceptable) response or disregard the header field by treating the response as if it is not subject to content negotiation for that request." — RFC 9110 §12.5.1
32+
33+
## Why it matters
34+
35+
Content negotiation allows servers to serve different representations of a resource based on client capabilities. A server that returns `406 Not Acceptable` for unrecognized media types actively enforces content negotiation. A server that ignores the `Accept` header and serves a default representation is also compliant — the RFC explicitly allows both behaviors.
36+
37+
## Verdicts
38+
39+
- **Pass** — Server returns `406 Not Acceptable` (enforces content negotiation)
40+
- **Warn** — Server returns `2xx` (ignores Accept, serves default representation)
41+
- **Fail** — Server returns an unexpected error status
42+
43+
## Sources
44+
45+
- [RFC 9110 §12.5.1](https://www.rfc-editor.org/rfc/rfc9110#section-12.5.1)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
title: "DATE-FORMAT"
3+
description: "DATE-FORMAT test documentation"
4+
weight: 20
5+
---
6+
7+
| | |
8+
|---|---|
9+
| **Test ID** | `COMP-DATE-FORMAT` |
10+
| **Category** | Compliance |
11+
| **Scored** | No |
12+
| **RFC** | [RFC 9110 §5.6.7](https://www.rfc-editor.org/rfc/rfc9110#section-5.6.7) |
13+
| **RFC Level** | SHOULD |
14+
| **Expected** | IMF-fixdate format |
15+
16+
## What it does
17+
18+
Sends a standard GET request and checks whether the `Date` response header uses the preferred IMF-fixdate format.
19+
20+
```http
21+
GET / HTTP/1.1\r\n
22+
Host: localhost:8080\r\n
23+
\r\n
24+
```
25+
26+
The test inspects the `Date` header value in the response.
27+
28+
## What the RFC says
29+
30+
> "An HTTP-date value represents time as an instance of Coordinated Universal Time (UTC). The first two formats [IMF-fixdate and rfc850-date] indicate UTC by the three-letter abbreviation for Greenwich Mean Time, 'GMT'... **A recipient that parses a timestamp value in an HTTP field MUST accept all three HTTP-date formats.**" -- RFC 9110 §5.6.7
31+
32+
> "HTTP-date = IMF-fixdate / obs-date" -- RFC 9110 §5.6.7
33+
34+
> "A sender MUST generate timestamps in the IMF-fixdate format." -- RFC 9110 §5.6.7 (quoted from RFC 7231 §7.1.1.1, carried forward)
35+
36+
The preferred format is **IMF-fixdate**:
37+
38+
```
39+
Sun, 06 Nov 1994 08:49:37 GMT
40+
```
41+
42+
## Why it matters
43+
44+
While all three date formats are valid for *recipients* to accept, **senders** (including origin servers) should generate the IMF-fixdate format. Servers using obsolete formats (RFC 850 or asctime) are technically non-conforming senders, though recipients must still parse them.
45+
46+
## Verdicts
47+
48+
- **Pass** -- Date header present and uses IMF-fixdate format
49+
- **Warn** -- Date header missing or uses a non-standard format
50+
51+
## Sources
52+
53+
- [RFC 9110 §5.6.7](https://www.rfc-editor.org/rfc/rfc9110#section-5.6.7)
54+
- [RFC 9110 §6.6.1](https://www.rfc-editor.org/rfc/rfc9110#section-6.6.1)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
title: "DUPLICATE-CT"
3+
description: "DUPLICATE-CT test documentation"
4+
weight: 20
5+
---
6+
7+
| | |
8+
|---|---|
9+
| **Test ID** | `COMP-DUPLICATE-CT` |
10+
| **Category** | Compliance |
11+
| **Scored** | Yes |
12+
| **RFC** | [RFC 9110 §5.3](https://www.rfc-editor.org/rfc/rfc9110#section-5.3) |
13+
| **RFC Level** | SHOULD |
14+
| **Expected** | `400` preferred, `2xx` acceptable |
15+
16+
## What it sends
17+
18+
A POST request with two `Content-Type` headers that have conflicting values.
19+
20+
```http
21+
POST / HTTP/1.1\r\n
22+
Host: localhost:8080\r\n
23+
Content-Length: 5\r\n
24+
Content-Type: text/plain\r\n
25+
Content-Type: text/html\r\n
26+
\r\n
27+
hello
28+
```
29+
30+
## What the RFC says
31+
32+
> "A sender MUST NOT generate multiple header fields with the same field name in a message unless either the entire field value for that header field is defined as a comma-separated list or the header field is a well-known exception." — RFC 9110 §5.3
33+
34+
> "A recipient MAY combine multiple header fields with the same field name into one 'field-name: field-value' pair... by appending each subsequent field value to the combined field value in order, separated by a comma." — RFC 9110 §5.3
35+
36+
`Content-Type` is not a list-based header — it has a single value. Duplicate `Content-Type` headers with different values create ambiguity about which value the server uses.
37+
38+
## Why it matters
39+
40+
When a proxy and origin server disagree on which `Content-Type` to use, it can lead to content-type confusion attacks. An attacker could craft a request that a proxy interprets as `text/plain` while the origin processes as `text/html`, enabling XSS or other injection attacks.
41+
42+
## Verdicts
43+
44+
- **Pass** — Server rejects with `400` or closes the connection
45+
- **Warn** — Server accepts with `2xx` (silently picks one value)
46+
- **Fail** — Server returns an unexpected error status
47+
48+
## Sources
49+
50+
- [RFC 9110 §5.3](https://www.rfc-editor.org/rfc/rfc9110#section-5.3)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
title: "LONG-URL-OK"
3+
description: "LONG-URL-OK test documentation"
4+
weight: 31
5+
---
6+
7+
| | |
8+
|---|---|
9+
| **Test ID** | `COMP-LONG-URL-OK` |
10+
| **Category** | Compliance |
11+
| **Scored** | Yes |
12+
| **RFC** | [RFC 9112 §3](https://www.rfc-editor.org/rfc/rfc9112#section-3) |
13+
| **RFC Level** | SHOULD |
14+
| **Expected** | Any status except `414` |
15+
16+
## What it sends
17+
18+
A GET request with a ~7900-character path (well under 8000 octets total for the request-line).
19+
20+
```http
21+
GET /aaaa...aaa HTTP/1.1\r\n
22+
Host: localhost:8080\r\n
23+
\r\n
24+
```
25+
26+
The path contains 7900 repetitions of `a`.
27+
28+
## What the RFC says
29+
30+
> "A server that receives a request-target longer than any URI it wishes to parse MUST respond with a 414 (URI Too Long) status code." — RFC 9112 §3
31+
32+
> "It is RECOMMENDED that all HTTP senders and recipients support, at a minimum, request-line lengths of 8000 octets." — RFC 9112 §3
33+
34+
## Why it matters
35+
36+
Servers that reject URLs well within the 8000-octet recommendation may break legitimate applications that use long query strings or path parameters. This test verifies the server can handle a request-line just under the recommended minimum.
37+
38+
This is the inverse of `MAL-LONG-URL`, which tests rejection of extremely long URLs (~100KB). Together they verify a server has reasonable upper and lower bounds.
39+
40+
## Verdicts
41+
42+
- **Pass** — Server returns any status other than `414`
43+
- **Fail** — Server returns `414 URI Too Long`
44+
- **Warn** — Server closes the connection without a response
45+
46+
## Sources
47+
48+
- [RFC 9112 §3](https://www.rfc-editor.org/rfc/rfc9112#section-3)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
title: "SPACE-IN-TARGET"
3+
description: "SPACE-IN-TARGET test documentation"
4+
weight: 32
5+
---
6+
7+
| | |
8+
|---|---|
9+
| **Test ID** | `COMP-SPACE-IN-TARGET` |
10+
| **Category** | Compliance |
11+
| **Scored** | Yes |
12+
| **RFC** | [RFC 9112 §3.2](https://www.rfc-editor.org/rfc/rfc9112#section-3.2) |
13+
| **RFC Level** | MUST |
14+
| **Expected** | `400` or connection close |
15+
16+
## What it sends
17+
18+
A GET request with an unencoded space inside the request-target.
19+
20+
```http
21+
GET /pa th HTTP/1.1\r\n
22+
Host: localhost:8080\r\n
23+
\r\n
24+
```
25+
26+
The request-target `/pa th` contains a bare space character (0x20) which is not a valid URI character.
27+
28+
## What the RFC says
29+
30+
> "Recipients of an invalid request-line SHOULD respond with either a 400 (Bad Request) error or a 301 (Moved Permanently) redirect with the request-target properly encoded." — RFC 9112 §3.2
31+
32+
> "request-target = origin-form / absolute-form / authority-form / asterisk-form" — RFC 9112 §3.2
33+
34+
The space character is the delimiter between the method, request-target, and HTTP-version in the request-line. An unencoded space in the target makes the request-line ambiguous — the parser sees `GET /pa th HTTP/1.1` as having four tokens instead of three.
35+
36+
## Why it matters
37+
38+
A server that accepts a bare space in the request-target must be performing heuristic parsing to guess where the target ends. This ambiguity is a classic source of request smuggling and cache poisoning vulnerabilities, where different parsers in a chain disagree on the boundaries of the request-line.
39+
40+
## Verdicts
41+
42+
- **Pass** — Server rejects with `400` or closes the connection
43+
- **Fail** — Server accepts the request
44+
45+
## Sources
46+
47+
- [RFC 9112 §3.2](https://www.rfc-editor.org/rfc/rfc9112#section-3.2)

0 commit comments

Comments
 (0)