diff --git a/android/app/src/main/java/com/remotedisplay/player/util/ImageLoader.kt b/android/app/src/main/java/com/remotedisplay/player/util/ImageLoader.kt index c607496..66b3733 100644 --- a/android/app/src/main/java/com/remotedisplay/player/util/ImageLoader.kt +++ b/android/app/src/main/java/com/remotedisplay/player/util/ImageLoader.kt @@ -44,6 +44,14 @@ object ImageLoader { } fun decodeUrl(url: String, maxW: Int, maxH: Int): Bitmap? { + // Reject anything that isn't HTTP/HTTPS. URL.openConnection() otherwise + // happily handles file://, jar:, ftp:, etc. — which would let a server-supplied + // remote_url read local files off the device or talk to internal services. + val scheme = try { URL(url).protocol?.lowercase() } catch (_: Throwable) { null } + if (scheme != "http" && scheme != "https") { + Log.w(TAG, "Rejecting non-http(s) URL scheme: $scheme") + return null + } return try { val bytes = URL(url).openConnection().apply { connectTimeout = 10_000 diff --git a/frontend/js/views/content-library.js b/frontend/js/views/content-library.js index 8f51d1c..2f22bd5 100644 --- a/frontend/js/views/content-library.js +++ b/frontend/js/views/content-library.js @@ -322,7 +322,7 @@ async function loadContent() {
No media uploaded yet
'} diff --git a/frontend/js/views/video-wall.js b/frontend/js/views/video-wall.js index a76cbe4..d42d505 100644 --- a/frontend/js/views/video-wall.js +++ b/frontend/js/views/video-wall.js @@ -1,5 +1,6 @@ import { api } from '../api.js'; import { showToast } from '../components/toast.js'; +import { esc } from '../utils.js'; const API = (url, opts = {}) => fetch('/api' + url, { headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${localStorage.getItem('token')}`, ...opts.headers }, ...opts }).then(r => r.json()); @@ -98,7 +99,7 @@ async function renderWallEditor(container, wallId) {