Skip to content

Collab link-preview endpoint skips trip membership validation and lets the server fetch attacker-controlled URLs as an open proxy (SSRF)

Moderate
mauriceboe published GHSA-5g6j-4563-wf98 Aug 27, 2026

Software

liketrek/TREK

Affected versions

>= 2.6.0, < 4.0.0

Patched versions

4.0.0

Description

TREK Collab link-preview server-side request forgery via attacker-controlled URL without trip membership check

Summary

TREK v3.4.1 link-preview endpoint skips trip membership validation and lets the server fetch attacker-controlled URLs as an open proxy.

Details

CollabController.linkPreview (collab.controller.ts:281-299) discards user and tripId before passing the attacker url to fetchLinkPreview (collabService.ts:404-451), which fetch()es it (line 418) and relays og metadata, forming an SSRF/open proxy.

Core vulnerable code path:

// server/src/nest/collab/collab.controller.ts:281-299
@Get('link-preview')
  async linkPreview(@CurrentUser() user: User, @Param('tripId') tripId: string, @Query('url') url?: string) {
    // NB: the legacy route does not verify trip access on link-preview; kept 1:1.
    void user; void tripId;
    if (!url) {
      throw new HttpException({ error: 'URL is required' }, 400);
    }
    try {
      const preview = await this.collab.linkPreview(url);

Entry point: no trip membership check (void user; void tripId), no host allowlist; attacker-controlled URL enters server-side outbound request path.

// server/src/services/collabService.ts:404-423
export async function fetchLinkPreview(url: string): Promise<LinkPreviewResult> {
  const parsed = new URL(url);
  const ssrf = await checkSsrf(url, true);
  if (!ssrf.allowed) {
    return { ...fallback, error: ssrf.error } as LinkPreviewResult & { error?: string };
  }
  try {
    const r = await fetch(url, {
      redirect: 'error',
      dispatcher: createPinnedDispatcher(ssrf.resolvedIp!),
    } as any);

Sink: checkSsrf only blocks private/loopback/link-local IPs; public targets pass; fetch executes attacker URL and og metadata is relayed back -> open proxy/SSRF.

POC

Preconditions: any valid TREK account; target is a public service trusting server outbound IP or attacker-controlled probe. PoC: 1. POST /api/auth/login {email,password} -> trek_session cookie. 2. GET /api/trips/1/collab/link-preview?url=https%3A%2F%2Fattacker.example.com%2Fprobe (any tripId). 3. Server requests target from its outbound IP; response relays og:title/og:description/og:image.

Impact

Any registered user uses TREK server as open HTTP proxy to arbitrary public URLs. Main impact: confidentiality of server-reachable resource states/metadata.

Remediation

Add trip membership check (requireTrip + canEdit); use explicit domain allowlist; restrict protocol/size/timeout and re-validate redirects; add rate limiting; regression tests.

Disclosure Notes

Candidate finding (needs_verification). collab.controller.ts:281-299 skips trip membership checks; collabService.ts:404-451 fetches attacker URL and relays og metadata. Default config: public open proxy; internal reachability needs dynamic verification. No vendor-confirmed fix; affected version v3.4.1.

Supplemental Information

Affected products

  • Ecosystem: self-hosted
  • Package name: liketrek/TREK
  • Affected versions: v3.4.1 (to be confirmed)
  • Patched versions: to be confirmed

Severity

  • Scoring method: CVSS v3.1
  • Score: 7.1
  • Vector string: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N

Weaknesses

  • CWE: CWE-918 Server-Side Request Forgery (SSRF)

Severity

Moderate

CVE ID

No known CVE

Weaknesses

Server-Side Request Forgery (SSRF)

The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination. Learn more on MITRE.

Credits