forgejo-11-secure/BACKPORTS.md
Cursor Agent 8b88cbe433
backport tagged security fixes through Forgejo v16.0.6
Keep v11.0.16 current with security fixes that are already in a published
upstream release, through v16.0.6 and v15.0.10 (2026-10-12). BACKPORTS.md
records what landed, what was skipped, and the latest tag checked.

Co-authored-by: KaKi87 <KaKi87@pm.me>
2026-10-12 22:06:42 +00:00

98 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Security backports onto Forgejo v11.0.16
This tree stays on the abandoned v11 line and only takes security fixes that are
already contained in a **published upstream tag**. Commits that exist only on
release branches, or only as `-dev` tags, are not applied.
## Latest upstream release checked
| Line | Latest published tag | Date | Commit |
| --- | --- | --- | --- |
| v16 (newest stable) | **v16.0.6** | 2026-10-12 | `1aa13944143b3bc4312607239a68da23512d5ce3` |
| v15 | v15.0.10 | 2026-10-12 | `17e1001d5e00e8ee3cbc1b6dd31be94ac38185f9` |
| v14 | v14.0.5 | 2026-04-29 | already older than v11.0.16 |
| v13 | v13.0.5 | 2026-01-16 | already older than v11.0.16 |
| v12 | v12.0.4 | 2025-09-19 | already older than v11.0.16 |
v11.0.16 itself is `0b2b072dcecbde8a53770855fd9c57cc54f276c3` (2026-07-09), the
same day as v15.0.4. v12–v14 security releases were merged into v11 before it
was abandoned, so they are not repeated here. There is no stable v17 tag
(`v17.0.0-dev` only).
Future runs should start after **v16.0.6** / **v15.0.10** and ignore branch tips
until those commits appear in a new tag.
## Version scheme
`v11.0.16-secure.N`, starting at `v11.0.16-secure.1`.
The GitHub release asset is `forgejo-<version>-linux-amd64` with the leading
`v` removed, for example `forgejo-11.0.16-secure.1-linux-amd64`.
## Backported
Each row names the v15 commit when that line has the fix (closest to v11). The
v16 commit is the same change on the newest stable line. Patches were applied
by hand: v15 files have diverged (API context helpers, migration registration,
authorization reducer), so a straight cherry-pick does not apply.
| Fix | Upstream commit (in a tag) | Shipped in | Notes |
| --- | --- | --- | --- |
| Treat RFC 6598 CGNAT `100.64.0.0/10` as private in the host matcher (SSRF) | `24c2be351abf929e3ede80f696277a5153b4e996` | v15.0.6, v16.0.2 | Applied with the upstream tests |
| Org-mode `#+INCLUDE` must not read server files | `0c41d710877c10a736a83fbf773ac4a44b8fc4ac` (org-mode half) | v15.0.6, v16.0.2 | `ReadFile` returns empty and logs are discarded |
| Disable hooks while applying a diff patch (GHSA-rcr6-4jqh-j84m) | `5f7e2e5c003c066a865ea483e42809fa87d85eae` | v15.0.6, v16.0.2 | `core.hooksPath=/dev/null` on apply, write-tree, commit-tree, and the temp-repo push. Local hooks only; remote pre-receive hooks still run |
| Apply the diff patch outside the bare temporary repo | `8efc220692` inside `19b9b9d216bbfb501c18514bd1a8c980246ca3f7` | v15.0.9, v16.0.5 | `git --git-dir <bare> apply` with a separate working directory, so a malicious patch cannot rewrite repo config |
| OpenID association CSRF | `8769076e3e` inside `19b9b9d216` | v15.0.9, v16.0.5 | Session stores `openIDState`. A missing session value is a failure, not a panic |
| Collaborator access mode cannot be raised to owner | `34091413a2` inside `d4de9eb2a87c26b402fdd0259e079957f8cd2b4b` | v15.0.7, v16.0.3 | `mode >= AccessModeOwner` is rejected |
| Public-only API tokens cannot use private repositories when updating a pull request | public-only half of `698e3dca06` / `d4de9eb2a8` and `b04c25d3d2` / `06d641d5b8c8b5670908bb414e22db672a2fb893` | v15.0.7–v15.0.8, v16.0.3–v16.0.4 | Adapted. v11 has public-only tokens but not the authorization reducer. `PublicOnlyContextKey` is set from `tokenRequiresScopes` and checked in `IsUserAllowedToUpdate` and `CanMaintainerWriteToBranch` |
| Draft release attachments require release write permission | `106b85d25a46023a305cb1375d2aa0e0b46b2629` | v15.0.8, v16.0.4 | API `checkReleaseMatchRepo` and web `ServeAttachment`. v11.0.16 already hid draft releases on get/list |
| Organization admin team is not promoted to owner | `450597142beff3af7d571b778738542cac2cfcd7` | v15.0.8, v16.0.4 | `perm.AccessMode = team.AccessMode` |
| Template generation removes a recreated `.git` before `git init` | `dee760c9ff` inside `06d641d5b8` | v15.0.8, v16.0.4 | Both `generate_repo_commit.go` (go1.25) and the legacy file |
| CVE-2026-20896: drop `REVERSE_PROXY_TRUSTED_PROXIES = *` from Docker app.ini templates | `81a5b0d8403d1bbb01421bb75b70bbfeb59d0c73` | v16.0.0 through v16.0.5 | Breaking for operators who relied on the wildcard. Set `FORGEJO__security__REVERSE_PROXY_TRUSTED_PROXIES` to the proxy address. Upstream did not put this in v15 LTS; v11 still shipped the vulnerable default |
| `github.com/go-chi/chi/v5` v5.3.2 | `00ebec2c6c` (v5.3.0 security) then `5af242d43a` (v5.3.2, same tags) | v15.0.6+ / v16.0.5 go.mod | v11 was v5.2.4 |
| `github.com/klauspost/compress` v1.18.7 | `c700a1ba0c` | v15.0.6, v16.0.2 | |
| `golang.org/x/crypto` v0.56.0 | `462b8b4993` | v15.0.8, v16.0.4 | CVE-2026-78662 and CVE-2026-56855 (SSH DoS). Module requires Go ≥ 1.26 |
| `golang.org/x/image` v0.45.0 | `ff6d06accc` | v15.0.7, v16.0.3 | v11 already had v0.43.0 |
| `golang.org/x/net` v0.58.0 | `7335a4d31d` (v0.56.0 security); v0.58.0 is what v15.0.7 and v16.0.5 ship | v15.0.6+ | v11 was v0.55.0. Superseded by v0.60.0 below |
| `golang.org/x/text` v0.41.0 | `7bb6ba2197` (v0.39.0 security); v0.41.0 is what v16.0.5 ships | v15.0.6+ | v11 was v0.38.0 |
| `golang.org/x/mod` v0.40.0 (indirect) | `0776a1843d` | v15.0.7, v16.0.3 | |
| `golang.org/x/sync` v0.22.0, `x/sys` v0.47.0, `x/tools` v0.49.0 | transitive, same versions as v16.0.5 `go.mod` | v16.0.5 | Pulled in by the modules above |
| Go `go 1.26.0` / `toolchain go1.26.7` | `525fc5b43c`, `971568e264` | v15.0.7, v16.0.5 | Required to consume `x/crypto` v0.56.0. Superseded by go1.26.9 below |
| mermaid 11.16.1 | `40c92cc422` | v15.0.7, v16.0.3 | lockfile updated |
| postcss 8.5.23 | `583c447a11` | v15.0.6, v16.0.2 | lockfile updated. Intermediate 8.5.12 and 8.5.18 are included |
| svgo 4.1.0 | `4aa4c8793f` | v15.0.8, v16.0.4 | `import {optimize} from 'svgo'` is unchanged. Intermediate 4.0.2 is included |
| Fork `pull_request_review` and `pull_request_review_comment` run from the pull request base | `6ff8b8e14f` inside `17e1001d5e` | v15.0.10, v16.0.6 | Adapted. v15 only adds `WithPullRequest` because `getPullRequestCommitAndApproval` already chooses the base commit. v11 has no `ActionUser` trust table, so a fork review uses the base workflow when the reviewer can write actions and the poster cannot. Same-repo pull requests and a trusted poster still use the head. `IsForkPullRequest` is set, so repository secrets stay withheld |
| Tag creation does not load attachments for an unsaved release | `65ca1b0dbe` inside `17e1001d5e` | v15.0.10, v16.0.6 | `LoadAttributes` returns before archive counts and attachments when `ID == 0`. The second `LoadAttributes` call inside `createTag` is removed |
| Issue label delete cannot read another repository's label | `9623034655` inside `17e1001d5e` | v15.0.10, v16.0.6 | Adapted. v11's route is `DELETE .../labels/{id}` and returns 204, not the GitHub label body. The id is resolved with `GetLabelInRepoByID`, then `GetLabelInOrgByID` when the owner is an organization, so an organization label on an issue can still be removed |
| Org and repo label deletes no longer share one id check | `5e4dc852a4` inside `17e1001d5e` | v15.0.10, v16.0.6 | `DeleteLabel` is split into `DeleteLabelInOrg` and `DeleteLabelInRepo`. A type mismatch returns an error instead of comparing an org id with a repo id |
| `katex` 0.18.2 | `b6291844dc` | v15.0.10, v16.0.6 | Direct dependency. v11 was 0.16.21. Mermaid still nests katex 0.16.45; micromark-extension-math nests 0.16.47, same shape as the v15 lockfile |
| `golang.org/x/net` v0.60.0 | `50d17fc53d` | v15.0.10, v16.0.6 | Also pulls `x/crypto` v0.57.0, `x/sync` v0.23.0, `x/sys` v0.48.0, `x/text` v0.42.0, and `x/mod` v0.41.0 |
| Go toolchain `go1.26.9` | `51056ebd74` | v15.0.10, v16.0.6 | `go 1.26.0` stays. `.github/workflows/release.yml` pins `GOTOOLCHAIN`, so that pin moves to go1.26.9 with the directive |
## Skipped
| Fix | Upstream | Why |
| --- | --- | --- |
| Actions pre-execution stored XSS | org-mode commit `0c41d71087` also edits `models/actions/pre_execution_errors.go` | `PreExecutionError` was added in v13 and is not in v11 |
| Expand local reusable workflows from the base branch on `pull_request_target` | `841c28d1f4` inside `d4de9eb2a8` | Needs `ExpandLocalReusableWorkflows`, `WorkflowSourceCommit`, and migration registration that v11 does not have |
| Authorization reducer and repo-specific access tokens | remainder of `d4de9eb2a8` and `06d641d5b8` | `services/authz` and `GetUserRepoPermissionWithReducer` do not exist on v11. The public-only behavior was ported separately (see above) |
| sharp security bumps (v0.35.0 / v0.35.4 / v0.35.5) | `2c05f9af24`, `8fbae40d9c`, `cb23914d45` | `sharp` is not a v11 dependency. v15.0.10 and v16.0.6 ship 0.35.5 |
| `google.golang.org/grpc` indirect bumps | `9b6de2d5ae`, `72f8a67635`, `f2d33d5625` | grpc is not in v11 `go.mod` |
| `github.com/jackc/pgx` | later lines | not a v11 dependency |
| `github.com/go-ldap/ldap/v3` v3.4.14 | `77b5524f6e` | not marked `[SECURITY]` |
| goldmark v1.8.2 | later lines | not marked `[SECURITY]`; v11 already has v1.7.17 |
| go-git v5.17.1 / v5.18.0 | older `[SECURITY]` commits | v11.0.16 is already on v5.18.0 |
| happy-dom 20.8.9, minimatch 10.2.3, webpack 5.104.1 | commits before v11.0.16 | already in v11.0.16. Later webpack/minimatch/katex numbers in v16.0.5 are not marked `[SECURITY]` |
| 2026-01-08, 2026-05-12, and 2026-06-10 security patches | `52406dc6ea`, `9e51a55b63`, `a32151caf6` | already in v11.0.16 |
| Actions trust helper and the fork-event integration test | `cc039bc494` inside `17e1001d5e` (`getPullRequestCommitAndApproval`, `UpdateTrustedWithPullRequest`, `TestActionsForkPullRequest`) | Needs `services/actions/trust.go`, `ActionUser`, and `forgery.CreateRepository`, which v11 does not have. The review-event dispatch is ported above. Other non-sync fork events (assign, label, close, and so on) already call `WithPullRequest` on v11 but still detect workflows from the head, because that trust helper is absent |
## Adaptations
- Whole merge commits were not cherry-picked. Applicable hunks were copied onto the v11 tree.
- OpenID: upstream type-asserts `Session.Get` to `string` and panics when the key is missing. This port treats a non-string or empty value as an invalid state.
- `CanMaintainerWriteToBranch` checks the base repository only after `LoadBaseRepo`.
- CVE-2026-20896 removes a default. Installs that use reverse-proxy authentication must set `REVERSE_PROXY_TRUSTED_PROXIES` explicitly.
- Fork review events: v15 relies on `getPullRequestCommitAndApproval` after `WithPullRequest`. This tree copies that decision with actions write permission, because there is no explicit-trust user table. A poster who can write still runs the head workflow.
- Issue label delete: v15 looks up a name, then a repository id. v11 only has a numeric id, and organization labels are valid on an organization's issues, so the id is accepted from the repository or from that repository's organization.
- `DeleteLabel` callers (`routers/api/v1/org`, `routers/api/v1/repo`, `routers/web/org`, `routers/web/repo`, `services/f3/driver`) now use `DeleteLabelInOrg` or `DeleteLabelInRepo`.
- The GitHub release workflow hardcodes `go-version` and `GOTOOLCHAIN`. Both are go1.26.9 so the published binary is built with the toolchain in `go.mod`.