fix: various security fixes (#38406)

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: 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:
bircni
2026-07-12 17:14:09 +00:00
committed by GitHub
co-authored by TheFox0x7 techknowlogick Lunny Xiao wxiaoguang Zettat123
parent d2bd1589fe
commit f69e15afe7
93 changed files with 1714 additions and 137 deletions
+21 -2
View File
@@ -10,6 +10,7 @@ import (
"path"
"strings"
"testing"
"time"
"gitea.dev/models/db"
issues_model "gitea.dev/models/issues"
@@ -17,6 +18,7 @@ import (
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/test"
issue_service "gitea.dev/services/issue"
repo_service "gitea.dev/services/repository"
@@ -24,6 +26,7 @@ import (
"gitea.dev/tests"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestPullView_ReviewerMissed(t *testing.T) {
@@ -95,6 +98,14 @@ func TestPullView_CodeOwner(t *testing.T) {
unittest.AssertExistsAndLoadBean(t, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 5})
assert.NoError(t, pr.LoadIssue(t.Context()))
// capture the current PR head ref so we can wait for the async
// refs/pull/N/head sync triggered by the next push to complete
baseGitRepo, err := gitrepo.OpenRepository(t.Context(), repo)
require.NoError(t, err)
defer baseGitRepo.Close()
headRefBefore, err := baseGitRepo.GetRefCommitID(pr.GetGitHeadRefName())
require.NoError(t, err)
// update the file on the pr branch
_, err = files_service.ChangeRepoFiles(t.Context(), repo, user2, &files_service.ChangeRepoFilesOptions{
OldBranch: "codeowner-basebranch",
@@ -108,9 +119,17 @@ func TestPullView_CodeOwner(t *testing.T) {
})
assert.NoError(t, err)
// refs/pull/N/head is refreshed asynchronously by the push hook; wait for
// it before evaluating code owners, otherwise the changed-file set may not
// yet include user8-file.md and the review request would be missed
require.Eventually(t, func() bool {
headRefAfter, err := baseGitRepo.GetRefCommitID(pr.GetGitHeadRefName())
return err == nil && headRefAfter != headRefBefore
}, 30*time.Second, 100*time.Millisecond)
reviewNotifiers, err := issue_service.PullRequestCodeOwnersReview(t.Context(), pr)
assert.NoError(t, err)
assert.Len(t, reviewNotifiers, 1)
require.NoError(t, err)
require.Len(t, reviewNotifiers, 1)
assert.EqualValues(t, 8, reviewNotifiers[0].Reviewer.ID)
err = issue_service.ChangeTitle(t.Context(), pr.Issue, user2, "[WIP] Test Pull Request")