Core Rule Set: the API searches gitea and Forgejo share pass (closes #353) #377

Merged
clawbot merged 1 commits from issue-353-api-searches into next 2026-11-12 12:28:33 +01:00
7 changed files with 271 additions and 11 deletions
Showing only changes of commit 7caad07de3 - Show all commits

No files matched your search

+12 -4
View File
@@ -883,11 +883,12 @@ one entry of `apps` in `internal/coreruleset/coreruleset.go`. gitea's fixes are:
which refused `org.apache.commons.logging`.
A branch, tag or package name can hold a slash, as `feat/docker-support`
does. So `q` skips the rule for shell paths (932160) too on these pages,
where it refused `/bin/sh`:
does. So `q` skips the rule for shell paths (932160) too on these
searches, where it refused `/bin/sh`:
- a repository's branches, tags and packages pages;
- an owner's packages page;
- the admin page of packages.
- the admin page of packages;
- the API's search of packages.
- `q` on gitea's other searches, for the same four rules. Words such as
`python3`, `powershell`, `ls -la` and `.htaccess` were refused there. The
@@ -902,12 +903,19 @@ one entry of `apps` in `internal/coreruleset/coreruleset.go`. gitea's fixes are:
- the runner lists of the site, a user, an organisation and a
repository;
- the admin lists of users, organisations, repositories, unadopted
repositories and emails.
repositories and emails;
- the API's searches of topics, of an organisation's teams and of
emails.
Most send `q` in the query string. The admin forms that adopt a
repository or activate an email send it in the body. gitea serves its
admin pages under `/-/admin/` and Forgejo under `/admin/`.
- Two fields of the API's searches other than `q`, for the same four rules:
- `query` of the search of unadopted repositories, which holds an owner
and a name, such as `alice/python3-app`;
- `name` of the search of a repository's milestones.
- The path of these requests, which names a file:
- a file's page;
- its raw file;
+4
View File
@@ -919,6 +919,10 @@ const retypeKey = "retype"
// system files (930120) holds.
const htaccess = ".htaccess"
// binSh is the shell path /bin/sh as a query or form value, which the rule for
// shell paths (932160) refuses.
const binSh = "%2Fbin%2Fsh"
// hardValues are words that name commands and files, as a query or form
// value. An app's tests check that its fields let them through.
//
+1 -1
View File
@@ -145,7 +145,7 @@ func TestForgejoExclusionsAreNarrow(t *testing.T) {
"/alice/-/packages/npm/x?q=",
"/alice/tools/branches?other=",
} {
for _, value := range slices.Concat([]string{"%2Fbin%2Fsh"}, hardValues) {
for _, value := range slices.Concat([]string{binSh}, hardValues) {
if got := inspect(t, crs, get(target+value)); got.Score < threshold {
t.Errorf("%s%s let through: %+v", target, value, got)
}
+32 -5
View File
@@ -172,11 +172,11 @@ SecRule REQUEST_FILENAME "@rx ^/(?:explore/repos|user/search_candidates|\
# A branch, tag or package name can hold a slash, as feat/docker-support and
# npm's @scope/name do. So q on a repository's branches, tags and packages
# pages, on an owner's packages page and on the admin page of packages also
# skips this rule:
# pages, on an owner's packages page, on the admin page of packages and on the
# API's search of packages also skips this rule:
# 932160: /bin/sh
SecRule REQUEST_FILENAME "@rx ^/(?:[^/]+/[^/]+/(?:branches|tags|packages)|\
admin/packages)$" \
admin/packages|api/v1/packages/[^/]+)$" \
"id:900605,phase:1,pass,nolog,ctl:ruleRemoveTargetById=932160;ARGS:q"
# gitea's other searches send a name or a few words in q too, which skips only
@@ -188,7 +188,9 @@ SecRule REQUEST_FILENAME "@rx ^/(?:[^/]+/[^/]+/(?:branches|tags|packages)|\
# The searches:
# - the dashboard's filter of repositories;
# - the author filter of the issue and pull request lists;
# - the lists of users and organisations, and the API's search for users;
# - the lists of users and organisations;
# - the API's searches of users, of topics, of an organisation's teams and of
# emails;
# - the list of repositories a user watches;
# - an organisation's milestones of one team, and its search for teams;
# - the milestones of a repository or an organisation, and the projects of a
@@ -205,7 +207,9 @@ SecRule REQUEST_FILENAME "@rx ^/(?:[^/]+/[^/]+/(?:branches|tags|packages)|\
# versions holds the package's name, which can hold a slash, as npm's
# @scope/name does.
SecRule REQUEST_FILENAME "@rx ^/(?:repo/search|notifications/watching|\
explore/(?:users|organizations)|api/v1/users/search|\
explore/(?:users|organizations)|\
api/v1/(?:users/search|topics/search|orgs/[^/]+/teams/search|\
admin/emails/search)|\
org/[^/]+/(?:milestones/[^/]+|teams/-/search)|\
[^/]+/-/packages/[^/]+/.+/versions|\
[^/]+/[^/]+/(?:(?:issues|pulls)/posters|issues/suggestions|milestones|\
@@ -219,6 +223,29 @@ SecRule REQUEST_FILENAME "@rx ^/(?:repo/search|notifications/watching|\
ctl:ruleRemoveTargetById=932250;ARGS:q,\
ctl:ruleRemoveTargetById=932260;ARGS:q"
# Two of the API's searches send their words in a field other than q, which
# skips these rules there:
# 930120: .htaccess
# 932120: powershell
# 932250: ls -la
# 932260: python3, alice/python3-app
# The search of unadopted repositories sends an owner and a name, such as
# alice/python3-app, in query.
SecRule REQUEST_FILENAME "@rx ^/api/v1/admin/unadopted$" \
"id:900607,phase:1,pass,nolog,\
ctl:ruleRemoveTargetById=930120;ARGS:query,\
ctl:ruleRemoveTargetById=932120;ARGS:query,\
ctl:ruleRemoveTargetById=932250;ARGS:query,\
ctl:ruleRemoveTargetById=932260;ARGS:query"
# The search of a repository's milestones sends a milestone's name in name.
SecRule REQUEST_FILENAME "@rx ^/api/v1/repos/[^/]+/[^/]+/milestones$" \
"id:900608,phase:1,pass,nolog,\
ctl:ruleRemoveTargetById=930120;ARGS:name,\
ctl:ruleRemoveTargetById=932120;ARGS:name,\
ctl:ruleRemoveTargetById=932250;ARGS:name,\
ctl:ruleRemoveTargetById=932260;ARGS:name"
# The repositories on a user's or an organisation's page are searched with q
# too. Their path has one segment, so q skips these rules on every path of one
# segment, other apps' pages such as /index.php included:
+101 -1
View File
@@ -3,6 +3,7 @@ package coreruleset_test
import (
"net/http"
"slices"
"strings"
"testing"
"sneak.berlin/go/smallwebwaf/internal/coreruleset"
@@ -182,7 +183,7 @@ func TestGiteaSearchExclusionsAreNarrow(t *testing.T) {
}
}
attacks := []string{"%2Fbin%2Fsh", commandInjection, pathTraversal}
attacks := []string{binSh, commandInjection, pathTraversal}
// /bin/sh, a shell command after a ";", a path traversal and the hard
// values stay refused in q on paths near the searches, and in another
@@ -248,3 +249,102 @@ func TestGiteaSearchExclusionsAreNarrow(t *testing.T) {
}
}
}
// giteaAPISearches are the API's searches that gitea and Forgejo share whose
// field skips the lists of system files and command names. Each ends in the
// field it sends its words in.
//
//nolint:gochecknoglobals // a constant cannot be a list
var giteaAPISearches = []string{
"/api/v1/users/search?q=",
"/api/v1/topics/search?q=",
"/api/v1/orgs/acme/teams/search?q=",
"/api/v1/admin/emails/search?q=",
"/api/v1/admin/unadopted?query=",
"/api/v1/repos/alice/tools/milestones?name=",
}
// giteaAPIPackageSearch is the API's search of an owner's packages, whose q
// also lets /bin/sh through, since a package name can hold a slash.
const giteaAPIPackageSearch = "/api/v1/packages/alice?q="
func TestGiteaAttacksAreRefusedInItsAPISearches(t *testing.T) {
t.Parallel()
const threshold = 5 // SWW_WAF_CORE_RULE_SET_SCORE_THRESHOLD's default
defaults, bodies := atDefaults(t), readingBodies(t)
searches := slices.Concat(
giteaAPISearches,
[]string{giteaAPIPackageSearch},
)
for _, search := range searches {
path, field, _ := strings.Cut(search, "?")
for _, attack := range []string{
sqlInjection, pathTraversal, scriptInjection, commandInjection,
} {
if got := inspect(t, defaults, get(search+attack)); got.Score < threshold {
t.Errorf("GET %s%s let through: %+v", search, attack, got)
}
// The same field in a form data body.
r := request{http.MethodPost, path, []string{formData}}
if got, _ := inspectBody(t, bodies, r, field+attack); got.Score < threshold {
t.Errorf(
"POST %s %s%s let through: %+v",
path,
field,
attack,
got,
)
}
}
}
// /bin/sh stays refused on the searches that are not of packages.
for _, search := range giteaAPISearches {
if got := inspect(t, defaults, get(search+binSh)); got.Score < threshold {
t.Errorf("%s%s let through: %+v", search, binSh, got)
}
}
}
func TestGiteaAPISearchExclusionsAreNarrow(t *testing.T) {
t.Parallel()
const threshold = 5 // SWW_WAF_CORE_RULE_SET_SCORE_THRESHOLD's default
crs := atDefaults(t)
// /bin/sh, a shell command after a ";", a path traversal and the hard
// values stay refused in each search's field on paths near the
// searches, and in another field on them.
for _, target := range []string{
"/api/v1/topics/search/x?q=",
"/api/v1/orgs/acme/teams?q=",
"/api/v1/orgs/acme/teams/search/x?q=",
"/api/v1/admin/emails?q=",
"/api/v1/admin/unadopted/alice/legacy-site?query=",
"/api/v1/admin/users?query=",
"/api/v1/repos/alice/tools/milestones/1?name=",
"/api/v1/repos/alice/tools/labels?name=",
"/api/v1/packages/alice/generic/tools-cli?q=",
"/api/v1/topics/search?other=",
"/api/v1/orgs/acme/teams/search?other=",
"/api/v1/admin/emails/search?other=",
"/api/v1/admin/unadopted?q=",
"/api/v1/repos/alice/tools/milestones?q=",
"/api/v1/packages/alice?other=",
} {
for _, value := range slices.Concat(
[]string{binSh, commandInjection, pathTraversal},
hardValues,
) {
if got := inspect(t, crs, get(target+value)); got.Score < threshold {
t.Errorf("%s%s let through: %+v", target, value, got)
}
}
}
}
+60
View File
@@ -974,3 +974,63 @@
{"method": "GET", "target": "/org/acme/issues/developers?type=your_repositories&sort=recentupdate&project=ZgotmplZ&state=open&q=SELECT%20%2A%20FROM%20users%20WHERE", "headers": ["Host: example.com", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://example.com/org/acme/issues/developers", "Accept-Encoding: gzip, deflate", "Cookie: session=5d2e8a17c4b9f063; lang=en-US"], "body": ""}
{"method": "GET", "target": "/org/acme/pulls/developers?type=your_repositories&sort=recentupdate&project=ZgotmplZ&state=open&q=SELECT%20%2A%20FROM%20users%20WHERE", "headers": ["Host: example.com", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://example.com/org/acme/pulls/developers", "Accept-Encoding: gzip, deflate", "Cookie: session=5d2e8a17c4b9f063; lang=en-US"], "body": ""}
{"method": "GET", "target": "/alice/tools/milestone/1?q=SELECT%20%2A%20FROM%20users%20WHERE", "headers": ["Host: example.com", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://example.com/alice/tools/milestone/1", "Accept-Encoding: gzip, deflate", "Cookie: session=5d2e8a17c4b9f063; lang=en-US"], "body": ""}
# The API's searches that gitea and Forgejo share, sent with curl to Forgejo
# 17.0.1. Each searches for words that name commands and files, such as python3
# and .htaccess, and for plain words. A package name can hold a slash, as npm's
# @alice/tools-cli does, so the search of packages is also sent /bin/sh. The
# search of unadopted repositories takes an owner and a name.
{"method": "GET", "target": "/api/v1/repos/search?q=python3&limit=10", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/search?q=powershell&limit=10", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/search?q=ls%20-la&limit=10", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/search?q=.htaccess&limit=10", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/search?q=docker-compose.yml&limit=10", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/search?q=tools&limit=10", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/users/search?q=python3", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/users/search?q=powershell", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/users/search?q=ls%20-la", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/users/search?q=.htaccess", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/users/search?q=bob", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/issues/search?q=python3&type=issues&state=open", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/issues/search?q=powershell&type=issues&state=open", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/issues/search?q=ls%20-la&type=issues&state=open", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/issues/search?q=.htaccess&type=issues&state=open", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/issues/search?q=docker-compose.yml&type=issues&state=open", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/issues/search?q=build&type=issues&state=open", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/alice/tools/issues?state=open&q=python3", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/alice/tools/issues?state=open&q=powershell", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/alice/tools/issues?state=open&q=ls%20-la", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/alice/tools/issues?state=open&q=.htaccess", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/alice/tools/issues?state=open&q=docker-compose.yml", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/packages/alice?q=python3", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/packages/alice?q=powershell", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/packages/alice?q=ls%20-la", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/packages/alice?q=.htaccess", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/packages/alice?q=%2Fbin%2Fsh", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/packages/alice?q=install-script", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/packages/alice?q=%40alice%2Ftools-cli", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/topics/search?q=python3", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/topics/search?q=powershell", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/topics/search?q=ls%20-la", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/topics/search?q=.htaccess", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/topics/search?q=docker", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/orgs/acme/teams/search?q=python3", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/orgs/acme/teams/search?q=powershell", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/orgs/acme/teams/search?q=ls%20-la", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/orgs/acme/teams/search?q=.htaccess", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/orgs/acme/teams/search?q=developers", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/admin/emails/search?q=python3", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/admin/emails/search?q=powershell", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/admin/emails/search?q=ls%20-la", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/admin/emails/search?q=.htaccess", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/admin/emails/search?q=alice", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/admin/unadopted?query=python3", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/admin/unadopted?query=powershell", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/admin/unadopted?query=ls%20-la", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/admin/unadopted?query=.htaccess", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/admin/unadopted?query=alice%2Fpython3-app", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/admin/unadopted?query=alice%2Flegacy-site", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/alice/tools/milestones?state=open&name=python3", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/alice/tools/milestones?state=open&name=powershell", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/alice/tools/milestones?state=open&name=ls%20-la", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/alice/tools/milestones?state=open&name=.htaccess", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
{"method": "GET", "target": "/api/v1/repos/alice/tools/milestones?state=open&name=v1.0", "headers": ["Host: example.com", "User-Agent: curl/8.18.0", "Accept: */*", "Authorization: token 772deb2aefef4c9484e8c673197b82bc880fc7ca"], "body": ""}
+61
View File
@@ -381,6 +381,67 @@
/org/acme/pulls/developers?type=your_repositories&sort=recentupdate&state=open&q=SELECT%20%2A%20FROM%20users%20WHERE&search_mode=exact
/alice/tools/milestone/1?q=SELECT%20%2A%20FROM%20users%20WHERE
# The API's searches that gitea and Forgejo share, sent with curl to gitea
# 1.27.3. Each searches for words that name commands and files, such as python3
# and .htaccess, and for plain words. A package name can hold a slash, as npm's
# @alice/tools-cli does, so the search of packages is also sent /bin/sh. The
# search of unadopted repositories takes an owner and a name.
/api/v1/repos/search?q=python3&limit=10
/api/v1/repos/search?q=powershell&limit=10
/api/v1/repos/search?q=ls%20-la&limit=10
/api/v1/repos/search?q=.htaccess&limit=10
/api/v1/repos/search?q=docker-compose.yml&limit=10
/api/v1/repos/search?q=tools&limit=10
/api/v1/users/search?q=python3
/api/v1/users/search?q=powershell
/api/v1/users/search?q=ls%20-la
/api/v1/users/search?q=.htaccess
/api/v1/users/search?q=bob
/api/v1/repos/issues/search?q=python3&type=issues&state=open
/api/v1/repos/issues/search?q=powershell&type=issues&state=open
/api/v1/repos/issues/search?q=ls%20-la&type=issues&state=open
/api/v1/repos/issues/search?q=.htaccess&type=issues&state=open
/api/v1/repos/issues/search?q=docker-compose.yml&type=issues&state=open
/api/v1/repos/issues/search?q=build&type=issues&state=open
/api/v1/repos/alice/tools/issues?state=open&q=python3
/api/v1/repos/alice/tools/issues?state=open&q=powershell
/api/v1/repos/alice/tools/issues?state=open&q=ls%20-la
/api/v1/repos/alice/tools/issues?state=open&q=.htaccess
/api/v1/repos/alice/tools/issues?state=open&q=docker-compose.yml
/api/v1/packages/alice?q=python3
/api/v1/packages/alice?q=powershell
/api/v1/packages/alice?q=ls%20-la
/api/v1/packages/alice?q=.htaccess
/api/v1/packages/alice?q=%2Fbin%2Fsh
/api/v1/packages/alice?q=install-script
/api/v1/packages/alice?q=%40alice%2Ftools-cli
/api/v1/topics/search?q=python3
/api/v1/topics/search?q=powershell
/api/v1/topics/search?q=ls%20-la
/api/v1/topics/search?q=.htaccess
/api/v1/topics/search?q=docker
/api/v1/orgs/acme/teams/search?q=python3
/api/v1/orgs/acme/teams/search?q=powershell
/api/v1/orgs/acme/teams/search?q=ls%20-la
/api/v1/orgs/acme/teams/search?q=.htaccess
/api/v1/orgs/acme/teams/search?q=developers
/api/v1/admin/emails/search?q=python3
/api/v1/admin/emails/search?q=powershell
/api/v1/admin/emails/search?q=ls%20-la
/api/v1/admin/emails/search?q=.htaccess
/api/v1/admin/emails/search?q=alice
/api/v1/admin/unadopted?query=python3
/api/v1/admin/unadopted?query=powershell
/api/v1/admin/unadopted?query=ls%20-la
/api/v1/admin/unadopted?query=.htaccess
/api/v1/admin/unadopted?query=alice%2Fpython3-app
/api/v1/admin/unadopted?query=alice%2Flegacy-site
/api/v1/repos/alice/tools/milestones?state=open&name=python3
/api/v1/repos/alice/tools/milestones?state=open&name=powershell
/api/v1/repos/alice/tools/milestones?state=open&name=ls%20-la
/api/v1/repos/alice/tools/milestones?state=open&name=.htaccess
/api/v1/repos/alice/tools/milestones?state=open&name=v1.0
# Pages, raw files and edit pages of files, and the API's call for their
# contents.
/owner/repo/src/branch/main/package.json