Skip to content

Commit e6e6b0d

Browse files
committed
ytdl_hook: whitelist protocols from urls retrieved from youtube-dl
Not very clean since there's a lot of potential unsafe urls that youtube-dl can give us, depending on whether it's a single url, split tracks, playlists, segmented dash, etc.
1 parent ab868fe commit e6e6b0d

File tree

1 file changed

+47
-7
lines changed

1 file changed

+47
-7
lines changed

Diff for: player/lua/ytdl_hook.lua

+47-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ local ytdl = {
1616

1717
local chapter_list = {}
1818

19+
function Set (t)
20+
local set = {}
21+
for _, v in pairs(t) do set[v] = true end
22+
return set
23+
end
24+
25+
local safe_protos = Set {
26+
"http", "https", "ftp", "ftps",
27+
"rtmp", "rtmps", "rtmpe", "rtmpt", "rtmpts", "rtmpte",
28+
"data"
29+
}
30+
1931
local function exec(args)
2032
local ret = utils.subprocess({args = args})
2133
return ret.status, ret.stdout, ret
@@ -183,6 +195,9 @@ local function edl_track_joined(fragments, protocol, is_live, base)
183195

184196
for i = offset, #fragments do
185197
local fragment = fragments[i]
198+
if not url_is_safe(join_url(base, fragment)) then
199+
return nil
200+
end
186201
table.insert(parts, edl_escape(join_url(base, fragment)))
187202
if fragment.duration then
188203
parts[#parts] =
@@ -208,6 +223,15 @@ local function proto_is_dash(json)
208223
or json["protocol"] == "http_dash_segments"
209224
end
210225

226+
local function url_is_safe(url)
227+
local proto = type(url) == "string" and url:match("^(.+)://") or nil
228+
local safe = proto and safe_protos[proto]
229+
if not safe then
230+
msg.error(("Ignoring potentially unsafe url: '%s'"):format(url))
231+
end
232+
return safe
233+
end
234+
211235
local function add_single_video(json)
212236
local streamurl = ""
213237
local max_bitrate = 0
@@ -218,6 +242,8 @@ local function add_single_video(json)
218242
if not mpd_url then
219243
msg.error("No manifest URL found in JSON data.")
220244
return
245+
elseif not url_is_safe(mpd_url) then
246+
return
221247
end
222248

223249
streamurl = mpd_url
@@ -238,14 +264,18 @@ local function add_single_video(json)
238264
edl_track = edl_track_joined(track.fragments,
239265
track.protocol, json.is_live,
240266
track.fragment_base_url)
267+
local url = edl_track or track.url
268+
if not url_is_safe(url) then
269+
return
270+
end
241271
if track.acodec and track.acodec ~= "none" then
242272
-- audio track
243273
mp.commandv("audio-add",
244-
edl_track or track.url, "auto",
274+
url, "auto",
245275
track.format_note or "")
246276
elseif track.vcodec and track.vcodec ~= "none" then
247277
-- video track
248-
streamurl = edl_track or track.url
278+
streamurl = url
249279
end
250280
end
251281

@@ -264,7 +294,13 @@ local function add_single_video(json)
264294

265295
msg.debug("streamurl: " .. streamurl)
266296

267-
mp.set_property("stream-open-filename", streamurl:gsub("^data:", "data://", 1))
297+
streamurl = streamurl:gsub("^data:", "data://", 1)
298+
299+
if not url_is_safe(streamurl) then
300+
return
301+
end
302+
303+
mp.set_property("stream-open-filename", streamurl)
268304

269305
mp.set_property("file-local-options/force-media-title", json.title)
270306

@@ -526,14 +562,18 @@ mp.add_hook(o.try_ytdl_first and "on_load" or "on_load_fail", 10, function ()
526562
site = entry["webpage_url"]
527563
end
528564

529-
if not (site:find("https?://") == 1) then
530-
site = "ytdl://" .. site
565+
-- links with only youtube id as returned by --flat-playlist
566+
if not site:find("://") then
567+
table.insert(playlist, "ytdl://" .. site)
568+
elseif url_is_safe(site) then
569+
table.insert(playlist, site)
531570
end
532-
table.insert(playlist, site)
533571

534572
end
535573

536-
mp.set_property("stream-open-filename", "memory://" .. table.concat(playlist, "\n"))
574+
if #playlist > 0 then
575+
mp.set_property("stream-open-filename", "memory://" .. table.concat(playlist, "\n"))
576+
end
537577
end
538578

539579
else -- probably a video

0 commit comments

Comments
 (0)