Weakness reference
CWE-830

Inclusion of Web Functionality from an Untrusted Source

This weakness occurs when a website or application loads scripts, stylesheets, or other executable content from a source it does not control or verify. An…

01Summary

This weakness occurs when a website or application loads scripts, stylesheets, or other executable content from a source it does not control or verify. An attacker who compromises that external source—or intercepts the connection to it—can inject malicious code that runs in users' browsers with the same privileges as the hosting site. This is particularly dangerous because the malicious code can steal credentials, redirect users, deface content, or harvest sensitive data.

02How It Happens

The vulnerability arises when developers include external resources (JavaScript files, CSS, iframes, or plugins) without verifying their integrity or ensuring the source is trustworthy. Common scenarios include:

- Loading a library or framework from a CDN without checking for tampering - Embedding third-party widgets or analytics scripts without validating the provider - Dynamically constructing URLs to external resources based on user input or configuration - Failing to use HTTPS or certificate pinning, allowing man-in-the-middle attacks - Trusting a domain or service that later becomes compromised or is sold to a malicious actor

The core issue is that once the external content is loaded, it executes with full access to the page's DOM, cookies, and local storage—the attacker's code is indistinguishable from legitimate application code.

03Real-World Impact

If an attacker successfully injects malicious code through an untrusted source, they can:

- Steal session cookies or authentication tokens, leading to account takeover - Capture keystrokes or form data before it is encrypted and sent to the server - Redirect users to phishing sites or malware distribution pages - Modify page content to spread misinformation or deface the site - Mine cryptocurrency using the user's browser resources - Perform actions on behalf of logged-in users (e.g., change passwords, transfer funds, post content)

The damage is amplified because users trust the hosting domain, not realizing the malicious code originated elsewhere.

04Vulnerable & Fixed Patterns

Vulnerable pattern
# Flask app dynamically loading a script from user-controlled input
from flask import Flask, render_template_string

app = Flask(__name__)

@app.route('/page')
def load_page():
    script_source = request.args.get('script_url', 'https://example.com/default.js')
    html = f'<html><body><script src="{script_source}"></script></body></html>'
    return render_template_string(html)

Why it's vulnerable:
The script URL is taken directly from user input without validation. An attacker can pass a malicious URL, and the browser will load and execute code from that source.

Fixed pattern
from flask import Flask, render_template_string
from urllib.parse import urlparse

app = Flask(__name__)
ALLOWED_DOMAINS = {'cdn.example.com', 'trusted-lib.org'}

@app.route('/page')
def load_page():
    script_source = request.args.get('script_url', 'https://cdn.example.com/default.js')
    parsed = urlparse(script_source)
    
    if parsed.netloc not in ALLOWED_DOMAINS or parsed.scheme != 'https':
        script_source = 'https://cdn.example.com/default.js'
    
    html = f'<html><body><script src="{script_source}"></script></body></html>'
    return render_template_string(html)
Vulnerable pattern
<?php
// Loading a script from a user-supplied URL
$script_url = isset($_GET['lib']) ? $_GET['lib'] : 'https://example.com/lib.js';
?>
<html>
<body>
    <script src="<?php echo $script_url; ?>"></script>
</body>
</html>

Why it's vulnerable:
The script URL is echoed directly into the HTML without validation. An attacker can inject any URL, including one pointing to malicious code.

Fixed pattern
<?php
$allowed_sources = array(
    'https://cdn.example.com/lib.js',
    'https://trusted-lib.org/script.js'
);

$script_url = isset($_GET['lib']) ? $_GET['lib'] : $allowed_sources[0];

if (!in_array($script_url, $allowed_sources, true)) {
    $script_url = $allowed_sources[0];
}
?>
<html>
<body>
    <script src="<?php echo esc_attr($script_url); ?>"></script>
</body>
</html>

05Prevention Checklist

Maintain an allowlist of trusted sources.
Only load scripts, stylesheets, and other resources from domains you control or have explicitly verified and trust. Update this list regularly.
Always use HTTPS.
Enforce HTTPS for all external resource URLs to prevent man-in-the-middle interception and tampering.
Implement Subresource Integrity (SRI).
Add integrity attributes to <script> and <link> tags with cryptographic hashes of the expected content. Browsers will refuse to load resources that don't match.
Avoid dynamic resource URLs based on user input.
If you must construct URLs dynamically, validate and sanitize the input against a strict allowlist; never trust user-supplied domain names or paths.
Use Content Security Policy (CSP).
Set a restrictive CSP header that limits script sources to specific domains, preventing the browser from loading scripts from unauthorized sources.
Regularly audit third-party dependencies.
Review all external libraries and services your site depends on. Remove unused integrations and monitor for security advisories.

06Signs You May Already Be Affected

- Unexpected scripts or stylesheets appearing in your page source that you did not add - Users reporting unusual behavior (redirects, pop-ups, or requests for credentials) when visiting your site - Monitoring tools or browser extensions flagging mixed content warnings or CSP violations - Unusual outbound traffic to unfamiliar domains in your web server or CDN logs - A third-party service you depend on announcing a security breach or compromise