Skip to Content
BlogCVE-2025-63290: How a single line of code created a vulnerability

CVE-2025-63290: How a single line of code created a vulnerability

Imagine this scenario: You’re working on a confidential project using a popular project management platform. An employee leaves your company, their access is revoked, and their authentication tokens expire; you breathe easy, thinking your data is safe. But what if those “expired” tokens could still secretly monitor every move your team makes in real-time?

Well, this hypothetical scenario could happen in Taiga, an open-source project management platform used by many organizations worldwide.

What is Taiga?

Taiga is a project management platform that helps teams organize their work using agile methodologies. Think of it as a workspace where teams can:

  • Create and manage user stories, tasks, and issues.
  • Track project progress in real-time.
  • Collaborate on documents and wikis.
  • Monitor team activity and productivity.
  • It’s essentially an open-source Jira.

And, like many applications, Taiga uses a microservices architecture with several components working together to provide a seamless experience.

Explaining the Vulnerability: CVE-2025-63290

Understanding JWT Tokens

Before diving into the vulnerability, let’s understand JWT (JSON Web Token) authentication. When I think of a JWT, I picture a student ID card that includes:

  • Who you are (student ID)
  • What you can do (student, professor, etc.)
  • When it expires (expiration timestamp/graduation date)

It’s similar with JWTs; when you log in to an application, you receive this “digital ID card,” and the application checks it before allowing you to access sensitive information. In theory, when the card expires, you should lose access.

Taiga’s Architecture

The architecture consists of several services:

  1. taiga-back: The main API server
  2. taiga-front: User interface
  3. taiga-events: WebSocket service
  4. taiga-protected: Provides token validation services

Each service checks your JWT token before letting you in. In an ideal system, all services should enforce the same rules, including token expiration.

The Flaw

Here’s where things went wrong, while most of Taiga’s services properly validate token expiration, the WebSocket service (taiga-events) had a simple misconfiguration:

taiga-events/src/crypto/index.js
const options = { algorithm: process.env.ALGORITHM || 'HS256', audience: process.env.AUDIENCE || '', issuer: process.env.ISSUER || '', ignoreExpiration: 'true' // ← THE PROBLEM };

That single line ignoreExpiration: 'true' basically tells the WebSocket service: “Don’t worry about checking if tokens are expired, just let everyone in :)“

How I Discovered It

The Contradiction

I wanted a change from Jira, so I decided to try Taiga. I used it for almost a week, but my intrusive thoughts got the better of me, and I started playing with my Docker instance. That’s when I noticed something strange:

# Testing with expired token on the main API curl -H "Authorization: Bearer [EXPIRED_TOKEN]" http://localhost:9000/api/v1/users/me # Result: "Token is invalid or expired" ← Correctly rejected # Testing same expired token on the WebSocket wscat -c ws://localhost:9000/events # Result: Connection successful ← Wait, what?

This contradiction led me to investigate further.

Confirming the Vulnerability

After finding that, I (and my best friend ChatGPT) developed a PoC script  that demonstrated the vulnerability in action.

Essentially, it first analyzes the token to confirm it is expired; then it performs two actions: it connects to the WebSocket using that expired token, and, from the perspective of two different users (privileged and non-privileged), generates activity to see if the “insider” sees it.

EXPIRED TOKEN VALIDATION ======================== Token Payload: { "token_type": "access", "exp": 1758726169, Expired timestamp "user_id": 5 } Current time: 2025-09-24T15:53:11.088Z Token expires: 2025-09-24T15:02:49.000Z TOKEN IS EXPIRED! (Expired 50 minutes ago)

Intelligence Gathering

Once connected with the expired token, the script successfully:

  • Authenticates to the WebSocket service
  • Subscribes to real-time project feeds
  • Intercepts live project activities

The results were as follows:

INTELLIGENCE SUMMARY: - Total Messages Intercepted: 12 - Projects Discovered: 1 (Project ID: 3) - Activity Types: {"change": 6, "create": 6} - Resource IDs Discovered: - userstories: [31, 32] - tasks: [26, 27] - issues: [25, 26]

For a full demonstration, watch the video below:

Real-World Impact: Why This Matters

For Organizations Using Taiga

  1. Employee Departure Risk: When employees leave, their expired tokens can still spy on projects.
  2. Token Theft Impact: Stolen tokens remain effective indefinitely for surveillance.
  3. Compliance Violations: Real-time access without proper authentication violates security policies.
  4. Industrial Espionage: Competitors could gain business intelligence through persistent monitoring.

The Fix

The fix is surprisingly simple and takes about 10 seconds; remove one line of code:

taiga-events/src/crypto/index.js
// BEFORE const options = { algorithm: process.env.ALGORITHM || 'HS256', audience: process.env.AUDIENCE || '', issuer: process.env.ISSUER || '', ignoreExpiration: 'true' // ← Remove this line }; // AFTER const options = { algorithm: process.env.ALGORITHM || 'HS256', audience: process.env.AUDIENCE || '', issuer: process.env.ISSUER || '' };

Conclusion

This vulnerability demonstrates how a single line of code can create a security issue. Perhaps the line was added for debugging and remained until production; no one will know.


This vulnerability has been disclosed to the Taiga development team.

Last updated on