**Unvalidated version in goproxy ParsePackage**
The module version is read straight from the zip directory path and
never checked, so a crafted upload can leave a newline in it;
`EnumeratePackageVersions` then writes each stored version on its own
line for the `@v/list` endpoint, letting a module advertise fabricated
versions to `go` clients. Validated the parsed version with
`semver.IsValid` inside the parser, matching the version checks the
other package parsers already do.
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
## Summary
Adds `GET
/repos/{owner}/{repo}/compare/{basehead}.{diffType:diff|patch}`,
mirroring the existing `/git/commits/{sha}.{diffType}` endpoint but for
comparisons between two arbitrary refs.
The new endpoint streams a raw unified diff or `git format-patch` output
between any two refs:
GET /repos/{owner}/{repo}/compare/main...feature.diff
GET /repos/{owner}/{repo}/compare/v1.0..v1.1.patch
GET /repos/{owner}/{repo}/compare/abc1234...def5678.diff
Resolves#5561, #13416 and #17165.
AI was used while creating this PR. Automated tests were added as per
the contribution policy.
---------
Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This PR contains the following updates:
| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [pnpm](https://pnpm.io)
([source](https://redirect.github.com/pnpm/pnpm/tree/HEAD/pnpm)) |
[`11.5.2` →
`11.5.3`](https://renovatebot.com/diffs/npm/pnpm/11.5.2/11.5.3) |

|

|
---
### Release Notes
<details>
<summary>pnpm/pnpm (pnpm)</summary>
###
[`v11.5.3`](https://redirect.github.com/pnpm/pnpm/blob/HEAD/pnpm/CHANGELOG.md#1153)
[Compare
Source](https://redirect.github.com/pnpm/pnpm/compare/v11.5.2...v11.5.3)
##### Patch Changes
- Stopped expanding environment variables in repository-controlled
registry/proxy request destinations and registry credential values from
`.npmrc`, and in workspace registry URLs from `pnpm-workspace.yaml`.
Move dynamic registry URL and token configuration to trusted user,
global, CLI, or environment config.
- Resolve package-manager bootstrap dependencies with trusted user or
CLI registry and network config, and reject package-manager env-lockfile
records that do not use registry package paths with integrity-only
resolutions before auto-switch execution.
- Avoid writing `packageManagerDependencies` to `pnpm-lock.yaml` when
package manager policy is set to `onFail: ignore` or `pmOnFail: ignore`
[#​12228](https://redirect.github.com/pnpm/pnpm/issues/12228).
- Avoid running dependency-status auto-install when the dependency
status is unavailable without a project manifest.
- Using the `$` version reference syntax in `overrides` (e.g. `"react":
"$react"`) now prints a deprecation warning. The syntax still works, but
[catalogs](https://pnpm.io/catalogs) are the recommended way to keep an
overridden version in sync with the rest of the workspace. Reference a
catalog entry with the `catalog:` protocol instead.
- Fixed `pnpm config get globalconfig` to return the global
`config.yaml` path again
[pnpm/pnpm#11962](https://redirect.github.com/pnpm/pnpm/issues/11962).
- Fixed bare `--color` so it does not consume the following CLI flag,
allowing command shorthands like `--parallel` to expand correctly and
forms like `pnpm --color with current <command>` to dispatch the inner
command instead of failing with `MISSING_WITH_CURRENT_CMD`.
- Fix `pnpm install` ignoring `enableGlobalVirtualStore` toggle by
including it in the workspace state settings check
[#​12142](https://redirect.github.com/pnpm/pnpm/issues/12142).
- Security: pnpm now verifies the npm registry signature of a
package-manager binary before spawning it, so a cloned repository cannot
make pnpm download and execute an arbitrary native binary.
This covers two paths that select an executable from
repository-controlled input:
- **pacquet install engine** — declaring `pacquet` (or `@pnpm/pacquet`)
in `configDependencies` opts in to pnpm's Rust install engine. pnpm now
verifies that the installed `pacquet` shim and the host's
`@pacquet/<platform>-<arch>` binary carry a valid npm registry signature
for their exact `name@version`, and refuses to run pacquet (failing the
command) if the signature does not verify or cannot be checked. The only
graceful fallback to pnpm's own engine is when pacquet has no binary for
the current platform.
- **automatic version switch / `self-update`** — the `packageManager` /
`devEngines.packageManager` field makes pnpm download and run a specific
pnpm version. pnpm now verifies the registry signature of `pnpm`,
`@pnpm/exe`, and the host platform binary before installing/spawning
them, and refuses to run an engine whose signature does not match a
published, signed release. The check runs only on an actual download
(store cache miss), so it does not add a network round trip to every
command.
In both cases the signature is verified over the *installed* integrity,
against npm's public signing keys that ship embedded in the pnpm CLI
(like corepack), so bytes substituted via a tampered lockfile or a
repository-controlled registry fail verification — and a registry the
user did not vouch for cannot supply its own signing keys. The signed
packument is fetched from the configured registry, so an npm mirror
works transparently. Verification fails closed: if it cannot be
completed (for example, the registry is unreachable), the command fails
rather than running an unverified binary. The embedded keys are kept
current by a release-time check against npm's signing-keys endpoint.
- Made peer-dependent deduplication deterministic. When a peer-suffixed
package variant was a subset of two or more mutually incompatible larger
variants, the variant it collapsed into depended on the order importers
were resolved in, which varies between machines. This could resolve the
same workspace to different lockfiles on different platforms and make
`pnpm dedupe --check` alternate between passing and failing.
- Reject invalid package names and versions from staged tarball
manifests before deriving filenames for `pnpm stage download`.
- Clarified in CLI help that the pnpm store is trusted shared state and
store integrity checks are corruption detection, not a tamper boundary
for untrusted store writers.
- Reject reserved manifest `bin` names (`""`, `"."`, `".."`, and scoped
forms such as `@scope/..`) when resolving a package's bins. These names
previously passed the bin-name guard and, when joined to the global bin
directory during global remove/update/add operations, could resolve to
the global bin directory itself or its parent and have it recursively
deleted.
- Require trusted package identity before package-name `allowBuilds`
entries can approve lifecycle scripts for git, git-hosted tarball,
direct tarball, and local directory artifacts. To approve one of those
artifacts explicitly, use its peer-suffix-free lockfile depPath as the
`allowBuilds` key. Lockfile verification now rejects lockfiles where a
registry-style dependency path (`name@semver`) is backed by a git,
directory, or git-hosted tarball resolution
(`ERR_PNPM_RESOLUTION_SHAPE_MISMATCH`), so the dependency path is a
reliable artifact identity by the time scripts can run.
- Security: pnpm now verifies the OpenPGP signature of a downloaded
Node.js runtime's `SHASUMS256.txt` before trusting its integrity hashes.
When a repository requests a Node.js runtime (e.g. via
`devEngines.runtime` / `useNodeVersion`), the download mirror is
repository-configurable through `node-mirror:<channel>`. The integrity
of the downloaded binary was only checked against `SHASUMS256.txt`
fetched from that same mirror — a circular check that a malicious mirror
could satisfy by serving a tampered binary together with a matching
`SHASUMS256.txt`. pnpm then executes the binary (for example to run
lifecycle scripts).
pnpm now fetches `SHASUMS256.txt.sig` and verifies the detached OpenPGP
signature against the Node.js release team's public keys, which ship
embedded in the pnpm CLI. A mirror that serves a tampered binary cannot
also produce a valid signature, so the download fails to verify. The
embedded keys are kept current by a release-time check against the
canonical `nodejs/release-keys` list.
The musl variants from the hardcoded `unofficial-builds.nodejs.org`
mirror are not repository-configurable and are signed by a different
key, so they continue to be trusted over TLS.
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- Only on Monday (`* * * * 1`)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR has been generated by [Mend
Renovate](https://redirect.github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNSIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
Co-authored-by: bircni <bircni@icloud.com>
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| redis | service | digest | `e74c9b9` → `a505f8b` |
|
[renovatebot/github-action](https://redirect.github.com/renovatebot/github-action)
| action | patch | `v46.1.14` → `v46.1.15` |
---
### Release Notes
<details>
<summary>renovatebot/github-action (renovatebot/github-action)</summary>
###
[`v46.1.15`](https://redirect.github.com/renovatebot/github-action/releases/tag/v46.1.15)
[Compare
Source](https://redirect.github.com/renovatebot/github-action/compare/v46.1.14...v46.1.15)
##### Documentation
- update references to actions/checkout to v6.0.3
([#​1033](https://redirect.github.com/renovatebot/github-action/issues/1033))
([fb473e1](fb473e186b))
- update references to renovatebot/github-action to v46.1.14
([34e09dd](34e09dd76c))
##### Miscellaneous Chores
- **deps:** update linters to v8.60.0
([1abcc51](1abcc518dc))
- **deps:** update node.js to v24.16.0
([7bbd8b1](7bbd8b12ba))
- **deps:** update pnpm to v10.34.1
([fc48fa8](fc48fa8e31))
- **deps:** update semantic-release monorepo to v12.0.8
([7ae9fb9](7ae9fb9e94))
##### Build System
- **deps:** lock file maintenance
([3e7e656](3e7e6563b3))
##### Continuous Integration
- **deps:** update actions/checkout action to v6.0.3
([bb87b51](bb87b5131a))
- **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.171.3
([f4736a8](f4736a876f))
- **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.173.0
([4374486](4374486206))
- **deps:** update ghcr.io/renovatebot/renovate docker tag to v43.214.5
([3fbdafe](3fbdafedb1))
- **deps:** update ghcr.io/zizmorcore/zizmor docker tag to v1.25.2
([#​1034](https://redirect.github.com/renovatebot/github-action/issues/1034))
([58252bc](58252bce69))
- **deps:** update zizmorcore/zizmor-action action to v0.5.6
([b8cc935](b8cc935bc1))
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- Only on Monday (`* * * * 1`)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.
👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR has been generated by [Mend
Renovate](https://redirect.github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNSIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
Co-authored-by: bircni <bircni@icloud.com>
Closes#37670.
Today, org members in Gitea only see teams they're a member of. In
larger orgs that hurts onboarding and discoverability — there's no way
to look up which team owns what without asking around. GitHub solves
this with a per-team visibility setting; this PR brings the same model
to Gitea.
## What changes
- Every team gets a `visibility` setting:
- `private` *(default)* — only team members and org owners can see the
team. Same as today's behavior.
- `limited` — listable by any member of the organization. Members and
the repos the team has access to are visible too. Non-org-members still
see nothing.
- `public` — listable by any signed-in user.
- The Owners team visibility is fixed and cannot be changed via
settings.
- Existing teams default to `private`, so this is a no-op for anyone who
doesn't change anything.
## API
- `Team`, `CreateTeamOption`, `EditTeamOption` all gain a `visibility`
field (string enum: `private` | `limited` | `public`).
- `GET /orgs/{org}/teams` and `/orgs/{org}/teams/search` now apply the
same visibility rules as the web UI:
- site admins and org owners still see every team
- other org members see their own teams plus any `limited` or `public`
team
- `private` teams are no longer leaked through these endpoints
- Swagger/OpenAPI specs regenerated.
## UI
View from admin2 (not an owner):
<img width="1669" height="726"
src="https://github.com/user-attachments/assets/daf4bccb-644b-4426-b178-71963aeaf73b"
/>
View from admin (owner):
<img width="2559" height="863"
src="https://github.com/user-attachments/assets/4f22cebc-e9df-4fd2-8ed4-724d31fadb7a"
/>
---------
Signed-off-by: bircni <bircni@icloud.com>
Co-authored-by: TheFox0x7 <thefox0x7@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
## Problem
`GET /repos/{owner}/{repo}/times` and `GET
/repos/{owner}/{repo}/issues/{index}/times` crash with a nil pointer
dereference when the `user` query filter names a user that does not
exist.
## Root cause
In `ListTrackedTimes` and `ListTrackedTimesByRepository`, the
`IsErrUserNotExist` branch sends the 404 but is missing a `return`, so
execution falls through to `opts.UserID = user.ID` with a nil `user`.
---------
Co-authored-by: bircni <bircni@icloud.com>
Fixes#38079
## Regression path
The layout previously had `.commit-status-item .status-context { flex: 1
}`,
which let the context fill remaining space and ellipsize. That rule was
dropped in #37517 ("Refactor pull request view (5)") when the row markup
moved to nested `.flex-text-block` wrappers, so nothing constrained the
left block anymore.
After:
<img width="832" height="242" alt="image"
src="https://github.com/user-attachments/assets/a20019f8-6016-40f7-8901-2808280dc093"
/>
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
* fix incorrect delayWriter call (there is already a defer call)
* split HookPostReceive into small functions
* fix incorrect HookPostReceiveResult response for errors
* fix incorrect AddRepoToLicenseUpdaterQueue call
* make sure repo home and branches page can work without default branch
* make sure default branch is always synchronized between database and
git repo, and fix FIXME
Follow-up to #37987, addressing the unresolved review comments on the
org members search form.
And fix more trivial problems together (see the commit titles)
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Reduces the CI cache growth and disk pressure behind the flaky `No space
left on device` failures in
https://github.com/go-gitea/gitea/issues/37974.
**`go-cache`** — the cache-seeder saved with a `restore-keys` prefix
fallback, so every `go.sum` change restored the previous cache and
re-saved the union; old module versions and stale build objects
accumulated (~3 GB → ~7 GB) and overflowed disk on smaller runners. Drop
`restore-keys` from the seeder **save** branches so each `go.sum` seeds
a clean, size-bounded cache. PR runs keep `restore-keys` for warm-start
fallback.
**`free-disk-space`** — delete the unused preinstalled toolchains in
parallel (~86 s → ~54 s) and log `df -h /` before/after.
Measured during review: the hosted `ubuntu-latest` fleet is
heterogeneous — most runners have ~89 GB free on `/` (a full pgsql
integration shard peaks at ~17 GB used), but a minority arrive nearly
full and fail mid cache-restore. The toolchain deletion is the headroom
that keeps those runners green, so it stays; the cache bound shrinks the
footprint for every runner.
Authored with assistance from Claude (Opus 4.8).
---------
Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: bircni <bircni@icloud.com>
[actions-proto-go v0.6.0](https://gitea.com/gitea/actions-proto-go) adds
a
`capabilities` field to `RegisterRequest` and `DeclareRequest`. This
lets a
runner advertise the transitional `cancelling` capability directly in
the proto
message instead of through the out-of-band mechanism we used while the
proto
bump was pending.
This PR:
- Bumps `gitea.dev/actions-proto-go` to `v0.6.0`.
- Drops the forward-compat `capabilityGetter` type-assertion shim and
the
`runnerRequestHasCancellingCapability` helper, reading
`GetCapabilities()`
directly (now part of the `declareRequest` interface).
- Removes the "capability state unknown → preserve existing value"
branch.
## Why the behaviour change is correct
The shim and the `(hasSupport, known)` two-value return only existed
because the
old proto had no `capabilities` field, so we couldn't tell "runner
doesn't
support it" from "we can't see the field." With v0.6.0 the field is
always
present. Since proto3 repeated fields have no presence, "no capabilities
sent"
now unambiguously means the runner does not advertise the capability, so
a
runner that omits `cancelling` is correctly recorded as
`HasCancellingSupport =
false`.
There is no regression: prior to this bump Gitea was on `v0.5.0`, where
the
type assertion always failed and `HasCancellingSupport` was therefore
never set
from requests — so no runner relied on the preserved-unknown path.
## Compatibility
The change is wire-compatible in both directions of version skew,
because the
new field uses a previously unused field number (8 on `RegisterRequest`,
3 on
`DeclareRequest`) and the transport uses the binary protobuf codec:
- **Old runner → new Gitea:** the runner omits the field; it decodes to
an empty
capability list. Registration/declaration succeed; the runner simply
doesn't
get the cancelling feature.
- **New runner → old Gitea:** the runner sends the field; the old
server's
generated code doesn't know the field number and silently ignores it.
Registration/declaration succeed.
The feature only activates once both server and runner are on `v0.6.0`.
The registry writes the stored gem name straight into its line-based
compact index, both the shared `/versions` listing (one `GEMNAME
versions md5` line per gem) and the per-package `info/{name}` file. The
parser only rejected an empty name or one containing a slash, so a
`.gem` whose gemspec `name` carries a newline was accepted and persisted
as the package name, letting an authenticated uploader forge extra lines
in the shared index and so spoof additional gem names, versions and
checksums to clients. The name is now checked against the upstream
RubyGems name pattern in the parser, which is the layer that already
validates the version.
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Enable `SQLITE_JOURNAL_MODE = WAL` for the sqlite integration test
config. With modernc as the default driver, concurrent writers serialize
on SQLite's single write lock and the tail of the queue can exceed the
20s busy timeout under CI load. WAL drains the queue fast enough to stay
inside the timeout (removes rollback's fsync-per-commit and
reader-vs-commit blocking) and covers all sqlite integration tests in
one change.
---
This PR was written with the help of Claude Opus 4.7
---------
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Giteabot <teabot@gitea.io>
**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: wxiaoguang <wxiaoguang@gmail.com>
## Summary
Two Gitea Actions workflow files that share the same `name:` and same
job name produced identical commit-status `Context` strings. Because
`GetLatestCommitStatus` groups by `context_hash` (derived from
`Context`), only one row was shown on the PR page — see #35699.
GitHub displays both rows even though they look identical. This change
does the same: the displayed `Context` is unchanged, but `ContextHash`
now mixes in the workflow file path so the two statuses remain distinct
in the dedupe query.
## Notes
- Workflows that omit `name:` now use the workflow file name in the
`Context` (e.g. `ci.yaml / build (push)`) instead of an empty `/ build
(push)`. This changes the `Context` string for unnamed workflows, so any
required-status-check rule that referenced the old string must be
updated after upgrade.
- For statuses created before this change (hashed from `Context` alone),
`createCommitStatus` reuses that legacy hash when a matching row is
still present, so in-flight pending statuses are superseded rather than
orphaned on upgrade.
Fixes#35699
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: silverwind <me@silverwind.io>