Title
CRITICAL: Remote Code Execution (RCE) via Unverified Sideloading of Plugins in ExternalExtensionLoader
Description
The application includes a plugin system intended to load "Cloudstream" extensions (.cs3 files), which are essentially compiled Dalvik Executables (DEX) / APKs containing executable Kotlin/Java code.
The ExternalExtensionLoader.kt handles downloading and dynamically loading these plugins via DexClassLoader. However, the implementation completely lacks any form of cryptographic signature verification, checksum validation, or origin authentication before executing the loaded code.
From ExternalExtensionLoader.kt:
suspend fun downloadExtension(scraperId: String, downloadUrl: String): File? = withContext(Dispatchers.IO) {
...
val request = Request.Builder().url(downloadUrl).build()
httpClient.newCall(request).execute().use { response ->
val bytes = response.body?.bytes() ?: return@withContext null
val targetFile = getExtensionFile(scraperId)
targetFile.writeBytes(bytes)
...
}
}
After downloading, the file is immediately passed to DexClassLoader and its classes are instantiated via reflection, running code inside the application's process and sandbox.
Furthermore, ExternalRepoParser.kt explicitly accepts http:// URLs for these repositories. Since the application also has usesCleartextTraffic="true" enabled globally, an attacker positioned on the same network (e.g., public Wi-Fi, compromised router, or DNS spoofing) can easily intercept the HTTP request for the plugin and swap the .cs3 file with a malicious payload.
Even if HTTPS is used, relying solely on TLS without verifying a cryptographic signature of the downloaded .cs3 file means that if the third-party plugin repository server is compromised, malicious code will be automatically distributed and executed on all users' TVs.
Proof of Concept
- A user adds an external Cloudstream repository URL in the app.
- The app fetches the repository JSON over HTTP (or HTTPS) and extracts the
downloadUrl for an extension.
- An attacker performs a MITM attack on the
http:// download request, replacing the .cs3 file stream with a crafted DEX file containing a malicious Plugin class.
ExternalExtensionLoader.downloadExtension() saves the file.
DexClassLoader loads the file, and loadClass() instantiates the malicious plugin class.
- The malicious plugin achieves Remote Code Execution (RCE) in the context of the Arvio application, gaining access to all permissions and local data held by the app (e.g., reading user tokens, installing malicious APK updates, exfiltrating viewing history).
Recommended Fix
Dynamic code loading (DexClassLoader) of files downloaded from the internet is inherently extremely dangerous.
- Implement Signature Verification: All
.cs3 extensions must be cryptographically signed by a trusted developer key. Before passing the downloaded file to DexClassLoader, the application must verify the digital signature (e.g., standard APK v2/v3 signature schemes or a custom Ed25519 signature mechanism) against a hardcoded public key or a pinned certificate. If the signature is invalid or missing, the file must be deleted immediately and not loaded.
- Enforce HTTPS: Strictly reject any
http:// URLs in ExternalRepoParser and ensure that all plugin metadata and payloads are fetched securely over TLS.
- Verify File Hashes: If a repository manifest provides SHA-256 checksums for the plugins, the app must hash the downloaded file and ensure it matches the expected checksum before loading it.
/assign
Title
CRITICAL: Remote Code Execution (RCE) via Unverified Sideloading of Plugins in
ExternalExtensionLoaderDescription
The application includes a plugin system intended to load "Cloudstream" extensions (
.cs3files), which are essentially compiled Dalvik Executables (DEX) / APKs containing executable Kotlin/Java code.The
ExternalExtensionLoader.kthandles downloading and dynamically loading these plugins viaDexClassLoader. However, the implementation completely lacks any form of cryptographic signature verification, checksum validation, or origin authentication before executing the loaded code.From
ExternalExtensionLoader.kt:After downloading, the file is immediately passed to
DexClassLoaderand its classes are instantiated via reflection, running code inside the application's process and sandbox.Furthermore,
ExternalRepoParser.ktexplicitly acceptshttp://URLs for these repositories. Since the application also hasusesCleartextTraffic="true"enabled globally, an attacker positioned on the same network (e.g., public Wi-Fi, compromised router, or DNS spoofing) can easily intercept the HTTP request for the plugin and swap the.cs3file with a malicious payload.Even if HTTPS is used, relying solely on TLS without verifying a cryptographic signature of the downloaded
.cs3file means that if the third-party plugin repository server is compromised, malicious code will be automatically distributed and executed on all users' TVs.Proof of Concept
downloadUrlfor an extension.http://download request, replacing the.cs3file stream with a crafted DEX file containing a maliciousPluginclass.ExternalExtensionLoader.downloadExtension()saves the file.DexClassLoaderloads the file, andloadClass()instantiates the malicious plugin class.Recommended Fix
Dynamic code loading (DexClassLoader) of files downloaded from the internet is inherently extremely dangerous.
.cs3extensions must be cryptographically signed by a trusted developer key. Before passing the downloaded file toDexClassLoader, the application must verify the digital signature (e.g., standard APK v2/v3 signature schemes or a custom Ed25519 signature mechanism) against a hardcoded public key or a pinned certificate. If the signature is invalid or missing, the file must be deleted immediately and not loaded.http://URLs inExternalRepoParserand ensure that all plugin metadata and payloads are fetched securely over TLS./assign