Skip to content

Validate webhook URLs against SSRF-prone private network ranges #9

Description

@mikewheeleer

Harden webhook registration against SSRF

Description

POST /api/v1/webhooks in src/index.ts accepts any http(s) URL up to 2048 chars. When a future delivery worker dispatches these webhooks, a registered URL pointing at http://169.254.169.254/ or http://localhost/ becomes an SSRF vector against cloud metadata and internal services. This issue blocks private, loopback, and link-local hosts at registration time.

Requirements and context

  • Repository scope: StableRoute-Org/Stableroute-backend only.
  • Parse the submitted URL with new URL() and reject hostnames resolving to loopback (127.0.0.0/8, ::1), private (10/8, 172.16/12, 192.168/16), and link-local (169.254/16) ranges, plus localhost.
  • Reject non-default ports below 1024 unless explicitly allowlisted via env (optional).
  • Return 400 invalid_request with a clear message and requestId.
  • Keep the existing length and scheme checks.

Suggested execution

  • Fork the repo and create a branch
  • git checkout -b enhancement/webhooks-09-ssrf-guard
  • Implement changes
    • Write code in: src/index.ts — add an isPublicWebhookUrl(url) helper used by the webhook handler.
    • Write comprehensive tests in: src/__tests__/index.test.ts — reject metadata IP, loopback, private ranges; accept a public https URL.
    • Add documentation: document the SSRF policy in README.md.
    • Add TSDoc on the validator.
    • Validate security: handle IPv6 literals and uppercase hosts.
  • Test and commit

Test and commit

  • Run npm run build, npm run lint, and npm test.
  • Cover edge cases: 169.254.169.254, [::1], 10.0.0.5, valid public host.
  • Paste full npm test output in the PR.

Example commit message

feat(webhooks): reject SSRF-prone private hosts at registration

Guidelines

  • Minimum 95 percent test coverage for impacted code.
  • Clear, reviewer-focused documentation.
  • Timeframe: 96 hours.

Community & contribution rewards

  • 💬 Join the StableRoute community on Discord for questions, reviews, and faster merges: https://discord.gg/37aCpusvx
  • ⭐ This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project — if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward.

Metadata

Metadata

Assignees

No one assigned

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions