Core Rule Set: the API searches gitea and Forgejo share pass (closes #353) #377
No files matched your search
@@ -883,11 +883,12 @@ one entry of `apps` in `internal/coreruleset/coreruleset.go`. gitea's fixes are:
|
|||||||
which refused `org.apache.commons.logging`.
|
which refused `org.apache.commons.logging`.
|
||||||
|
|
||||||
A branch, tag or package name can hold a slash, as `feat/docker-support`
|
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,
|
does. So `q` skips the rule for shell paths (932160) too on these
|
||||||
where it refused `/bin/sh`:
|
searches, where it refused `/bin/sh`:
|
||||||
- a repository's branches, tags and packages pages;
|
- a repository's branches, tags and packages pages;
|
||||||
- an owner's packages page;
|
- 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
|
- `q` on gitea's other searches, for the same four rules. Words such as
|
||||||
`python3`, `powershell`, `ls -la` and `.htaccess` were refused there. The
|
`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
|
- the runner lists of the site, a user, an organisation and a
|
||||||
repository;
|
repository;
|
||||||
- the admin lists of users, organisations, repositories, unadopted
|
- 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
|
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
|
repository or activate an email send it in the body. gitea serves its
|
||||||
admin pages under `/-/admin/` and Forgejo under `/admin/`.
|
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:
|
- The path of these requests, which names a file:
|
||||||
- a file's page;
|
- a file's page;
|
||||||
- its raw file;
|
- its raw file;
|
||||||
|
|||||||
@@ -919,6 +919,10 @@ const retypeKey = "retype"
|
|||||||
// system files (930120) holds.
|
// system files (930120) holds.
|
||||||
const htaccess = ".htaccess"
|
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
|
// 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.
|
// value. An app's tests check that its fields let them through.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ func TestForgejoExclusionsAreNarrow(t *testing.T) {
|
|||||||
"/alice/-/packages/npm/x?q=",
|
"/alice/-/packages/npm/x?q=",
|
||||||
"/alice/tools/branches?other=",
|
"/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 {
|
if got := inspect(t, crs, get(target+value)); got.Score < threshold {
|
||||||
t.Errorf("%s%s let through: %+v", target, value, got)
|
t.Errorf("%s%s let through: %+v", target, value, got)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
# 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
|
# 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
|
# pages, on an owner's packages page, on the admin page of packages and on the
|
||||||
# skips this rule:
|
# API's search of packages also skips this rule:
|
||||||
# 932160: /bin/sh
|
# 932160: /bin/sh
|
||||||
SecRule REQUEST_FILENAME "@rx ^/(?:[^/]+/[^/]+/(?:branches|tags|packages)|\
|
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"
|
"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
|
# 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 searches:
|
||||||
# - the dashboard's filter of repositories;
|
# - the dashboard's filter of repositories;
|
||||||
# - the author filter of the issue and pull request lists;
|
# - 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;
|
# - the list of repositories a user watches;
|
||||||
# - an organisation's milestones of one team, and its search for teams;
|
# - 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
|
# - 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
|
# versions holds the package's name, which can hold a slash, as npm's
|
||||||
# @scope/name does.
|
# @scope/name does.
|
||||||
SecRule REQUEST_FILENAME "@rx ^/(?:repo/search|notifications/watching|\
|
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)|\
|
org/[^/]+/(?:milestones/[^/]+|teams/-/search)|\
|
||||||
[^/]+/-/packages/[^/]+/.+/versions|\
|
[^/]+/-/packages/[^/]+/.+/versions|\
|
||||||
[^/]+/[^/]+/(?:(?:issues|pulls)/posters|issues/suggestions|milestones|\
|
[^/]+/[^/]+/(?:(?: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=932250;ARGS:q,\
|
||||||
ctl:ruleRemoveTargetById=932260;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
|
# 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
|
# 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:
|
# segment, other apps' pages such as /index.php included:
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package coreruleset_test
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"slices"
|
"slices"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sneak.berlin/go/smallwebwaf/internal/coreruleset"
|
"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
|
// /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
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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/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": "/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": ""}
|
{"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": ""}
|
||||||
@@ -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
|
/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
|
/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
|
# Pages, raw files and edit pages of files, and the API's call for their
|
||||||
# contents.
|
# contents.
|
||||||
/owner/repo/src/branch/main/package.json
|
/owner/repo/src/branch/main/package.json
|
||||||
|
|||||||
Reference in new issue
Block a user