fix: cherry-pick upstream security fixes from v1.26.3 and v1.26.4 #712

Merged
jmiller merged 17 commits from fix/upstream-security-v1.26.3 into main 2026-06-28 08:45:15 +00:00

17 Commits

Author SHA1 Message Date
jmiller 5da6a40f10 fix: resolve merge conflict marker and fix import paths in cherry-picked tests
Universal: PR Check / Branch Policy (pull_request) Failing after 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 9s
Generic: Project CI / Lint & Validate (pull_request) Successful in 41s
PR RC Release / Build RC Release (pull_request) Failing after 1m15s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Failing after 1m19s
Universal: PR Check / Secret Scan (pull_request) Successful in 1m23s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Build & Release / Build & Release Pipeline (pull_request) Failing after 1m38s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 13m43s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
- Remove residual <<<<<<< HEAD marker from api_org_test.go
- Convert code.gitea.io/gitea to mokoconsulting paths in 5 new test files:
  cmd/serv_test.go, models/auth/twofactor_test.go,
  modules/git/commit_info_nogogit_test.go,
  routers/private/hook_pre_receive_test.go,
  services/actions/notifier_helper_test.go
- Add changelog entries for new features (#460, #507, #513)

Claude-Session: https://claude.ai/code/session_011AAFzotGMf3ayvXhEmStCd
2026-06-28 03:31:44 -05:00
jmiller 4e5aa5f3ce fix: revert accidental secret scanning code from security fix branch
Universal: PR Check / Branch Policy (pull_request) Failing after 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 12s
Generic: Project CI / Lint & Validate (pull_request) Successful in 52s
Universal: PR Check / Secret Scan (pull_request) Successful in 54s
PR RC Release / Build RC Release (pull_request) Failing after 2m29s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Failing after 1m17s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
The pre-receive hook had security scanning code from the wrong feature
branch (feature/secret-scanning-clean). Restoring to the correct state
with only upstream security cherry-picks.

Claude-Session: https://claude.ai/code/session_011AAFzotGMf3ayvXhEmStCd
2026-06-28 02:37:49 -05:00
jmiller e947600ea7 fix: log error when pre-receive secret scan cannot read commit
Universal: PR Check / Branch Policy (pull_request) Failing after 2s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 11s
Generic: Project CI / Lint & Validate (pull_request) Successful in 40s
PR RC Release / Build RC Release (pull_request) Failing after 1m0s
Universal: PR Check / Secret Scan (pull_request) Successful in 1m15s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Failing after 1m12s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Previously, GetCommit failures were silently swallowed, allowing
pushes to proceed without scanning. Now logs the error so admins
can diagnose issues while still allowing the push.

Claude-Session: https://claude.ai/code/session_011AAFzotGMf3ayvXhEmStCd
2026-06-28 02:35:11 -05:00
jmiller b0bbaab621 docs: add security section to changelog for upstream v1.26.3/v1.26.4 fixes
Claude-Session: https://claude.ai/code/session_011AAFzotGMf3ayvXhEmStCd
2026-06-28 02:35:07 -05:00
Giteabot 2ff0e4aa21 fix: walk git log context error handling (#38182) (#38185)
Generic: Project CI / Lint & Validate (pull_request) Successful in 35s
Universal: PR Check / Branch Policy (pull_request) Failing after 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 10s
PR RC Release / Build RC Release (pull_request) Failing after 1m15s
Universal: PR Check / Secret Scan (pull_request) Successful in 55s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Has been cancelled
Universal: Build & Release / Promote to RC (pull_request) Has been cancelled
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been cancelled
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Backport #38182

Fix #38177

Make WalkGitLog can handle EOF and context errors correctly, and don't
export these private functions & methods & structs.

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-06-28 02:24:02 -05:00
bircni c0f89a373d fix(auth): do not auto-reactivate disabled users on OAuth2 callback (#38009) (#38183)
Backport #38009

The OAuth2 sign-in callback unconditionally set IsActive=true on the
local user row whenever the IdP authenticated them, silently undoing an
administrator's "Disable Account" action and granting the user a fresh
session in the same response. Treat the local IsActive flag as an
authoritative admin override: inactive users get a session and are
routed through the existing activate / prohibit-login pages by
verifyAuthWithOptions, matching the local-credentials sign-in path.

Adds an integration regression test that disables a linked local user
and asserts the row stays IsActive=false after a full OIDC callback.

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-06-28 02:24:00 -05:00
Giteabot 0dc858c15c fix(hostmacher): patch incorrect private list (#38170) (#38173)
Backport #38170 by @TheFox0x7

regression from #38039

Co-authored-by: TheFox0x7 <thefox0x7@gmail.com>
2026-06-28 02:23:35 -05:00
bircni 94590bc834 fix: allow git clone of private repos with anonymous code access (#38074) (#38146)
Backport #38074

Fixes #38062.

Private repositories with a code unit configured for **anonymous read
access** (Settings → Public Access → Code: anonymous view) could not be
cloned without credentials. The git HTTP auth gate (`httpBase`) only
bypassed authentication for non-private repos, ignoring the per-unit
anonymous access setting entirely.

- Check anonymous permissions via
`access_model.GetDoerRepoPermission(ctx, repo, nil)` + `CanAccess`
before requiring auth on pull operations, so the per-unit
`AnonymousAccessMode` is respected through the existing permission model
- This also correctly handles `setting.Repository.ForcePrivate` (which
the naive direct-field check would have missed)
- Push (receive-pack) and `RequireSignInViewStrict` continue to require
credentials as before

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-06-28 02:23:33 -05:00
bircni cbf34fb987 fix: Various security fixes (#38103) (#38151)
Backport #38103

- Enforce org visibility on organization label read endpoints (private
org labels no longer leak to non-members).
- Block fork sync (`merge-upstream`) when the base repo is no longer
readable (stops pulling commits after a parent goes private).
- Remove `REVERSE_PROXY_LIMIT` / `REVERSE_PROXY_TRUSTED_PROXIES` from
the Docker `app.ini` templates (the `= *` default allowed
`X-WEBAUTH-USER` impersonation; reverse-proxy auth is now opt-in and
admin-configured).
- Enforce single-use TOTP passcodes across web login, password-reset,
and Basic-Auth `X-Gitea-OTP` (fixes a TOCTOU race and a stateless
replay).
- Re-check branch write permission for every ref in a push (the
pre-receive hook cached the first ref's result, letting a per-branch
maintainer-edit grant escalate to full repo write).

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-06-28 02:22:18 -05:00
Lunny Xiao 26ad4fd03f fix(auth): ignore stale OIDC external login links to organizations (#37875) (#38141)
Backport #37875

This fixes an OIDC sign-in edge case where a stale `external_login_user`
record can still point to an organization or a deleted user.

In that situation, Gitea may keep resolving the external login to the
wrong account during sign-in. For affected instances, this matches the
behavior reported in #36439 and #37812, where a user signing in with
OIDC/Entra ID could appear as an organization, or hit a 404 after that
organization was removed.

- validate the user resolved from `external_login_user` during
OAuth2/OIDC login
- ignore stale links when the linked user no longer exists
- ignore stale links when the linked user is not an individual user
- remove the stale external login row so the sign-in flow can relink the
external account to the correct user

- Fixes #37812
- Related to #36439

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.8) <noreply@anthropic.com>
Co-authored-by: bircni <bircni@icloud.com>
2026-06-28 02:20:21 -05:00
bircni bc578b7eba fix: Various sec fixes (#38108) (#38147)
Backport #38108

- Enforce repository token scope on RSS/Atom feed endpoints so a PAT
without repo scope can no longer read private repo commit data.
- Block HTTP redirects during repository migration clones to prevent
SSRF reaching internal addresses via an attacker-controlled redirect.
- Redact the notification subject after repo access is revoked so
private issue/PR metadata is no longer leaked through the notification
API.

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2026-06-28 02:18:12 -05:00
Giteabot 186ac68f03 fix: bound debian ParseControlFile to a single control stanza (#38044) (#38055)
Backport #38044 by @metsw24-max

**Packages-index stanza injection via Debian control file**

A `.deb` whose `control` file appends extra paragraphs after a blank
line was still accepted, and `ParseControlFile` stored the whole
multi-stanza blob in `p.Control`. That blob is re-emitted verbatim into
the generated `Packages` index, so the embedded blank line splits it
into separate stanzas and an uploader can smuggle a package entry with
an attacker-chosen `Filename` into the shared index. A binary control
file only holds one stanza, so parsing now stops at the blank line that
terminates it; well-formed packages are unaffected and the new subtest
covers the trailing-stanza case.

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: metsw24-max <metsw24@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: bircni <bircni@icloud.com>
2026-06-28 02:17:28 -05:00
Giteabot fedce235d5 fix(hostmatcher): block reserved IP ranges from external/private filters (#38039) (#38059) 2026-06-28 02:17:27 -05:00
Giteabot d3c6998d3e fix(lfs): require Code-unit access for cross-repo LFS object reuse (#38006) (#38050) 2026-06-28 02:17:27 -05:00
Giteabot e9648f367e fix(actions)!: require merged PR to bypass fork PR approval gate (#38010) (#38041)
Backport #38010 by @bircni

`ifNeedApproval` in `services/actions/notifier_helper.go` decided
whether a
fork PR's workflow run had to wait for maintainer approval. The bypass
clause
counted any prior `approved_by > 0` run for `(repo_id,
trigger_user_id)`, so
the very first Approve-and-run click on a contributor's fork PR
permanently
trusted that user for every future fork PR in the same repository —
including
PRs whose only change is the workflow YAML itself.

Approving a workflow *run* is not the same as merging *code*. This
change
aligns the gate with GitHub Actions' first-time-contributor model: trust
is
granted only after the user has had a pull request merged in the repo.

## Behavior change

- **Before**: one approval = permanent trust for that user in that repo.
- **After**: every fork PR is gated until the contributor has at least
one
  merged PR in the repo.

Existing already-approved runs and merged PRs continue to work; only the
trust criterion for *future* fork PRs changes. Maintainers who rely on
the
implicit "approve once" trust will see the approval banner reappear
until
they merge a PR from that contributor.

---------

Signed-off-by: bircni <bircni@icloud.com>
Co-authored-by: bircni <bircni@icloud.com>
2026-06-28 02:17:26 -05:00
Giteabot 725acbe112 fix: bound CODEOWNERS regex match time (#38011) (#38025)
Backport #38011 by @bircni

User-supplied CODEOWNERS patterns were compiled without a match timeout,
so a crafted pattern (e.g. (a+)+) against a crafted file path could
backtrack for tens of seconds inside the PR creation transaction and
exhaust the database connection pool. Set MatchTimeout on each compiled
rule; the caller already treats match errors as non-matches.

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-06-28 02:17:26 -05:00
Giteabot 884e568ea2 fix(lfs): reject unknown SSH LFS sub-verbs to prevent auth bypass (#38008) (#38015) 2026-06-28 02:17:25 -05:00