[Android] Remote access: fix security drift on video-list and download routes
Nicolas Pomepuy
git at videolan.org
Thu Sep 10 04:41:21 UTC 2026
vlc-android | branch: master | Nicolas Pomepuy <nicolas at videolabs.io> | Wed Sep 9 15:00:03 2026 +0200| [8e84a658d67fc9a9f79f440183bc6495b67c06a5] | committer: Nicolas Pomepuy
Remote access: fix security drift on video-list and download routes
> https://code.videolan.org/videolan/vlc-android/commit/8e84a658d67fc9a9f79f440183bc6495b67c06a5
---
.../routing/RemoteAccessRoutingFile.kt | 1 +
.../routing/RemoteAccessRoutingUtils.kt | 20 ++++++++++++++++++++
.../routing/RemoteAccessRoutingVideo.kt | 5 +----
3 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/routing/RemoteAccessRoutingFile.kt b/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/routing/RemoteAccessRoutingFile.kt
index 89cd88e8c5..b72fd3ab65 100644
--- a/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/routing/RemoteAccessRoutingFile.kt
+++ b/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/routing/RemoteAccessRoutingFile.kt
@@ -466,6 +466,7 @@ fun Route.authenticatedFileRouting(appContext: Context, scope: CoroutineScope, s
}
// Download a file previously prepared
get("/download") {
+ if (!checkPermission(settings) { settings.getBoolean(REMOTE_ACCESS_FILE_BROWSER_CONTENT, false) }) return at get
val requested = call.request.queryParameters["file"] ?: run {
call.respond(HttpStatusCode.BadRequest, "Missing file parameter")
return at get
diff --git a/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/routing/RemoteAccessRoutingUtils.kt b/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/routing/RemoteAccessRoutingUtils.kt
index fd009d2a00..c3f8089483 100644
--- a/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/routing/RemoteAccessRoutingUtils.kt
+++ b/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/routing/RemoteAccessRoutingUtils.kt
@@ -25,6 +25,7 @@
package org.videolan.vlc.remoteaccessserver.routing
import android.content.Context
+import android.content.SharedPreferences
import android.text.format.Formatter
import android.util.Log
import androidx.core.net.toUri
@@ -34,7 +35,9 @@ import io.ktor.http.HttpStatusCode
import io.ktor.http.content.OutgoingContent
import io.ktor.http.content.TextContent
import io.ktor.server.application.ApplicationCall
+import io.ktor.server.application.call
import io.ktor.server.response.respond
+import io.ktor.util.pipeline.PipelineContext
import kotlinx.coroutines.*
import org.videolan.medialibrary.interfaces.media.MediaWrapper
import org.videolan.medialibrary.media.MediaLibraryItem
@@ -46,6 +49,7 @@ import org.videolan.resources.util.observeLiveDataUntil
import org.videolan.tools.livedata.LiveDataset
import org.videolan.vlc.remoteaccessserver.RemoteAccessOTP
import org.videolan.vlc.remoteaccessserver.RemoteAccessServer
+import org.videolan.vlc.remoteaccessserver.RemoteAccessSession.verifyLogin
import org.videolan.vlc.remoteaccessserver.websockets.RemoteAccessWebSockets
import org.videolan.vlc.util.*
import java.io.File
@@ -264,3 +268,19 @@ internal fun File.isSafelyWithin(parentDir: File): Boolean {
val canonicalChild = this.canonicalFile.path
return canonicalChild == canonicalParent || canonicalChild.startsWith(canonicalParent + File.separator)
}
+
+/**
+ * Verifies session authentication and evaluates a permission predicate.
+ * Responds with HTTP 403 Forbidden and returns false if permission check fails.
+ */
+internal suspend inline fun PipelineContext<Unit, ApplicationCall>.checkPermission(
+ settings: SharedPreferences,
+ predicate: () -> Boolean
+): Boolean {
+ verifyLogin(settings)
+ if (!predicate()) {
+ call.respond(HttpStatusCode.Forbidden)
+ return false
+ }
+ return true
+}
diff --git a/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/routing/RemoteAccessRoutingVideo.kt b/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/routing/RemoteAccessRoutingVideo.kt
index f727b94e88..864016ebc4 100644
--- a/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/routing/RemoteAccessRoutingVideo.kt
+++ b/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/routing/RemoteAccessRoutingVideo.kt
@@ -43,10 +43,7 @@ import org.videolan.vlc.remoteaccessserver.utils.serveVideos
fun Route.videoRouting(appContext: Context, settings: SharedPreferences) {
// List of all the videos
get("/video-list") {
- if (!settings.serveVideos(appContext)) {
- call.respond(HttpStatusCode.Forbidden)
- return at get
- }
+ if (!checkPermission(settings) { settings.serveVideos(appContext) }) return at get
val grouping = call.request.queryParameters["grouping"]?.toInt() ?: 0
val groupId = call.request.queryParameters["group"]?.toLong() ?: 0L
val folderId = call.request.queryParameters["folder"]?.toLong() ?: 0L
More information about the Android
mailing list