fix: various security fixes (#38406) (#38426)

Backport #38406 by @bircni

Addresses a batch of privately reported security issues, grouped by
area:

- **SSRF** - migration PR-patch/asset fetches, OAuth2 avatar & OpenID
discovery, pull-mirror URL re-validation, and the outbound proxy path.
- **Access-token scope** - prevent scope escalation on token creation;
keep public-only tokens confined (feeds, packages, Actions listings,
star/watch lists, limited/private owners).
- **Access control / disclosure** - go-get default-branch leak, webhook
authorization-header leak, watch clearing on private transitions,
label/attachment scoping.
- **Denial of service** - input bounds for npm dist-tags, Debian control
files, Arch file lists, and SSH keys.

### 📌 Attention for site admins

Not breaking - existing configs keep working - but two changes are worth
a look:

- **New SSRF protection** Outbound requests (migrations, OAuth2 avatars,
OpenID discovery, pull mirrors, proxy path) are now validated against
the allow/block host lists. If your instance legitimately reaches
internal hosts, you may need to add them to
`[security].ALLOWED_HOST_LIST` (and the relevant `ALLOW_LOCALNETWORKS`
settings).
- **Deprecation** `[webhook].ALLOWED_HOST_LIST` is deprecated and will
be removed in a future release. Use `[security].ALLOWED_HOST_LIST`
instead; the old key still works for now.

Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: TheFox0x7 <thefox0x7@gmail.com>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Zettat123 <zettat123@gmail.com>
This commit is contained in:
Giteabot
2026-07-12 17:41:58 +00:00
committed by GitHub
co-authored by bircni TheFox0x7 techknowlogick Lunny Xiao wxiaoguang Zettat123
parent acbc75e2bd
commit de4b8277e9
93 changed files with 1714 additions and 137 deletions
+9 -1
View File
@@ -40,9 +40,17 @@ func TestAPICreateHook(t *testing.T) {
apiHook := DecodeJSON(t, resp, &api.Hook{})
assert.Equal(t, "http://example.com/", apiHook.Config["url"])
assert.Equal(t, "Bearer s3cr3t", apiHook.AuthorizationHeader)
// the stored authorization header is a secret and must never be returned by the API
assert.Empty(t, apiHook.AuthorizationHeader)
assert.Equal(t, "CI notifications", apiHook.Name)
// a read-scoped token must not be able to read back the authorization header
readToken := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
getReq := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/hooks/%d", owner.Name, repo.Name, apiHook.ID)).
AddTokenAuth(readToken)
getResp := MakeRequest(t, getReq, http.StatusOK)
assert.NotContains(t, getResp.Body.String(), "s3cr3t")
newName := "Deploy hook"
patchReq := NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s/hooks/%d", owner.Name, repo.Name, apiHook.ID), api.EditHookOption{
Name: &newName,