Skip to content

[Feature]: Add rate limiting and input validation to public profile click-tracking endpoint to prevent analytics manipulation #341

Description

@prince-pokharna

Summary

The Conn platform includes a real-time analytics system that tracks link clicks via the POST /api/u/:username/links/:id/click endpoint. This endpoint is publicly accessible without authentication — by design, since public profile visitors should not need to log in to register a click. However, without rate limiting or any form of abuse prevention, a single client can artificially inflate click counts by making unlimited repeated requests to this endpoint, rendering the analytics data meaningless.

Problem

  • The POST /api/u/:username/links/:id/click endpoint is unauthenticated and currently has no per-IP or per-session rate limiting.
  • A simple curl loop or a browser script can send thousands of click events in seconds, inflating a link's click count arbitrarily.
  • The analytics data — specifically the "top-performing links" metric displayed on the dashboard — is directly driven by these click counts and is therefore vulnerable to manipulation.
  • For a SaaS product where analytics is a core value proposition (especially for paid tiers), fabricated metrics destroy user trust.

Impact

  • Creators on the platform making decisions based on analytics data (e.g., which links to promote) may act on manipulated numbers.
  • Competitors or bad actors can artificially inflate or distort a public profile's analytics.
  • On a free-tier serverless deployment (Vercel), abusive bot traffic against this endpoint can exhaust function invocation limits.

Proposed Solution

I would like to implement a layered abuse prevention strategy on the click-tracking endpoint:

  1. IP-based rate limiting using express-rate-limit: Limit each IP to a maximum of 1 click registration per link per 10-minute window:
const rateLimit = require('express-rate-limit');

const clickLimiter = rateLimit({
  windowMs: 10 * 60 * 1000, // 10 minutes
  max: 1,
  keyGenerator: (req) => `${req.ip}-${req.params.username}-${req.params.id}`,
  message: { error: 'Too many click requests. Please try again later.' },
  standardHeaders: true,
  legacyHeaders: false,
});

app.post('/api/u/:username/links/:id/click', clickLimiter, handleClick);
  1. Input sanitization: Validate that :username matches the allowed character set (alphanumeric + underscores, max 30 chars) and that :id is a valid UUID or integer before hitting the database.

  2. Optional: Bot detection header check: Reject requests that lack a standard User-Agent header or that present known bot signatures, as an additional heuristic layer.

I am happy to implement this end-to-end. Could you please assign this issue to me?

Labels: security, enhancement, analytics, help wanted, GSSoC 2026

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions