CVE-2026-35594: Vikunja Link Share JWT tokens remain valid for 72 hours after share deletion or permission downgrade

Published Apr 10, 2026
·
Updated

Title Link Share JWT tokens remain valid for 72 hours after share deletion or permission downgrade

Description

Vikunja'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).

GetLinkShareFromClaims at pkg/models/linksharing.go lines 88-119 performs zero database queries — it builds the LinkSharing struct purely from JWT claim values (id, hash, projectid, permission, sharedByID). This struct is passed directly to permission checks:

| Function | File | Lines | DB queries | |----------|------|-------|------------| | GetLinkShareFromClaims | linksharing.go | 88-119 | 0 | | Project.CanRead (link share) | projectpermissions.go | 105-108 | 0 | | Project.CanWrite (link share) | projectpermissions.go | 50-53 | 0 | | Project.IsAdmin (link share) | projectpermissions.go | 192-194 | 0 |

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.

Permalink: - GetLinkShareFromClaims: pkg/models/linksharing.go:88-119 - NewLinkShareJWTAuthtoken: pkg/modules/auth/auth.go:141-160 - Permission checks: pkg/models/projectpermissions.go:50-53, 105-108, 192-194 - TTL defaults: pkg/config/config.go:337-339

PoC

bash 1. Create an Admin-level link share on project 42 curl -X PUT "https://vikunja.example.com/api/v1/projects/42/shares" \ -H "Authorization: Bearer <owner-jwt>" \ -H "Content-Type: application/json" \ -d '{"permission": 2}' Response: {"id": 5, "hash": "abc123", ...}

2. Obtain link share JWT (72h TTL, no sid claim) curl -X POST "https://vikunja.example.com/api/v1/shares/abc123/auth" Response: {"token": "<link-share-jwt>"}

3. Delete the link share curl -X DELETE "https://vikunja.example.com/api/v1/projects/42/shares/5" \ -H "Authorization: Bearer <owner-jwt>" 200 OK — share row removed from database

4. Use the deleted share's JWT — STILL WORKS for up to 72 hours curl -X GET "https://vikunja.example.com/api/v1/projects/42/tasks" \ -H "Authorization: Bearer <link-share-jwt>" 200 OK — full task list returned with Admin permissions

5. Permission downgrade variant: Delete Admin share → create Read-only share → old JWT still has Admin access

Impact

- Revoked link shares remain functional for up to 72 hours (default TTL) - Project owners cannot respond to security events (leaked URLs, access revocation) in real time - Permission downgrades have no effect on outstanding tokens - Scope: single project per token, severity scales with permission level (Admin > Write > Read)

Fix

Add database validation in GetLinkShareFromClaims:

go func GetLinkShareFromClaims(claims jwt.MapClaims) (share LinkSharing, err error) { id, is := claims["id"].(float64) if !is { return nil, &ErrLinkShareTokenInvalid{} } // Validate against database s := db.NewSession() defer s.Close() share, err = GetLinkShareByID(s, int64(id)) if err != nil { return nil, err // Share was deleted } // Verify permission not downgraded claimedPermission := Permission(claims["permission"].(float64)) if share.Permission < claimedPermission { return nil, &ErrLinkShareTokenInvalid{} } return share, nil }

Alternatives: shorter TTL with refresh mechanism, token blocklist, or session tracking matching user token pattern.

Other sources

Vikunja is an open-source self-hosted task management platform. Prior to 2.3.0, Vikunja's link share authentication (GetLinkShareFromClaims in pkg/models/linksharing.go) 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). This vulnerability is fixed in 2.3.0.

MITRE

Affected Software

2 affected componentsFixes available
go/code.vikunja.io/api<=2.2.2
2.3.0
Vikunja Vikunja<2.3.0

Event History

Apr 10, 2026
Advisory Published
via GitHub·03:31 PM
Data Sourced
via GitHub·03:31 PM
DescriptionSeverityWeaknessAffected Software
CVE Published
via MITRE·03:55 PM
Data Sourced
via MITRE·03:55 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·04:16 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·04:16 PM
RemedyAffected Software
Free Weekly Intel

Don't miss critical vulnerabilities

Join thousands of security professionals who receive our weekly digest of trending CVEs, zero-days, and exploited vulnerabilities.

No spam. Unsubscribe anytime.

Frequently Asked Questions

1

What is the severity of CVE-2026-35594?

CVE-2026-35594 has a moderate severity due to the potential for unauthorized access to data through stale JWT tokens.

2

How do I fix CVE-2026-35594?

To fix CVE-2026-35594, upgrade Vikunja to version 2.3.0 or later where the issue has been addressed.

3

What are the potential impacts of CVE-2026-35594?

The main impact of CVE-2026-35594 is that deleted shares may still allow access through valid JWT tokens for up to 72 hours.

4

Which Vikunja versions are affected by CVE-2026-35594?

CVE-2026-35594 affects Vikunja versions up to 2.2.2.

5

Is user action required for CVE-2026-35594?

Yes, users need to upgrade to the latest version to mitigate the risks associated with CVE-2026-35594.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203