CVE-2023-48705
Executive Summary
CVE-2023-48705 is a stored cross-site scripting (XSS) vulnerability affecting Nautobot, a Network Source of Truth and Network Automation Platform. All users running Nautobot versions earlier than 1.6.6 or 2.0.5 are potentially affected. The vulnerability stems from incorrect usage of Django's mark_safe() API when rendering user-authored content — specifically custom links, job buttons, and computed fields — allowing privileged users to inject and execute arbitrary JavaScript in the browsers of other users viewing pages containing that content. Successful exploitation could lead to session hijacking, credential theft, or unauthorized administrative actions within the Nautobot platform.
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.
No signup required
Technical Analysis
The vulnerability resides in Nautobot's rendering pipeline for three specific types of user-authored content:
- Custom links — user-defined hyperlinks that appear on object detail pages
- Job buttons — custom buttons that trigger automation jobs
- Computed fields — user-defined fields whose values are calculated via templates or expressions
The root cause is the misuse of Django's mark_safe() API. In Django, mark_safe() explicitly designates a string as safe for direct HTML output, bypassing Django's automatic HTML escaping. When user-supplied content is passed through mark_safe() without prior sanitization or proper escaping, any embedded HTML or JavaScript in that content is rendered as-is in the browser.
The maintainers fixed the issue by replacing the incorrect mark_safe() calls with format_html() calls. format_html() is Django's recommended API for building HTML strings from dynamic data because it performs proper HTML escaping on all arguments before inserting them into the format string. This prevents malicious payloads from being interpreted as executable markup.
Attack surface: Any page in Nautobot that renders custom links, job buttons, or computed fields is a potential vector. The vulnerability is exploitable by any authenticated user with permission to create or edit these content types. Because Nautobot is a network automation platform, the stored payload would persist and execute for all subsequent viewers of the affected pages, including administrators and other operators.
Key technical detail from the NVD description: The vulnerability affects "all users of Nautobot versions earlier than 1.6.6 or 2.0.5." The NVD description explicitly names the mark_safe() API and the three content types affected. No other implementation details are provided in the description.
Exploitation Scenarios
Preconditions:
- Attacker must have valid credentials and object permissions to create or edit custom links, job buttons, or computed fields in Nautobot
- Target user must view a page that renders the attacker-controlled content
- No public proof-of-concept or exploit code is available; the attack chain is inferred from the vulnerability class (stored XSS)
Step 1 — Reconnaissance / Target Identification:
The attacker identifies a Nautobot instance (typically exposed on ports 80/443 or via VPN). They enumerate accessible features and determine whether they have (or can obtain) the necessary permissions to create custom links, job buttons, or computed fields. Shodan queries such as http.title:"Nautobot" can be used to locate exposed instances.
Step 2 — Flaw Trigger:
The attacker authenticates to the Nautobot web interface and navigates to the content creation/edit forms for custom links, job buttons, or computed fields. Instead of entering benign content, the attacker embeds a JavaScript payload within the content field. Because the application passes this content through mark_safe() (which suppresses auto-escaping), the payload is stored unmodified in the database.
Step 3 — Payload / Execution Method (vulnerability class level): The attacker crafts content containing an HTML/JavaScript payload, such as:
<script>/* malicious payload */</script>
or an event-handler-based payload like <img src=x onerror="/* malicious code */">.
When any user (including administrators) navigates to a page that renders the affected custom link, job button, or computed field, the browser executes the embedded script in the context of the Nautobot application origin.
Step 4 — Post-Exploitation Impact: The malicious script executes in the victim's browser session. Depending on the payload, the attacker could:
- Steal session cookies and hijack authenticated sessions
- Perform unauthorized actions via the Nautobot API using the victim's session token
- Manipulate network configuration data (since Nautobot is a Source of Truth platform)
- Escalate privileges by creating accounts or altering permissions
- Deploy further malicious content to other users
Note: No public PoC is available for this CVE; the attack chain above is inferred from the vulnerability class (stored XSS) and the affected content types named in the CNA title and NVD description.
Impact Assessment
CVSS Score: 7.1 (High)
Attack Vector (AV): Network — the vulnerability is exploitable over the network via the web interface. Attack Complexity (AC): Low — exploitation does not require special conditions beyond the attacker having content-editing permissions. Privileges Required (PR): Low — the attacker must be an authenticated user with object permissions to create/edit the affected content types. User Interaction (UI): Required — a victim must view the compromised page. Scope (S): Changed — the impact extends beyond the vulnerable component; a script executed in one user's browser can compromise the entire application. Confidentiality/Integrity/Availability Impact: Low/Low/Low — the script operates within the user's browser session and can read/modify data accessible to that session.
Business Impact:
- Data integrity: As a Network Source of Truth platform, Nautobot stores authoritative network configuration and device metadata. A compromised session could allow an attacker to alter network configuration data, potentially causing operational disruptions.
- Credential exposure: Session token theft could grant attackers persistent access to the platform.
- Supply-chain risk: Malicious content pushed through job buttons could trigger unauthorized network automation jobs.
Blast Radius: Medium — exploitation requires prior authentication and content-creation permissions, limiting the attack to insiders or compromised accounts. However, the stored XSS nature means the payload propagates to all users who view the affected pages.
EPSS Score: 0.00543 (42.8th percentile) — low probability of active exploitation in the wild; no CISA KEV listing and no known exploit campaigns.
Detection Guidance
Sigma Rule
title: Nautobot Stored XSS Payload in User-Authored Content
id: 9f4e2a1c-3b7d-4e5f-8a9b-1c2d3e4f5a6b
status: experimental
description: Detects potential XSS payloads being submitted to Nautobot content creation/edit endpoints
author: Valtersit Threat Intelligence
date: 2024/01/15
logsource:
category: web
product: nginx
service: http
detection:
selection:
http.url|contains:
- '/api/extras/custom-links/'
- '/api/extras/job-buttons/'
- '/api/extras/computed-fields/'
http.method: 'POST'
http.request_body|contains:
- '<script'
- 'javascript:'
- 'onerror='
- 'onload='
- 'onclick='
- 'onmouseover='
- '<script>'
- '%3Cscript%3E'
condition: selection
timeframe: 10m
falsepositives:
- Legitimate use of HTML in custom link tooltips or descriptions
- Security scanning tools submitting benign XSS payloads
level: high
tags:
- attack.t1190
- attack.t1059.007
- cve.2023.48705
YARA Rule
rule Nautobot_Stored_XSS_CVE_2023_48705
{
meta:
author = "Valtersit Threat Intelligence"
description = "Detects XSS payload patterns in Nautobot user-authored content"
cve = "CVE-2023-48705"
date = "2024-01-15"
severity = "high"
strings:
$s1 = "<script" ascii nocase
$s2 = "javascript:" ascii nocase
$s3 = "onerror=" ascii nocase
$s4 = "onload=" ascii nocase
$s5 = "onclick=" ascii nocase
$s6 = "onmouseover=" ascii nocase
$s7 = "document.cookie" ascii nocase
$s8 = "XMLHttpRequest" ascii nocase
$s9 = "fetch(" ascii nocase
$s10 = "eval(" ascii nocase
$s11 = "mark_safe" ascii nocase
condition:
// Payload indicators in content destined for stored rendering
(any of ($s1, $s2) and any of ($s7, $s8, $s9, $s10)) or
// Suspicious event handlers combined with executable patterns
(any of ($s3, $s4, $s5, $s6) and any of ($s1, $s9, $s10)) or
// Indicator of the vulnerable API pattern itself
($s11)
}
Suricata IDS Rule
alert http any any -> $HOME_NET any (
msg:"NAUTOBOT Stored XSS Payload in User-Authored Content (CVE-2023-48705)";
flow:established,to_server;
http.method;
content:"POST";
http.uri;
content:"/api/extras/";
http.request_body;
content:"<script";
nocase;
http.request_body;
content:"javascript:";
nocase;
reference:cve,2023-48705;
classtype:web-application-attack;
sid:10004870;
rev:1;
metadata:created_at 2024_01_15, updated_at 2024_01_15, cve 2023_48705;
)
Elastic Detection
// Detect XSS payloads in Nautobot API request bodies
sequence by source.ip with maxspan=10m
[ network where event.type == "connection" and destination.port in (80, 443) ]
[ http where
http.request.method == "POST" and
http.request.body.content contains "<script" or
http.request.body.content contains "javascript:" or
http.request.body.content contains "onerror=" or
http.request.body.content contains "onload=" and
(url.path contains "/api/extras/custom-links/" or
url.path contains "/api/extras/job-buttons/" or
url.path contains "/api/extras/computed-fields/")
]
Splunk SPL Query
index=web sourcetype=access_combined
| where method="POST"
| search uri IN ("/api/extras/custom-links/*", "/api/extras/job-buttons/*", "/api/extras/computed-fields/*")
| regex form_data="(?i)(<script|javascript:|onerror=|onload=|onclick=|onmouseover=)"
| eval malicious_payload=if(match(form_data, "(?i)(document\.cookie|XMLHttpRequest|fetch\(|eval\()"), "yes", "no")
| where malicious_payload="yes"
| table _time, src_ip, user, uri, form_data
| sort -_time
Wazuh OSSEC Rule
<group name="nautobot,">
<rule id="100487" level="12">
<if_sid>31122</if_sid>
<regex>(?i)(<script>|javascript:|onerror=|onload=|onclick=|onmouseover=)</regex>
<description>Nautobot: Potential Stored XSS payload detected in user-authored content (CVE-2023-48705)</description>
<group>web_application_attack,xss,</group>
<mitre>
<id>T1190</id>
</mitre>
<options>no_full_log</options>
</rule>
</group>
Mitigation & Patch Guidance
Patch Confidence: 3/4 — LIKELY (confirmed by 2 independent sources: CNA and OSV)
Immediate Mitigations:
- Restrict object permissions to limit which users can create or edit custom links, job buttons, and computed fields. The NVD description explicitly states that "appropriate object permissions can and should be applied."
- Audit existing custom links, job buttons, and computed fields for suspicious content containing script tags or event handlers.
- If upgrade is not immediately possible, monitor logs for POST requests to the affected endpoints containing XSS payload characteristics.
Patch / Upgrade Steps:
- Nautobot 1.6.x LTM users: Upgrade to v1.6.6 (or later within the 1.6.x LTM branch).
- Nautobot 2.0.x users: Upgrade to v2.0.5 (or later within the 2.0.x branch).
- The fix replaces incorrect
mark_safe()calls withformat_html(), which properly escapes HTML in user-supplied content. Verify the upgrade by testing that HTML/JavaScript in custom links and computed fields are rendered as plain text rather than executed. - After patching, review all existing custom links, job buttons, and computed fields to ensure no pre-existing malicious payloads remain.
Long-Term Hardening:
- Enforce least-privilege access: only grant content-creation permissions to trusted administrators.
- Implement Content Security Policy (CSP) headers to mitigate XSS impact even if a payload bypasses input validation.
- Regularly audit Nautobot user permissions and review user-authored content.
- Deploy web application firewall (WAF) rules to detect and block XSS payload patterns targeting the affected endpoints.
- Monitor the Nautobot security advisory channel for future updates.
References
- NVD Entry: https://nvd.nist.gov/vuln/detail/CVE-2023-48705
- Nautobot GitHub Advisory (OSV): https://github.com/nautobot/nautobot/security/advisories
- Nautobot Release Notes (v1.6.6): https://github.com/nautobot/nautobot/releases/tag/v1.6.6
- Nautobot Release Notes (v2.0.5): https://github.com/nautobot/nautobot/releases/tag/v2.0.5
- Django
mark_safe()/format_html()Documentation: https://docs.djangoproject.com/en/stable/utils/html/
Threat Actor Campaigns / In-the-Wild Exploitation: None known at the time of writing. No CISA KEV listing. EPSS score of 0.00543 (42.8th percentile) indicates low current exploitation probability. No public exploit code or PoC has been identified.
Report generated by Valtersit Threat Intelligence — 2024-01-15
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.