🛡️ CVE-2026-42931 — gitea.dev

⚪ Unknown ✅ No Known Exploit CWE-770 OSV
N/A
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

Gitea: Denial of Service via Unbounded io.ReadAll in NPM Package Tag Endpoint

Summary

An unbounded io.ReadAll(ctx.Req.Body) call in the NPM package tag API endpoint allows any authenticated user to crash the Gitea server by sending a single large HTTP request. The request body is read entirely into memory with no size limit, causing an Out-of-Memory (OOM) kill. With concurrent requests, the attack produces a persistent denial of service that survives automatic restarts.

Details

The [AddPackageTag](https://github.com/go-gitea/gitea/blob/a12f9807933bd463368c6111dbc283d8a65f20f7/routers/api/packages/npm/npm.go#L336) function reads the entire HTTP request body into memory using io.ReadAll() with no size validation:

```go

// routers/api/packages/npm/npm.go:332-341

func AddPackageTag(ctx *context.Context) {

packageName := packageNameFromParams(ctx)

body, err := io.ReadAll(ctx.Req.Body) // NO SIZE LIMIT

if err != nil {

apiError(ctx, http.StatusInternalServerError, err)

return

}

version := strings.Trim(string(body), "\"")

// ...

}

```

This route is registered at [routers/api/packages/api.go:433](https://github.com/go-gitea/gitea/blob/a12f9807933bd463368c6111dbc283d8a65f20f7/routers/api/packages/api.go#L433):

```go

r.Group("/-/package/{id}/dist-tags", func() {

// ...

r.Group("/{tag}", func() {

r.Put("", npm.AddPackageTag) // reqPackageAccess(perm.AccessModeWrite)

r.Delete("", npm.DeletePackageTag)

})

})

```

Why this causes OOM and not just a slow request:

In Go, io.ReadAll() reads into a []byte that grows dynamically. When the incoming data exceeds available memory, the Go runtime attempts to allocate a larger backing array. This allocation fails, triggering an unrecoverable runtime.throw("out of memory") that kills the entire process, not just the goroutine handling the request.

No server-side size limits apply to this endpoint:

Gitea has per-type size limits (e.g., LIMIT_SIZE_NPM) defined in [modules/setting/packages.go](https://github.com/go-gitea/gitea/blob/a12f9807933bd463368c6111dbc283d8a65f20f7/modules/setting/packages.go#L35), but these are only enforced during UploadPackage, not in AddPackageTag. The [mustBytes()](https://github.com/go-gitea/gitea/blob/a12f9807933bd463368c6111dbc283d8a65f20f7/modules/setting/packages.go#L96-L108) function defaults all limits to -1 (unlimited) when not explicitly configured:

```go

// modules/setting/packages.go:96-101

func mustBytes(section ConfigSection, key string) int64 {

const noLimit = "-1"

value := section.Key(key).MustString(noLimit) // defaults to "-1"

if value == noLimit {

return -1

}

```

Even if an admin sets LIMIT_SIZE_NPM, it would not protect this endpoint. AddPackageTag never checks any size limit before calling io.ReadAll().

The Gitea HTTP server has no global request body size limit. The [HashedBuffer](https://github.com/go-gitea/gitea/blob/a12f9807933bd463368c6111dbc283d8a65f20f7/modules/packages/hashed_buffer.go#L20-L33) used for package uploads (which does have a 32MB memory buffer before spilling to disk) is not used for this endpoint. AddPackageTag reads the body directly via io.ReadAll(), bypassing all buffer protections:

```go

// modules/packages/hashed_buffer.go:29-33

const DefaultMemorySize = 32 * 1024 * 1024 // 32MB, which is safe and spills to disk

// but npm.go:336 bypasses this entirely:

body, err := io.ReadAll(ctx.Req.Body) // reads everything into RAM, no limit

```

Access requirements:

  • The route requires reqPackageAccess(perm.AccessModeWrite)
  • Any user has write access to their own package namespace ([services/context/package.go:155-157](https://github.com/go-gitea/gitea/blob/a12f9807933bd463368c6111dbc283d8a65f20f7/services/context/package.go#L155-L157)):

```go

if doer.ID == pkgOwner.ID {

accessMode = perm.AccessModeOwner

}

```

  • No NPM package needs to exist. The OOM occurs at line 336 before the [package lookup at line 343](https://github.com/go-gitea/gitea/blob/a12f9807933bd463368c6111dbc283d8a65f20f7/routers/api/packages/npm/npm.go#L343):

```go

body, err := io.ReadAll(ctx.Req.Body) // line 336; OOM happens here

// ...

pv, err := packages_model.GetVersionByNameAndVersion(...) // line 343, which is never reached

```

PoC

Tested Environment:

  • Gitea instance (tested on v1.26.2 Docker, confirmed in source up to v1.27.0-dev)

Prerequisites: Set up test environment

```yaml

# docker-compose.yml

version: "3"

services:

gitea:

image: gitea/gitea:latest

container_name: gitea-dos-test

environment:

  • GITEA__database__DB_TYPE=sqlite3
  • GITEA__service__DISABLE_REGISTRATION=false

ports:

  • "3000:3000"

deploy:

resources:

limits:

memory: 512M

```

```bash

docker compose up -d

# Complete initial setup in browser at http://localhost:3000

# Register a user account (e.g., user1 / Pas

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is low, an attacker needs low-level privileges on the target. No user interaction is required. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality none, integrity none, availability high.

Weakness class

CVE-2026-42931 is classified as CWE-770: Allocation of Resources Without Limits. Resources are allocated on request with no cap, so a client can exhaust them.

Affected software

CVE-2026-42931 is recorded against 2 packages.

  • code.gitea.io/gitea
  • gitea.dev

Timeline and source

Published on 21 July 2026 and last revised on 27 July 2026. No public exploit is currently recorded for this entry. Record sourced from OSV.

References

github.com (Web)
github.com (Package)
github.com (Web)

Details

Severity Unknown
CVSS Score N/A
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
CWE CWE-770
Public Exploit ✅ No
Source OSV
Published 2026-07-21
Updated 2026-08-12
Modified 2026-07-27
Fix URL N/A

Affected Packages

Software From version Fixed in
code.gitea.io/gitea
gitea.dev

Similar Threats

Free Vulnerability Check

Is your site affected by CVE-2026-42931?

BotEraser helps you identify potentially vulnerable plugins and themes by checking your installation against CVE-2026-42931 and other known CVE records.

Scan My Site Free →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.