[PR] avformat/rtsp: clear authentication on cross-origin redirects (PR #23904)

michaelni via ffmpeg-devel <[email protected]> Sat, 25 Jul 2026 01:57:04 -0000
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <178494462504.59.1711605164270027867@29965ddac10e>
PR #23904 opened by michaelni
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23904
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23904.patch

RTSP redirects retain URL credentials and authentication state when a
Location URI changes to another origin. This can forward reusable
credentials to a server with a different scheme, host, or port.

Clear the stored credentials and authentication state when the redirect
crosses an origin boundary. Preserve them for same-origin redirects.

Fixes: cross-origin credential disclosure
Fixes: rtsp_redirect_auth_leak_poc.py
Fixes: VaKaPOnfN02z



>From 84e0ee6ce0b03e1a8a0263dfad4073d5d1c1d512 Mon Sep 17 00:00:00 2001
From: Abdessamie <[email protected]>
Date: Wed, 22 Jul 2026 06:21:26 +0200
Subject: [PATCH] avformat/rtsp: clear authentication on cross-origin redirects

RTSP redirects retain URL credentials and authentication state when a
Location URI changes to another origin. This can forward reusable
credentials to a server with a different scheme, host, or port.

Clear the stored credentials and authentication state when the redirect
crosses an origin boundary. Preserve them for same-origin redirects.

Fixes: cross-origin credential disclosure
Fixes: rtsp_redirect_auth_leak_poc.py
Fixes: VaKaPOnfN02z
---
 libavformat/rtsp.c | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 20baacf0c6..b6f58f3102 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -1868,6 +1868,32 @@ void ff_rtsp_close_connections(AVFormatContext *s)
     ffurl_closep(&rt->rtsp_hd);
 }
 
+static int rtsp_url_same_origin(const char *url1, const char *url2)
+{
+    char proto1[128], proto2[128];
+    char host1[1024], host2[1024];
+    int port1, port2;
+
+    av_url_split(proto1, sizeof(proto1), NULL, 0, host1, sizeof(host1),
+                 &port1, NULL, 0, url1);
+    av_url_split(proto2, sizeof(proto2), NULL, 0, host2, sizeof(host2),
+                 &port2, NULL, 0, url2);
+
+    if (!proto1[0] || !proto2[0] || !host1[0] || !host2[0])
+        return 0;
+
+    if (port1 < 0)
+        port1 = !av_strcasecmp(proto1, "rtsps") ? RTSPS_DEFAULT_PORT
+                                                : RTSP_DEFAULT_PORT;
+    if (port2 < 0)
+        port2 = !av_strcasecmp(proto2, "rtsps") ? RTSPS_DEFAULT_PORT
+                                                : RTSP_DEFAULT_PORT;
+
+    return !av_strcasecmp(proto1, proto2) &&
+           !av_strcasecmp(host1, host2) &&
+           port1 == port2;
+}
+
 int ff_rtsp_connect(AVFormatContext *s)
 {
     RTSPState *rt = s->priv_data;
@@ -2181,7 +2207,13 @@ redirect:
     ff_rtsp_close_streams(s);
     ff_rtsp_close_connections(s);
     if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) {
-        int ret = ff_format_check_set_url(s, reply->location);
+        int ret;
+
+        if (!rtsp_url_same_origin(s->url, reply->location)) {
+            memset(rt->auth, 0, sizeof(rt->auth));
+            memset(&rt->auth_state, 0, sizeof(rt->auth_state));
+        }
+        ret = ff_format_check_set_url(s, reply->location);
         if (ret < 0) {
             err = ret;
             goto fail2;
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]