Joomla Extension - regularlabs.com - SSRF via remote image downloads in Articles Anywhere and Users Anywhere extensions - Content-controlled image URLs could request private or reserved network services, follow unsafe redirects and save responses without validating that they were images. This could result in SSRF, internal-data access or writing attacker-controlled files into a web-accessible folder.
In Progress® Telerik® UI for AJAX prior to v2026.2.708, insufficient validation of content submitted to the RadEditor PDF export feature may allow an authenticated attacker to trigger server-side requests to arbitrary hosts, resulting in outbound network connections and potential exposure of Windows authentication credentials.
Gitea 1.25.4 and earlier versions prior to 1.26.4 contain a server-side request forgery (SSRF) vulnerability in the repository migration endpoint. The vulnerability arises because Gitea validates the initial migration URL to block internal addresses but does not re-validate URLs after following HTTP 302 redirects. This allows a low-privilege user to cause Gitea to access internal services by redirecting from an attacker-controlled server to internal IP addresses, effectively using Gitea as a proxy to access otherwise inaccessible internal resources.
PraisonAI is a multi-agent teams system. Prior to version 4.6.40 of PraisonAI, corresponding to version 1.6.40 of praisonaiagents, `spider_tools` URL validation can be bypassed using alternate loopback host encodings. The tool contains a URL validation function intended to block local or unsafe targets before fetching attacker-controlled URLs. However, the validation only blocks a small set of exact host strings such as `localhost` and `127.0.0.1`. It does not normalize hostnames, resolve DNS, parse numeric IPv4 variants, or validate the final resolved IP address before making the request. As a result, certain URLs may bypass the protection and still reach loopback services. After the weak validation passes, `scrape_page()` calls `requests.Session.get()` on the attacker-controlled URL. This allows an attacker who can influence URLs passed to `scrape_page`, `crawl`, or `extract_text` to induce SSRF requests against loopback-only services. This is a server-side request forgery protection bypass. PraisonAI version 4.6.40 and praisonaiagents version 1.6.40 contain a patch.
A Server-Side Request Forgery (SSRF) vulnerability exists in the themexpert.com JMedia extension for Joomla versions 1.0 through 1.5.4. This vulnerability allows remote URL downloads that could be manipulated to target internal or reserved network addresses. The issue is identified as CWE-918 and has a CVSS 4.0 base score of 5.1, indicating a medium severity level.
## Summary
The fix for GHSA-6jxm-fv7w-rw5j (CVE-2026-23845, "Server-Side Request Forgery (SSRF) via HTML Check API"), shipped in mailpit `v1.28.3`, hardened `internal/htmlcheck/css.go::downloadCSSToBytes` with a 5MB size cap, a `text/css` content-type check, login-info stripping in `isValidURL`, and an opt-in `--block-remote-css-and-fonts` config flag — but **did not add the IP-filtering dialer that the same codebase already uses on the two sister SSRF endpoints** (the proxy handler and link-check). At HEAD `8bc966e61834a24c48b4465da418f75e73be0afd` (2026-05-06), `internal/htmlcheck/css.go::newSafeHTTPClient` is mis-named — it builds an `http.Client` whose `Transport.DialContext` calls `net.Dialer.DialContext` directly with no IP allowlisting. As a result, the SSRF originally reported by Bao Anh Phan still permits the server to dial:
- loopback (`127.0.0.0/8`, `::1`),
- private (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `fc00::/7`),
- link-local incl. **cloud IMDS** (`169.254.0.0/16`, especially `169.254.169.254`),
- CGNAT (`100.64.0.0/10`),
- and any other reserved/multicast range,
— provided the target replies with `HTTP/200` and a content-type beginning with `text/css`. With redirect-following (`CheckRedirect` allows redirects to any `isValidURL` URL with no IP filter), an attacker-controlled public site can redirect mailpit's request into the private network without ever appearing in the email's HTML.
In the default mailpit deploy (no UI auth, no SMTP auth, port 1025/8025 exposed), this is an unauthenticated, network-reachable SSRF triggered by sending an HTML email and then issuing one HTTP `GET` to `/api/v1/message/{id}/html-check`.
## Affected versions
- `internal/htmlcheck/css.go` at HEAD `8bc966e61834a24c48b4465da418f75e73be0afd` (2026-05-06).
- All versions `>= v1.28.3` (the version that shipped the GHSA-6jxm fix). Versions `<= v1.28.2` are vulnerable to the original GHSA-6jxm; versions `>= v1.28.3` carry the still-vulnerable variant described here.
## The incomplete fix
The original GHSA-6jxm fix added size+content-type+login-info hardening to `downloadCSSToBytes`. But the dialer it uses still has no `safeDialContext`. The companion `linkcheck` and `proxy` handlers in the same codebase have all-three protections: size cap, content-type/redirect filter, **AND** a `safeDialContext` that runs `tools.IsInternalIP(ip.IP)` per resolved address — same pattern the htmlcheck dialer should adopt.
Side-by-side at HEAD `8bc966e`:
| File | Function | `safeDialContext` (IP filter)? | TOCTOU-safe (dial-by-IP)? |
|---|---|---|---|
| `internal/linkcheck/status.go::safeDialContext` line 140-163 | dial check | YES | YES (resolved IP joined with port) |
| `server/handlers/proxy.go::safeDialContext` line 393-415 | dial check | YES | YES |
| `internal/htmlcheck/css.go::newSafeHTTPClient` line 275-310 | dial check | **NO** | n/a |
The mis-named `newSafeHTTPClient` reads:
```go
// internal/htmlcheck/css.go:275-310
func newSafeHTTPClient() *http.Client {
dialer := &net.Dialer{
Timeout: 5 * time.Second,
KeepAlive: 30 * time.Second,
}
tr := &http.Transport{
Proxy: nil,
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
return dialer.DialContext(ctx, network, address) // no IP filter
},
...
}
client := &http.Client{
Transport: tr,
Timeout: 15 * time.Second,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
if len(via) >= 3 { return errors.New("too many redirects") }
if !isValidURL(req.URL.String()) { return errors.New("invalid redirect URL") }
return nil
},
}
return client
}
```
`isValidURL` only rejects non-http(s) and userinfo URLs — it does NOT reject internal IPs. Compare `linkcheck/status.go::safeDialContext`:
```go
ips, err := net.DefaultResolver.LookupIPAddr(ctx, host)
...
if !config.AllowInternalHTTPRequests {
for _, ip := range ips {
if tools.IsInternalIP(ip.IP) {
return nil, fmt.Errorf("blocked request to %s (%s): private/reserved address", host, ip)
}
}
}
return dialer.DialContext(ctx, network, net.JoinHostPort(ips[0].IP.String(), port))
```
That's the protection htmlcheck is missing.
## Reachability chain (default deploy)
```
Listen() # config/config.go:36 SMTPListen = "[::]:1025"
↓
SMTP server # internal/smtpd/main.go:222-249 AuthRequired: false, AuthHandler: nil
↓ attacker injects HTML body with <link rel="stylesheet" href="...attacker.com/redirect.css">
↓
storage.Store(...)
↓
Listen() # server/server.go HTTPListen
↓ attacker sends GET /api/v1/message/{id}/html-check
apiv1.HTMLCheck # server/apiv1/other.go:18
↓ no UI auth in default deploy (auth.UICredentials == nil)
htmlcheck.RunTests(msg.HTML)
Apache Syncope contains a Server-Side Request Forgery (SSRF) vulnerability that allows low-privileged authenticated users to exploit the Connectors and Resources check functionality. This vulnerability affects multiple versions of Apache Syncope from 3.0.0-M0 through 3.0.16, 4.0.0-M0 through 4.0.6, and 4.1.0-M0 through 4.1.1. The issue is resolved in versions 4.0.7 and 4.1.2. The vulnerability has a high severity rating with a CVSS score of 8.1.
The Kirki WordPress plugin before 6.0.12 does not validate a user-supplied URL before requesting it server-side, allowing unauthenticated attackers to make the site issue HTTP requests to arbitrary hosts (Server-Side Request Forgery).
CVE-2026-16194 is a server-side request forgery (SSRF) vulnerability in zhayujie CowAgent versions 2.1.0 and 2.1.1. The flaw exists in the WebFetch.execute function of the web_fetch.py file, where manipulation of the url argument can lead to SSRF attacks. This vulnerability can be exploited remotely. The vendor has released version 2.1.2 to address the issue.
CVE-2026-16127 is a server-side request forgery (SSRF) vulnerability in zevorn rt-claw versions up to 0.2.0. It affects the http_request component, specifically the claw_net_get and claw_net_post functions in claw/tools/tool_net.c. The vulnerability allows remote attackers to manipulate the URL argument, potentially causing the server to make unintended requests. The issue was reported early to the project, but no response or fix has been provided yet. Public exploit code exists for this vulnerability.
CloudTAK is a browser-based Common Operating Picture and situational awareness tool compatible with TAK. Prior to version 13.10.0, every route in the ESRI helper family (api/routes/esri.ts) takes a fully attacker-controlled URL from the request (POST /api/esri body url, and the portal / server / layer query parameters on the GET /api/esri/* routes) and passes it into EsriBase / EsriProxyPortal / EsriProxyServer / EsriProxyLayer in api/lib/esri.ts, which fetch it with the bare fetch from @tak-ps/etl. No IP / DNS / hostname classification is applied at any point, so the destination is never validated against private, loopback, or link-local ranges. Any authenticated user (the routes only require Auth.is_auth(config, req, { anyResources: true }), i.e. any token, not an admin) can therefore make the CloudTAK server issue arbitrary outbound GET/POST requests to internal addresses such as the cloud instance-metadata service (169.254.169.254), loopback admin ports (127.0.0.1:<port>), and other hosts reachable only from inside the deployment VPC. This is a full-read SSRF, not blind: on success the upstream JSON body is returned to the caller via res.json(...), and on failure the upstream error string is reflected verbatim as ESRI Server Error: <message>. An attacker can read cloud metadata (and the temporary IAM credentials the instance role exposes), enumerate internal services, and exfiltrate their response bodies. The sniff() URL classifier provides no protection: it only pattern-matches the pathname (/rest, /arcgis/rest, /sharing/rest), so a URL like http://169.254.169.254/arcgis/rest or http://127.0.0.1:8500/rest passes sniff() and is fetched. This issue has been patched in version 13.10.0.
css_parser is a Ruby CSS parser. From 2.2.0 until 3.0.0, CssParser::Parser#read_remote_file in lib/css_parser/parser.rb, and therefore load_uri! and the @import-following branch of add_block!, issued HTTP and HTTPS requests against any host, port, and URI without a scheme allowlist, host or IP filtering, or protection against link-local, loopback, or RFC-1918 addresses. Location: redirects were followed recursively back into the same function, which also serviced file:// URIs, so a single attacker-controlled HTTP redirect could upgrade the bug from SSRF to arbitrary local file disclosure. Any consumer of css_parser that hands it attacker-influenced CSS together with a base_uri: option is exposed. This issue is fixed in version 3.0.0.
Statamic is a Laravel and Git powered content management system (CMS). Prior to 5.73.24 and 6.20.1, the Glide image proxy's URL validation in src/Imaging/RemoteUrlValidator.php and src/Imaging/GuzzleAdapter.php could be bypassed using DNS rebinding. The remote hostname was validated as publicly routable, but resolved again when the image was actually fetched, so an attacker controlling the hostname's DNS could rebind it to an internal address after validation and cause the server to make HTTP requests to internal addresses, including loopback, private network, and cloud metadata endpoints. This affects sites that pass user-supplied URLs to Glide. This issue is fixed in versions 5.73.24 and 6.20.1.
oras-go is a Go library for managing OCI artifacts. Prior to 2.6.1, registry/remote/repository.go in blobStore.completePushAfterInitialPost follows a registry-controlled Location header during monolithic blob upload and reuses the Authorization header from the initial POST request for the subsequent PUT request, allowing a malicious registry to return a cross-host Location and receive the caller's credentials at an attacker-controlled endpoint. This issue is fixed in version 2.6.1.