feat: sanity check video IDs with regex

This commit is contained in:
Fijxu 2026-09-14 00:54:47 -03:00
parent 34173a3d84
commit a138436e08
No known key found for this signature in database
GPG Key ID: 32C1DDF333EDA6A4
6 changed files with 31 additions and 9 deletions

View File

@ -38,3 +38,15 @@ end
# some important informations, and that the query should be sent again. # some important informations, and that the query should be sent again.
class RetryOnceException < Exception class RetryOnceException < Exception
end end
# Exception for invalid video IDs.
class InvalidVideoID < InfoException
getter id : String?
def initialize(@id)
end
def message
return "Invalid video ID '#{id}'"
end
end

View File

@ -404,3 +404,10 @@ def invidious_companion_encrypt(data)
encrypted_data = encrypt_ecb_without_salt("#{timestamp}|#{data}", CONFIG.invidious_companion_key) encrypted_data = encrypt_ecb_without_salt("#{timestamp}|#{data}", CONFIG.invidious_companion_key)
return Base64.urlsafe_encode(encrypted_data) return Base64.urlsafe_encode(encrypted_data)
end end
def validate_video_id(id : String) : Bool
# This is the video ID regex. May be need to be changed
# if Youtube ever decides to add more characters to their
# video IDs.
/^[a-zA-Z0-9_-]{11}$/.matches?(id)
end

View File

@ -81,9 +81,10 @@ module Invidious::Routes::API::V1::Authenticated
return error_json(409, "Watch history is disabled in preferences.") return error_json(409, "Watch history is disabled in preferences.")
end end
# Sanity checks
id = env.params.url["id"] id = env.params.url["id"]
if !id.match(/^[a-zA-Z0-9_-]{11}$/) unless validate_video_id(id)
return error_json(400, "Invalid video id.") return error_json(400, InvalidVideoID.new(id))
end end
Invidious::Database::Users.mark_watched(user, id) Invidious::Database::Users.mark_watched(user, id)
@ -309,8 +310,9 @@ module Invidious::Routes::API::V1::Authenticated
end end
video_id = env.params.json["videoId"].try &.as(String) video_id = env.params.json["videoId"].try &.as(String)
if !video_id # Sanity checks
return error_json(403, "Invalid videoId") unless video_id && validate_video_id(video_id)
return error_json(403, InvalidVideoID.new(video_id))
end end
begin begin

View File

@ -32,8 +32,9 @@ module Invidious::Routes::API::V1::Videos
id = env.params.url["id"] id = env.params.url["id"]
region = env.params.query["region"]? || env.params.body["region"]? region = env.params.query["region"]? || env.params.body["region"]?
if id.nil? || id.size != 11 || !id.matches?(/^[\w-]+$/) # Sanity checks
return error_json(400, "Invalid video ID") unless validate_video_id(id)
return error_json(400, InvalidVideoID.new(id))
end end
# See https://github.com/ytdl-org/youtube-dl/blob/6ab30ff50bf6bd0585927cb73c7421bef184f87a/youtube_dl/extractor/youtube.py#L1354 # See https://github.com/ytdl-org/youtube-dl/blob/6ab30ff50bf6bd0585927cb73c7421bef184f87a/youtube_dl/extractor/youtube.py#L1354

View File

@ -268,8 +268,8 @@ module Invidious::Routes::VideoPlayback
itag = env.params.query["itag"]?.try &.to_i? itag = env.params.query["itag"]?.try &.to_i?
# Sanity checks # Sanity checks
if id.nil? || id.size != 11 || !id.matches?(/^[\w-]+$/) unless id && validate_video_id(id)
return error_template(400, "Invalid video ID") return error_json(400, InvalidVideoID.new(id))
end end
if !itag.nil? && (itag <= 0 || itag >= 1000) if !itag.nil? && (itag <= 0 || itag >= 1000)

View File

@ -235,7 +235,7 @@ module Invidious::Routes::Watch
token = env.params.body["csrf_token"]? token = env.params.body["csrf_token"]?
id = env.params.query["id"]? id = env.params.query["id"]?
if !id unless id && validate_video_id(id)
env.response.status_code = 400 env.response.status_code = 400
return return
end end