Skip to main content

Overview

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. 🌐📥➡️😈

Business Impact

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-494 Related 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

Framework-Specific Analysis and Remediation

This vulnerability manifests in two primary ways:
  1. Client-Side (Frontend): Including scripts or stylesheets from CDNs without using Subresource Integrity (SRI).
  2. 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.
  • Python
  • Java
  • .NET(C#)
  • PHP
  • Node.js
  • Ruby

Framework Context

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).

Vulnerable Scenario 1: Missing Subresource Integrity (SRI) in Template

<html>
<head>
  <script src="[https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js](https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js)"></script>
</head>
<body>
  ...
</body>
</html>

Vulnerable Scenario 2: Insecure Server-Side Update Check

A custom admin utility to “check for updates” downloads and runs a script.
# utils/updater.py
import requests
import os

def check_for_updates():
    try:
        # DANGEROUS: Downloading script over HTTP (vulnerable to MitM).
        response = requests.get("[http://updates.example-utility.com/latest.py](http://updates.example-utility.com/latest.py)")
        if response.status_code == 200:
            script_content = response.text
            # DANGEROUS: Executing code downloaded without signature/hash validation.
            exec(script_content)
    except requests.RequestException as e:
        print(f"Failed to check for updates: {e}")

Mitigation and Best Practices

  • 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.

Secure Code Example

<html>
<head>
  <script
    src="[https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js](https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js)"
    integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ=="
    crossorigin="anonymous"
  ></script>
</head>
<body>
  ...
</body>
</html>
# utils/updater_secure.py (Secure Update Concept)
import requests
import hashlib
# Assume 'verify_signature' function exists using a trusted public key
# from cryptography.hazmat.primitives.asymmetric import padding
# from cryptography.hazmat.primitives import hashes

def check_for_updates_secure():
    try:
        # SECURE: Download over HTTPS
        package_url = "[https://updates.example-utility.com/latest.pkg](https://updates.example-utility.com/latest.pkg)"
        manifest_url = "[https://updates.example-utility.com/latest.manifest](https://updates.example-utility.com/latest.manifest)"

        pkg_response = requests.get(package_url, verify=True) # verify=True is default
        manifest_response = requests.get(manifest_url, verify=True)
        pkg_response.raise_for_status()
        manifest_response.raise_for_status()

        package_bytes = pkg_response.content
        manifest = manifest_response.json() # Assume manifest is JSON

        # SECURE: 1. Verify manifest signature (if manifest is signed)
        # if not verify_signature(manifest['signature'], manifest['payload'], trusted_pub_key):
        #    raise Exception("Invalid manifest signature!")

        # SECURE: 2. Verify package hash against manifest
        expected_hash = manifest['package_hash_sha256']
        actual_hash = hashlib.sha256(package_bytes).hexdigest()
        if actual_hash != expected_hash:
             raise Exception("Package hash mismatch!")

        # SECURE: 3. Install/process the verified package (do not use exec!)
        # (e.g., unpack to specific directory, update DB)
        # install_package(package_bytes) # Assume this exists and is safe

    except Exception as e:
        print(f"Secure update failed: {e}")

Testing Strategy

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.