Aug 26, 2026·7 min read·1 visit
A structural logic flaw in eml_parser's validation flow allows attackers to obfuscate malicious URLs using HTML entities. The module validates candidate strings before decoding them, causing the extraction engine to discard the obfuscated links. This lets phishing and malware campaigns evade security automated tooling while remaining fully functional in the victim's email client.
A critical logical flaw in the eml_parser Python module prior to version 3.0.2 allows malicious URLs to evade automated security analysis pipelines. By encoding key URI delimiter characters as HTML decimal entities, an attacker can mask indicators of compromise. Security controls, orchestration layers, and sandbox systems fail to detect these links, while downstream Mail User Agents natively reconstruct the malicious hyper-references when processed by end-users. This mechanism undermines the integrity of automated indicator extraction processes within Security Operations Centers.
The Python library eml_parser, developed by GOVCERT-LU, is a foundational component used in threat intelligence, incident response, and automated security orchestration. Its primary function is to parse electronic mail (.eml) files, extracting metadata, headers, attachments, and URLs. This structured output is heavily relied upon by Security Operations Centers (SOCs) to query threat intelligence platforms, execute sandbox analyses, and feed downstream security orchestration, automation, and response (SOAR) workflows.\n\nPrior to version 3.0.2, the library contained a critical logical vulnerability within its URL parsing and sanitization pipeline. This flaw falls under the CWE-116 classification (Improper Encoding or Escaping of Output). Because email ingestion systems parse mail headers and body text dynamically, the integrity of the parsing output is paramount to identifying and blocking malicious payloads before they reach downstream recipients.\n\nWhen processing HTML-formatted email bodies, the parser identifies potential URL strings via regular expressions. However, if an attacker uses HTML entity representation to encode key structural characters of the URL (such as colons, slashes, or periods), the internal verification logic in eml_parser discards the candidate string. Consequently, the extracted JSON payload returned by the parser entirely omits these obfuscated URLs, allowing them to bypass detection rules.
The root cause of this vulnerability lies in the execution order of operations within the clean_found_uri method of eml_parser/parser.py. The function is designed to validate and prune candidate URI strings discovered during body parsing. Specifically, it executes a validation block to filter out non-functional URIs before it performs HTML entity unescaping.\n\nTo filter out invalid or malformed strings, the function checks if the candidate URL contains a physical period character (.) or an opening bracket ([), which is typical for IPv6 literals. If neither character is found in the raw string, the parser assumes the candidate is invalid and immediately discards it by returning None. This validation logic is executed on the raw, encoded string extracted from the HTML message.\n\nIf an attacker replaces structural characters such as a period with its equivalent HTML entity representation (.), the validation condition '.' not in url and '[' not in url evaluates to true. As a result, the function returns None and exits early. The logic that performs entity unescaping (unescape(url)) is situated at the very end of the function and is never executed. This design flaw prevents the normalization of the input string prior to validation.\n\n```mermaid\ngraph LR\n A["Raw HTML Email Input"] --> B["Regex Extract Candidates"]
B --> C["Validate (Checks for '.' and '[')"]
C -- "No literal '.' (Entity encoded)" --> D["Discard URL (Return None)"]
C -- "Literal '.' present" --> E["Unescape Entities"]
E --> F["Store in Output JSON"]
style D fill:#f99,stroke:#333,stroke-width:2px
An analysis of the vulnerable code path in versions prior to 3.0.2 reveals how the validation logic prematurely terminates processing. The code-level mismatch is highlighted below in the comparison of the vulnerable and patched states of the clean_found_uri method.\n\npython\n# Vulnerable implementation in eml_parser/parser.py (Pre-v3.0.2)\n\ndef clean_found_uri(self, url: str) -> str | None:\n # The structural validation occurs immediately on raw input\n if '.' not in url and '[' not in url:\n # Discards valid but encoded URLs like phishing.com\n return None\n\n # Additional sanitization is processed here...\n if url.endswith('://'):\n return None\n\n # Entity unescaping is unreachable for obfuscated payloads\n if '&' in url:\n url = unescape(url)\n\n return url\n\n\nIn version 3.0.2, the vulnerability was resolved by reordering the sequence of actions. The unescaping mechanism was moved to the absolute entry point of the function, ensuring that all subsequent validation checks operate on a normalized canonical string. Additionally, the patch implemented secondary parsing to recursively pull domains directly from successfully cleaned URLs to prevent domain bypasses.\n\npython\n# Patched implementation in eml_parser/parser.py (v3.0.2)\n\ndef clean_found_uri(self, url: str) -> str | None:\n # Fix: Unescape HTML entities at the entry point\n if '&' in url:\n url = unescape(url)\n\n # Validation is now executed on the normalized, unescaped string\n if '.' not in url and '[' not in url:\n return None\n\n if url.endswith('://'):\n return None\n\n return url\n\n\n> [!NOTE]\n> The fix is highly complete and structurally sound. By forcing early normalization, it systematically eliminates any permutation of HTML decimal or hexadecimal entity encoding bypasses against the URL validation check. No variant attacks against the same code path remain feasible under this logic.
Exploitation of this vulnerability requires no special system configuration or authentication, relying entirely on input manipulation. The attack scenario targets automated security analytics tools that ingest email files via python scripts using eml_parser.\n\nAn attacker starts by identifying a target phishing landing page, for example https://phishing.example.com/verify. To bypass detection, the attacker obfuscates the URL delimiters using HTML entity codes, substituting colons, slashes, and dots with their decimal representations: : becomes :, / becomes /, and . becomes .. This converts the hyperlink into the following string: https://phishing.example.com/verify.\n\nThe attacker embeds this obfuscated URL inside an HTML-formatted .eml file. When the security gateway processes the incoming mail file using eml_parser, the regex engine extracts the obfuscated string. However, because the raw extracted string lacks a physical dot character, the validation function discards the candidate. The resulting JSON metadata returned by the parser contains empty lists for both parsed URIs and observed domains, which leads the gateway to classify the email as clean.\n\nFinally, the email is delivered to the recipient. The Mail User Agent (MUA) or webmail interface used by the victim natively parses HTML emails. During rendering, the browser or mail client decodes the decimal entities to establish a valid functional hyperlink. When the victim clicks the link, they are directed to the phishing site, successfully bypassing the analysis pipeline.
The primary security impact of CVE-2026-55618 is the compromise of analytical integrity in automated defensive tools. While it does not directly lead to remote code execution on the server executing eml_parser, it facilitates blind spots in security tools, creating a reliable path for delivery-phase evasion in targeted phishing and social engineering campaigns.\n\nIn automated incident response setups, SOAR playbooks automatically parse incoming suspicious emails reported by users. If a playbook relies on eml_parser to extract and submit indicators to firewalls, secure email gateways, and endpoint detection engines, this vulnerability ensures that high-risk indicators are completely missed. Consequently, threat intelligence platforms will not capture the threat data, and active attacks will go unnoticed.\n\nThe CVSS v3.1 score of 6.5 (Medium) reflects the severity of this issue. Although confidentiality and availability remain unaffected, the integrity impact is high because security controls are rendered ineffective. This logic flaw allows malicious links to bypass inspection, demonstrating how small structural parsing errors can compromise broader defense-in-depth strategies.
Definitive remediation requires upgrading eml_parser to version 3.0.2 or higher. This update resolves the URL validation ordering issue and introduces security improvements that mitigate other vulnerabilities in the parsing pipeline.\n\nFor environments where an immediate upgrade is not feasible, an interim mitigation involves processing the raw email body before it is passed to eml_parser. Utilizing Python's built-in html.unescape function on raw HTML body components before passing the payload to the parser acts as a temporary workaround. This ensures that the validator is supplied with already-normalized inputs.\n\npython\nimport html\nfrom eml_parser import EmlParser\n\ndef safe_parse_eml(raw_eml_bytes):\n # Perform entity normalization prior to parser execution\n decoded_content = html.unescape(raw_eml_bytes.decode('utf-8', errors='ignore'))\n parser = EmlParser()\n return parser.decode_email_bytes(decoded_content.encode('utf-8'))\n\n\nIn addition to the URL extraction fix, version 3.0.2 addresses other vulnerabilities. It mitigates potential Denial of Service (DoS) conditions caused by extremely deep headers and eliminates a Regular Expression Denial of Service (ReDoS) vulnerability in the parentheses clean-up logic (noparenthesis in routing.py). Upgrading therefore hardens the parsing workflow against both bypass and performance-exhaustion vectors.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
eml_parser GOVCERT-LU | < 3.0.2 | 3.0.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-116 |
| Attack Vector | Network (AV:N) |
| CVSS Score | 6.5 |
| EPSS Score | Not registered |
| Impact | High Integrity Loss (Bypass of security analysis pipelines) |
| Exploit Status | Proof of Concept (PoC) |
| KEV Status | Not Listed |
The product does not escape or clean output, or does so incorrectly, which can allow an attacker to bypass validation or introduce injection vulnerabilities.
A denial of service vulnerability in GOVCERT-LU eml_parser before version 3.0.2 allows unauthenticated remote attackers to trigger an unhandled RecursionError exception. The issue arises during the parsing of structured email headers containing excessively nested parentheses representing Comments and Folding White Space (CFWS). Because the parser fails to catch this recursion-limit exception from Python's standard library, processing of the entire mail immediately aborts, which can disrupt automated security triage pipelines and email ingestion components.
Prior to version 3.0.2, GOVCERT-LU's eml_parser library is vulnerable to an algorithmic complexity Denial of Service (DoS) vulnerability via the comment-stripping routine noparenthesis() in routing.py. An unauthenticated attacker can submit a crafted EML file containing nested parenthesized comments to cause complete CPU saturation. This happens due to a quadratic time complexity bottleneck in regex replacement of nested structures.
Whistle prior to version 2.10.3 contains a path traversal vulnerability in its internal service layer. An unauthenticated remote attacker can read arbitrary files on the hosting operating system by issuing a crafted GET request containing relative or absolute file paths to the `/cgi-bin/temp/get` endpoint. This behavior occurs because the application fails open when an input file parameter does not match the temporary file format regex.
An arbitrary file read and write vulnerability exists in the Model Context Protocol (MCP) server endpoints of sublinear-time-solver and consciousness-explorer. By providing unvalidated file paths to the export_state, import_state, saveVectorToFile, and loadVectorFromFile tools, local attackers can read or overwrite sensitive host files.
An Authorization Bypass Through User-Controlled Key (CWE-639 / Insecure Direct Object Reference) vulnerability exists in @arikusi/deepseek-mcp-server starting in version 1.4.2 and fixed in 1.7.0. In Streamable HTTP transport mode, a process-global SessionStore singleton allows any remote client to retrieve or modify active conversation contexts belonging to other clients.
CVE-2026-45018 is a critical command injection vulnerability in Chainlit's Model Context Protocol (MCP) stdio transport backend. By submitting a crafted JSON payload containing dangerous argument options to an unauthenticated HTTP endpoint, a remote attacker can bypass executable validation rules and run arbitrary shell commands with the privileges of the active Python process.