VYPR
Critical severity9.3NVD Advisory· Published May 13, 2026· Updated May 14, 2026

CVE-2026-44364

CVE-2026-44364

Description

MISP modules are autonomous modules that can be used to extend MISP for new services. In 3.0.7 and earlier, a Cross-Site Request Forgery vulnerability in the MISP Modules website allowed an attacker to cause an authenticated user to submit unintended requests to the home endpoint. The vulnerability was due to the home blueprint being exempted from CSRF protection. This could allow modification of session query data in the context of the authenticated user. The issue was fixed by enabling CSRF protection for the affected blueprint and hardening query parsing.

Patches

1
52cda9caa003

fix: [security] csrf in website, and others in modules

https://github.com/MISP/misp-modulesDavid CrucianiApr 29, 2026via ghsa
5 files changed · +43 8
  • misp_modules/modules/expansion/html_to_markdown.py+38 2 modified
    @@ -1,6 +1,9 @@
     import json
    +import socket
     
     import requests
    +import ipaddress
    +from urllib.parse import urlparse
     from bs4 import BeautifulSoup
     from markdownify import markdownify
     
    @@ -24,11 +27,44 @@
     }
     
     
    +
    +BLOCKED_RANGES = [
    +    ipaddress.ip_network("127.0.0.0/8"),
    +    ipaddress.ip_network("10.0.0.0/8"),
    +    ipaddress.ip_network("172.16.0.0/12"),
    +    ipaddress.ip_network("192.168.0.0/16"),
    +    ipaddress.ip_network("169.254.0.0/16"),
    +    ipaddress.ip_network("::1/128"),
    +]
    +
    +def _is_ip_blocked(ip_str: str) -> bool:
    +    ip = ipaddress.ip_address(ip_str)
    +    return any(ip in net for net in BLOCKED_RANGES)
    +
    +
    +def _hostname_resolves_to_blocked_ip(hostname: str) -> bool:
    +    try:
    +        resolved = socket.getaddrinfo(hostname, None)
    +        return any(_is_ip_blocked(info[4][0]) for info in resolved)
    +    except socket.gaierror:
    +        return True
    +
    +
    +def is_safe_url(url: str) -> bool:
    +    parsed = urlparse(url)
    +    if parsed.scheme not in ("http", "https"):
    +        return False
    +    try:
    +        return not _is_ip_blocked(parsed.hostname)
    +    except ValueError:
    +        return not _hostname_resolves_to_blocked_ip(parsed.hostname)
    +
     def fetchHTML(url):
    -    r = requests.get(url)
    +    if not is_safe_url(url):
    +        raise ValueError(f"Blocked URL: {url}")
    +    r = requests.get(url, timeout=10)
         return r.text
     
    -
     def stripUselessTags(html):
         soup = BeautifulSoup(html, "html.parser")
         toRemove = ["script", "head", "header", "footer", "meta", "link"]
    
  • misp_modules/modules/expansion/jinja_template_rendering.py+3 1 modified
    @@ -1,6 +1,7 @@
     #!/usr/bin/env python\
     
     import json
    +import logging
     
     from jinja2.sandbox import SandboxedEnvironment
     
    @@ -41,7 +42,8 @@ def handler(q=False):
         templateData = data.get("data", {})
         try:
             rendered = renderTemplate(templateData, template)
    -    except TypeError:
    +    except Exception as e:
    +        logging.warning("Template render failed: %s", type(e).__name__)
             rendered = ""
     
         r = {"results": [{"types": mispattributes["output"], "values": [rendered]}]}
    
  • misp_modules/modules/expansion/qrcode.py+1 2 modified
    @@ -100,8 +100,7 @@ def fetch_url_image(target_url):
                 target_url,
                 headers=headers,
                 timeout=TIMEOUT_SECONDS,
    -            stream=True,
    -            verify=False
    +            stream=True
             ) as response:  # nosec
                 response.raise_for_status()
     
    
  • website/app/home.py+1 2 modified
    @@ -1,4 +1,3 @@
    -import ast
     import json
     
     from flask import Blueprint, jsonify, render_template, request
    @@ -23,7 +22,7 @@ def home():
     
         sess["admin_user"] = bool(admin_user_active())
         if "query" in request.args:
    -        sess["query"] = ast.literal_eval(request.args.get("query"))
    +        sess["query"] = json.loads(request.args.get("query"))
         if "query" in request.form:
             sess["query"] = json.loads(request.form.get("query"))
         return render_template("home.html")
    
  • website/app/__init__.py+0 1 modified
    @@ -58,7 +58,6 @@ def create_app():
         app.register_blueprint(history_blueprint, url_prefix="/")
         app.register_blueprint(account_blueprint, url_prefix="/")
         app.register_blueprint(external_tools_blueprint, url_prefix="/")
    -    csrf.exempt(home_blueprint)
     
         # Register 404 error handler
         @app.errorhandler(404)
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.