{"id":"GHSA-p7c4-8x34-8j8f","summary":"TinyIce: Missing authentication on WebRTC ingest endpoint allows unauthorized stream injection","details":"## Title\n\nMissing authentication on WebRTC ingest endpoint allows unauthenticated stream injection in TinyIce\n\n## Ecosystem / Package\n\n- **Ecosystem:** `Go` (or \"Other\" — TinyIce is shipped as a Go binary, not a Go module published to a registry)\n- **Package name:** `github.com/DatanoiseTV/tinyice`\n\n## Affected versions\n\n```\n\u003e= 0.8.95, \u003c= 2.4.1\n```\n\n(Introduced 2026-02-21 in commit `e2b60d6` — \"debug: add Go Live connection tracing and backend data flow logging\" — when `handleWebRTCSourceOffer` was registered at `/webrtc/source-offer` without an authentication check. Every tagged release from `v0.8.95` through `v2.4.1` ships the vulnerable handler.)\n\n## Patched versions\n\n```\n\u003e= 2.5.0\n```\n\n## Severity\n\n- **CVSS 3.1 base score:** 7.4 (High)\n- **CVSS vector:** `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L`\n- **CWE:** [CWE-306: Missing Authentication for Critical Function](https://cwe.mitre.org/data/definitions/306.html)\n\n## Description\n\nTinyIce's WebRTC source-ingest HTTP endpoint, `POST /webrtc/source-offer?mount=\u003cmount\u003e`, accepted any inbound WebRTC SDP offer with no authentication check. The handler routed the offer to `WebRTCManager.HandleSourceOffer`, which then accepted whatever audio/video tracks the peer published and broadcast them on the named mount as if they were the legitimate source.\n\nThe other ingest paths (`POST /\u003cmount\u003e` over HTTP/1 with the icecast `SOURCE` / `PUT` verb, RTMP, SRT) all require the per-mount source password, falling back to `default_source_password` from the config. The WebRTC ingest path didn't.\n\n## Impact\n\nA network attacker who can reach the TinyIce HTTP port can:\n\n1. Identify a target mount (mount names are public — they appear in the directory listing, the player URL, and the YP listing).\n2. Negotiate a WebRTC peer connection with the server.\n3. Publish arbitrary Opus / H.264 to that mount.\n4. Have it broadcast to every listener on the mount.\n\nThis is a high-integrity-impact issue: an attacker can replace a radio's broadcast with their own audio (silence, noise, malicious content, branded competitor content, etc.). Listeners hear what the attacker sends, not what the legitimate publisher intended.\n\nThe legitimate publisher can re-establish their session — TinyIce's source-takeover handshake gives the new offer priority once it arrives, with a 3-second drain of the previous pump goroutine — but the attacker can in principle re-connect immediately after, producing a sustained broadcast hijack until the operator manually intervenes (block at firewall, rotate source passwords once the patch is applied, restart the service).\n\nThere is no direct confidentiality impact through this endpoint: the attacker doesn't gain access to listener data or other mounts' content.\n\n## Workarounds\n\nIf users cannot upgrade immediately:\n\n- **Recommended:** block `POST /webrtc/source-offer` at the reverse proxy in front of TinyIce. The endpoint has no production use case for clients outside the operator's own administration — disabling it loses no functionality unless the consuming application specifically use the browser-based \"go-live\" feature.\n- Restrict TinyIce's HTTP port to a trusted network (VPN, internal LAN). Listener access can still be served via a separately-firewalled CDN if the application needs public listening.\n\n## Detection\n\nTo check whether an application's deployment is exposed, run from outside the network:\n\n```\ncurl -i -X POST 'https://your-tinyice-host/webrtc/source-offer?mount=/anymount' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"type\":\"offer\",\"sdp\":\"v=0\\r\\n\"}'\n```\n\n- If the response is `400 Bad Request` with a JSON body containing an SDP-parsing error from `pion/webrtc`, **a consuming application is vulnerable** — the server tried to negotiate the (malformed) offer without asking for credentials.\n- If the response is `401 Unauthorized` (Basic auth challenge), the consuming application has been patched.\n\nAuthenticated log lines on a patched server will look like:\n\n```\nWARN  Authentication failed for user 'webrtc-source' from 1.2.3.4: invalid source password\n```\n\n## Fix\n\nUpstream commit: [`8067d6b`](https://github.com/DatanoiseTV/tinyice/commit/8067d6b) \"fix(api): require source password on /webrtc/source-offer + CSRF/access on /go-live-chunk\".\n\nThe handler now:\n\n1. Requires either HTTP Basic auth or a `?password=` query parameter.\n2. Compares the supplied password against the per-mount source password (or the `default_source_password` fallback) using bcrypt.\n3. Hooks into the existing brute-force IP rate-limiter (5 failed attempts per IP within 15 minutes triggers a lockout).\n4. Rejects requests for mounts in `disabled_mounts`.\n\nThe same release also tightens an adjacent endpoint, `POST /admin/golive/chunk`, which previously required session authentication but did not verify the session user's per-mount access nor check the CSRF token.\n\n## Timeline\n\n- 2026-02-21 — Vulnerable handler introduced (`e2b60d6`).\n- 2026-05-09 — Vulnerability identified during a maintainer-led audit.\n- 2026-05-09 — Patched in commit `8067d6b`, released as `v2.5.0`.\n- 2026-05-09 — GitHub Security Advisory published, CVE assigned.","aliases":["CVE-2026-45327","GO-2026-5534"],"modified":"2026-06-25T23:11:34.886701319Z","published":"2026-05-18T17:20:17Z","database_specific":{"severity":"HIGH","github_reviewed":true,"github_reviewed_at":"2026-05-18T17:20:17Z","nvd_published_at":"2026-06-05T18:17:27Z","cwe_ids":["CWE-306"]},"references":[{"type":"WEB","url":"https://github.com/DatanoiseTV/tinyice/security/advisories/GHSA-p7c4-8x34-8j8f"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-45327"},{"type":"WEB","url":"https://github.com/DatanoiseTV/tinyice/commit/8067d6b"},{"type":"PACKAGE","url":"https://github.com/DatanoiseTV/tinyice"},{"type":"WEB","url":"https://github.com/DatanoiseTV/tinyice/releases/tag/v2.5.0"}],"affected":[{"package":{"name":"github.com/DatanoiseTV/tinyice","ecosystem":"Go","purl":"pkg:golang/github.com/DatanoiseTV/tinyice"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0.8.95"},{"fixed":"2.5.0"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/05/GHSA-p7c4-8x34-8j8f/GHSA-p7c4-8x34-8j8f.json","last_known_affected_version_range":"\u003c= 2.4.1"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L"}]}