Skip to content
Heist/ feed
Back to feed
HighFix available

Vikunja: Denial of service via decompression bomb in the data import

Type: advisorySources: OSV

### Summary Vikunja lets you export your data as a zip and import it back. The import doesn't limit how large the archive expands to, how many files it contains, or how much storage one user can consume, and it appears to hold the whole archive in memory while processing it. Because the archive is compressed, a ~20 MB upload made of highly compressible content expands to tens of gigabytes once imported. A single crafted upload is enough to exhaust the server's memory or fill its disk and knock the whole instance offline. It can be repeated or run in parallel, since nothing stops a user from starting several imports at once. ### Details The import accepts an archive in the same layout the built-in export produces: a manifest describing projects and tasks, plus the attachment files those tasks reference. Each individual file inside the archive is size-checked, but there's no ceiling on the total uncompressed size or on the number of files, and there's no per-user storage quota anywhere. On top of that, the server seems to buffer every attachment in memory before writing it out, so the peak memory cost is the sum of all decompressed files at once, not one at a time. Compression is the key factor: a file full of a repeating byte (e.g. zeroes) shrinks by roughly a thousand to one. So an archive that fits under the upload size limit (around 20 MB) can describe on the order of a thousand ~20 MB attachments, which the server then expands to tens of gigabytes in RAM and writes to disk

Products
code.vikunja.io/api
Affected versions
Not specified
Fixed versions
2.6.0
CVEs
CVE-2026-91979
Confirmed fixed CVEs
Not specified
Updated in this feed
31 Oct 2026, 08:44 UTC · Revision 1

Source evidence

Vikunja: Denial of service via decompression bomb in the data import

core-osv · Original source

Published 9 Oct 2026, 20:52 UTC

### Summary Vikunja lets you export your data as a zip and import it back. The import doesn't limit how large the archive expands to, how many files it contains, or how much storage one user can consume, and it appears to hold the whole archive in memory while processing it. Because the archive is compressed, a ~20 MB upload made of highly compressible content expands to tens of gigabytes once imported. A single crafted upload is enough to exhaust the server's memory or fill its disk and knock the whole instance offline. It can be repeated or run in parallel, since nothing stops a user from starting several imports at once. ### Details The import accepts an archive in the same layout the built-in export produces: a manifest describing projects and tasks, plus the attachment files those tasks reference. Each individual file inside the archive is size-checked, but there's no ceiling on the total uncompressed size or on the number of files, and there's no per-user storage quota anywhere. On top of that, the server seems to buffer every attachment in memory before writing it out, so the peak memory cost is the sum of all decompressed files at once, not one at a time. Compression is the key factor: a file full of a repeating byte (e.g. zeroes) shrinks by roughly a thousand to one. So an archive that fits under the upload size limit (around 20 MB) can describe on the order of a thousand ~20 MB attachments, which the server then expands to tens of gigabytes in RAM and writes to disk

osv:GHSA-w7jp-mf2v-8342

code.vikunja.io/api

Fixed versions: 2.6.0

Complete source record
{
  "id": "b10a10dca16d3439ee13addb1ac5c0ed17dcddec8c5e43f201b3626110f209cf",
  "url": "https://osv.dev/vulnerability/GHSA-w7jp-mf2v-8342",
  "method": "structured",
  "payload": {
    "kind": "advisory",
    "title": "Vikunja: Denial of service via decompression bomb in the data import",
    "summary": "### Summary Vikunja lets you export your data as a zip and import it back. The import doesn't limit how large the archive expands to, how many files it contains, or how much storage one user can consume, and it appears to hold the whole archive in memory while processing it. Because the archive is compressed, a ~20 MB upload made of highly compressible content expands to tens of gigabytes once imported. A single crafted upload is enough to exhaust the server's memory or fill its disk and knock the whole instance offline. It can be repeated or run in parallel, since nothing stops a user from starting several imports at once. ### Details The import accepts an archive in the same layout the built-in export produces: a manifest describing projects and tasks, plus the attachment files those tasks reference. Each individual file inside the archive is size-checked, but there's no ceiling on the total uncompressed size or on the number of files, and there's no per-user storage quota anywhere. On top of that, the server seems to buffer every attachment in memory before writing it out, so the peak memory cost is the sum of all decompressed files at once, not one at a time. Compression is the key factor: a file full of a repeating byte (e.g. zeroes) shrinks by roughly a thousand to one. So an archive that fits under the upload size limit (around 20 MB) can describe on the order of a thousand ~20 MB attachments, which the server then expands to tens of gigabytes in RAM and writes to disk",
    "evidence": "osv:GHSA-w7jp-mf2v-8342",
    "products": [
      {
        "name": {
          "value": "code.vikunja.io/api",
          "evidence": "/affected/0/package/name"
        },
        "prerequisites": [],
        "fixed_versions": [
          {
            "value": "2.6.0",
            "evidence": "/affected/0/ranges"
          }
        ],
        "affected_versions": []
      }
    ],
    "severity": "high",
    "structured": {
      "id": "GHSA-w7jp-mf2v-8342",
      "aliases": [
        "CVE-2026-91979",
        "GHSA-w7jp-mf2v-8342",
        "GO-2026-6756"
      ],
      "metrics": [
        {
          "type": "CVSS_V4",
          "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N"
        }
      ],
      "affected": [
        {
          "ranges": [
            {
              "type": "SEMVER",
              "events": [
                {
                  "introduced": "0"
                },
                {
                  "fixed": "2.6.0"
                }
              ]
            }
          ],
          "package": {
            "name": "code.vikunja.io/api",
            "purl": "pkg:golang/code.vikunja.io/api",
            "ecosystem": "Go"
          },
          "database_specific": {
            "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-w7jp-mf2v-8342/GHSA-w7jp-mf2v-8342.json",
            "last_known_affected_version_range": "<= 2.5.0"
          }
        }
      ],
      "modified": "2026-10-19T21:40:53.010838518Z",
      "provider": "osv",
      "references": [
        "https://github.com/go-vikunja/vikunja/security/advisories/GHSA-w7jp-mf2v-8342",
        "https://nvd.nist.gov/vuln/detail/CVE-2026-91979",
        "https://github.com/go-vikunja/vikunja/pull/3688",
        "https://github.com/go-vikunja/vikunja",
        "https://github.com/go-vikunja/vikunja/releases/tag/v2.6.0",
        "https://www.vulncheck.com/advisories/vikunja-before-2.6.0-denial-of-service-via-decompression-bomb"
      ],
      "provider_metadata": {
        "cwe_ids": [
          "CWE-400",
          "CWE-409",
          "CWE-770"
        ],
        "severity": "HIGH",
        "github_reviewed": true,
        "nvd_published_at": null,
        "github_reviewed_at": "2026-10-09T20:52:52Z"
      }
    },
    "related_cves": [
      {
        "value": "CVE-2026-91979",
        "evidence": "/aliases"
      }
    ],
    "security_relevant": true,
    "severity_evidence": "/database_specific/severity"
  },
  "source_id": "core-osv",
  "document_id": 376748,
  "published_at": "2026-10-09T20:52:52+00:00"
}