Skip to content

fix(tasks): stats endpoint public without auth or org scope #3430

@PierreBrisorgueil

Description

@PierreBrisorgueil

Problem

/api/tasks/stats is registered with no middleware at all:

// stats — public aggregate endpoint, no auth required
app.route('/api/tasks/stats').get(tasks.stats);

The controller calls Task.estimatedDocumentCount() which returns a global count across all organizations — no scoping, no authentication.

This is inconsistent with other stats endpoints in the stack (e.g. scraps stats) which require JWT + organization scope.

Expected behaviour

Stats endpoints should be either:

  • JWT-protected and org-scopedcountDocuments({ organizationId }) like scraps stats, OR
  • Intentionally public — document the reason explicitly and ensure the returned data cannot leak cross-org information

Fix

Option A (recommended): align with scraps stats pattern

app.route('/api/tasks/stats')
  .all(passport.authenticate('jwt', { session: false }), organization.resolveOrganization, policy.isAllowed)
  .get(tasks.stats);

And scope the repository query to organization._id.

Option B: if public is intentional, add policy.isAllowed at minimum and return only a safe aggregate (no org-specific data).

Migration

Check MIGRATIONS.md — any downstream project relying on unauthenticated access to /api/tasks/stats will need to pass a JWT after this change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions