CWE-918
AllowedServer-Side Request Forgery (SSRF)
Abstraction: Base · Status: Incomplete
The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.
4688 vulnerabilities reference this CWE, most recent first.
GHSA-MMC5-FXR8-4XPV
Vulnerability from github – Published: 2022-05-24 17:43 – Updated: 2022-05-24 17:43A server-side request forgery (SSRF) vulnerability in Upgrade.php of gopeak masterlab 2.1.5, via the 'source' parameter.
{
"affected": [],
"aliases": [
"CVE-2020-23534"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-02-25T16:15:00Z",
"severity": "CRITICAL"
},
"details": "A server-side request forgery (SSRF) vulnerability in Upgrade.php of gopeak masterlab 2.1.5, via the \u0027source\u0027 parameter.",
"id": "GHSA-mmc5-fxr8-4xpv",
"modified": "2022-05-24T17:43:02Z",
"published": "2022-05-24T17:43:02Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-23534"
},
{
"type": "WEB",
"url": "https://github.com/gopeak/masterlab/issues/254"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-MMJ8-WCVW-6789
Vulnerability from github – Published: 2026-06-26 21:50 – Updated: 2026-06-26 21:50Summary
The administrative proxy route (cmsproxy) in Aimeos Pagible CMS is vulnerable to a Server-Side Request Forgery (SSRF) attack via DNS Rebinding. A Time-of-Check to Time-of-Use (TOCTOU) race condition exists between the URL validation phase and the actual HTTP request phase, allowing attackers to access internal network resources and cloud metadata endpoints.
Details
Before executing an HTTP request to fetch external content, the AdminController::proxy controller validates the target URL using \Aimeos\Cms\Utils::isValidUrl($url). This function performs a DNS query to verify that the hostname does not resolve to private or reserved IP ranges (e.g., 127.0.0.1, 10.0.0.0/8, 169.254.169.254).
If the validation passes, the application proceeds to the "Use" phase, invoking Guzzle/cURL to send the request. However, Guzzle performs a second DNS lookup to establish the socket connection.
An attacker can exploit this by setting up a malicious DNS server for a domain they control and configuring it with a TTL of 0. 1. During the validation "Check", the DNS server returns a safe, public IP. 2. During the Guzzle "Use", the DNS server returns an internal/private IP.
### POC
1. Attacker registers rebound.test.com with a custom nameserver.
2. Attacker generates a valid proxy token (assuming basic authenticated access).
3. Attacker requests/cmsproxy?url=http://rebound.test.com.
4.isValidUrlchecksrebound.test.com. DNS returns8.8.8.8. Validation passes.
5. Guzzle requestshttp://rebound.test.com. DNS returns169.254.169.254`.
6. The CMS fetches AWS Instance Metadata and returns it to the attacker.
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "aimeos/pagible"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.10.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-49262"
],
"database_specific": {
"cwe_ids": [
"CWE-367",
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-26T21:50:10Z",
"nvd_published_at": null,
"severity": "LOW"
},
"details": "### Summary\nThe administrative proxy route (`cmsproxy`) in Aimeos Pagible CMS is vulnerable to a Server-Side Request Forgery (SSRF) attack via DNS Rebinding. A Time-of-Check to Time-of-Use (TOCTOU) race condition exists between the URL validation phase and the actual HTTP request phase, allowing attackers to access internal network resources and cloud metadata endpoints.\n\n### Details\nBefore executing an HTTP request to fetch external content, the `AdminController::proxy` controller validates the target URL using `\\Aimeos\\Cms\\Utils::isValidUrl($url)`. This function performs a DNS query to verify that the hostname does not resolve to private or reserved IP ranges (e.g., `127.0.0.1`, `10.0.0.0/8`, `169.254.169.254`). \n\nIf the validation passes, the application proceeds to the \"Use\" phase, invoking Guzzle/cURL to send the request. However, Guzzle performs a *second* DNS lookup to establish the socket connection. \n\nAn attacker can exploit this by setting up a malicious DNS server for a domain they control and configuring it with a TTL of 0. \n1. During the validation \"Check\", the DNS server returns a safe, public IP.\n2. During the Guzzle \"Use\", the DNS server returns an internal/private IP.\n\n ### POC\n1. Attacker registers `rebound.test.com with a custom nameserver.\n2. Attacker generates a valid proxy token (assuming basic authenticated access).\n3. Attacker requests `/cmsproxy?url=http://rebound.test.com`.\n4. `isValidUrl` checks `rebound.test.com`. DNS returns `8.8.8.8`. Validation passes.\n5. Guzzle requests `http://rebound.test.com`. DNS returns `169.254.169.254`.\n6. The CMS fetches AWS Instance Metadata and returns it to the attacker.",
"id": "GHSA-mmj8-wcvw-6789",
"modified": "2026-06-26T21:50:10Z",
"published": "2026-06-26T21:50:10Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/aimeos/pagible/security/advisories/GHSA-mmj8-wcvw-6789"
},
{
"type": "PACKAGE",
"url": "https://github.com/aimeos/pagible"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Aimeos Pagible CMS vulnerable to Server Side Request Forgery (SSRF) via DNS rebinding in admin proxy"
}
GHSA-MMMQ-786F-84XQ
Vulnerability from github – Published: 2024-09-09 18:30 – Updated: 2024-09-09 21:31SeaCMS v13.1 was discovered to a Server-Side Request Forgery (SSRF) via the url parameter at /admin_reslib.php.
{
"affected": [],
"aliases": [
"CVE-2024-44721"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-09-09T16:15:02Z",
"severity": "CRITICAL"
},
"details": "SeaCMS v13.1 was discovered to a Server-Side Request Forgery (SSRF) via the url parameter at /admin_reslib.php.",
"id": "GHSA-mmmq-786f-84xq",
"modified": "2024-09-09T21:31:22Z",
"published": "2024-09-09T18:30:30Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-44721"
},
{
"type": "WEB",
"url": "https://github.com/seacms-net/CMS/issues/23"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-MP8F-XWF5-RV6V
Vulnerability from github – Published: 2024-04-29 09:31 – Updated: 2026-04-28 21:35Server-Side Request Forgery (SSRF) vulnerability in Creative Motion Auto Featured Image (Auto Post Thumbnail).This issue affects Auto Featured Image (Auto Post Thumbnail): from n/a through 4.0.0.
{
"affected": [],
"aliases": [
"CVE-2024-33629"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-04-29T08:15:07Z",
"severity": "MODERATE"
},
"details": "Server-Side Request Forgery (SSRF) vulnerability in Creative Motion Auto Featured Image (Auto Post Thumbnail).This issue affects Auto Featured Image (Auto Post Thumbnail): from n/a through 4.0.0.",
"id": "GHSA-mp8f-xwf5-rv6v",
"modified": "2026-04-28T21:35:00Z",
"published": "2024-04-29T09:31:52Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-33629"
},
{
"type": "WEB",
"url": "https://patchstack.com/database/vulnerability/auto-post-thumbnail/wordpress-auto-featured-image-auto-post-thumbnail-plugin-4-0-0-server-side-request-forgery-ssrf-vulnerability?_s_id=cve"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-MPF7-P9X7-96R3
Vulnerability from github – Published: 2026-02-26 15:18 – Updated: 2026-02-26 15:18Summary
The Link Check API (/api/v1/message/{ID}/link-check) is vulnerable to Server-Side Request Forgery (SSRF). The server performs HTTP HEAD requests to every URL found in an email without validating target hosts or filtering private/internal IP addresses. The response returns status codes and status text per link, making this a non-blind SSRF. In the default configuration (no authentication on SMTP or API), this is fully exploitable remotely with zero user interaction.
This is the same class of vulnerability that was fixed in the HTML Check API (CVE-2026-23845 / GHSA-6jxm-fv7w-rw5j) and the screenshot proxy (CVE-2026-21859 / GHSA-8v65-47jx-7mfr), but the Link Check code path was not included in either fix.
Details
The doHead() function in https://github.com/axllent/mailpit/blob/v1.29.0/internal/linkcheck/status.go#L59-L98 creates a plain http.Transport{} and http.Client with no DialContext hook or IP validation:
func doHead(link string, followRedirects bool) (int, error) {
timeout := time.Duration(10 * time.Second)
tr := &http.Transport{}
// ...
client := http.Client{
Timeout: timeout,
Transport: tr,
// ...
}
req, err := http.NewRequest("HEAD", link, nil)
// ...
res, err := client.Do(req) // No IP validation — requests any URL
return res.StatusCode, nil
}
The call chain is:
- GET /api/v1/message/{ID}/link-check hits LinkCheck() in https://github.com/axllent/mailpit/blob/v1.29.0/server/apiv1/other.go#L84
- Which calls linkcheck.RunTests() in https://github.com/axllent/mailpit/blob/v1.29.0/internal/linkcheck/main.go#L16
- Which extracts all URLs from the email's HTML (,
, ) and text body, then passes them to getHTTPStatuses() in https://github.com/axllent/mailpit/blob/v1.29.0/internal/linkcheck/status.go#L14
- Which spawns goroutines calling doHead() for each URL with no filtering
There is no check anywhere in this path to block requests to loopback (127.0.0.0/8), private (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), link-local (169.254.0.0/16), or IPv6 equivalents (::1, fc00::/7, fe80::/10).
PoC
Prerequisites: Mailpit running with default settings (no auth flags). A listener on 127.0.0.1:8081 simulating an internal service.
Step 1 — Start a listener to prove the SSRF:
python3 -m http.server 8081 --bind 127.0.0.1
Step 2 — Send a crafted email via SMTP:
swaks --to recipient@example.com \
--from attacker@example.com \
--server localhost:1025 \
--header "Content-Type: text/html" \
--body '<html><body><a href="http://127.0.0.1:8081/ssrf-proof">click</a><a
href="http://169.254.169.254/latest/meta-data/">metadata</a></body></html>'
Step 3 — Get the message ID:
curl -s http://localhost:8025/api/v1/messages?limit=1 | jq -r '.messages[0].ID'
Or use the shorthand ID latest.
Step 4 — Trigger the link check:
curl -s http://localhost:8025/api/v1/message/latest/link-check | jq .
Expected result:
- The Python HTTP server on port 8081 logs a HEAD /ssrf-proof request from Mailpit.
- The API response contains the status code and status text for each internal target:
{
"Errors": 0,
"Links": [
{"URL": "http://127.0.0.1:8081/ssrf-proof", "StatusCode": 200, "Status": "OK"},
{"URL": "http://169.254.169.254/latest/meta-data/", "StatusCode": 200, "Status": "OK"}
]
}
-- This behavior can be identified by creating a email txt file as
cat email.txt >
From: sender@example.com
To: recipient@example.com
Subject: Email Subject
This is the body of the email.
It can contain multiple lines of text.
http://localhost:8408
-
Start a Python server on port 8408
-
execute the command
mailpit sendmail < email.txt -
Observe a request to your python server and link status on the UI as OK
The attacker now knows both internal services are reachable and gets their exact HTTP status codes, this allows internal port scanning
Impact
Who is impacted: Any Mailpit deployment where an attacker can both send email (SMTP) and access the API. This includes the default configuration, which binds both services to all interfaces with no authentication.
What an attacker can do:
- Internal network scanning — Enumerate hosts and open ports on the internal network by reading status codes and error messages (connection refused vs. timeout vs. 200 OK).
- Cloud metadata access — Reach cloud provider metadata endpoints (169.254.169.254) and infer sensitive information from response codes.
- Service fingerprinting — Identify what services run on internal hosts from their HTTP status codes and response behavior.
- Bypass network segmentation — Use the Mailpit server's network position to reach hosts that are not directly accessible to the attacker.
This is a non-blind SSRF: the attacker gets direct, structured feedback (status code + status text) for every URL, making exploitation straightforward without any timing or side-channel inference.
Remediation
Then standard Go library can be used to identify a local address being requested and deny it.
func isBlockedIP(ip net.IP) bool {
return ip.IsLoopback() ||
ip.IsPrivate() ||
ip.IsLinkLocalUnicast() ||
ip.IsLinkLocalMulticast() ||
ip.IsUnspecified() ||
ip.IsMulticast()
}
- IsLoopback() — 127.0.0.0/8, ::1
- IsPrivate() — 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7
- IsLinkLocalUnicast() — 169.254.0.0/16, fe80::/10 (covers cloud metadata 169.254.169.254)
- IsLinkLocalMulticast() — 224.0.0.0/24, ff02::/16
- IsUnspecified() — 0.0.0.0, ::
- IsMulticast() — 224.0.0.0/4, ff00::/8
And the safe dialer that uses it:
func safeDialContext(dialer *net.Dialer) func(ctx context.Context, network, address string) (net.Conn, error) {
return func(ctx context.Context, network, address string) (net.Conn, error) {
host, port, err := net.SplitHostPort(address)
if err != nil {
return nil, err
}
ips, err := net.DefaultResolver.LookupIPAddr(ctx, host)
if err != nil {
return nil, err
}
for _, ip := range ips {
if isBlockedIP(ip.IP) {
return nil, fmt.Errorf("blocked request to private/reserved address: %s (%s)", host, ip.
}
}
return dialer.DialContext(ctx, network, net.JoinHostPort(ips[0].IP.String(), port))
}
}
Then the doHead() change — replace the bare transport with one that uses the safe dialer, and re-validate URLs on redirect hops:
func doHead(link string, followRedirects bool) (int, error) {
if !isValidLinkURL(link) {
return 0, fmt.Errorf("invalid URL: %s", link)
}
dialer := &net.Dialer{
Timeout: 5 * time.Second,
KeepAlive: 30 * time.Second,
}
tr := &http.Transport{
DialContext: safeDialContext(dialer),
}
if config.AllowUntrustedTLS {
tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} // #nosec
}
client := http.Client{
Timeout: 10 * time.Second,
Transport: tr,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
if len(via) >= 3 {
return errors.New("too many redirects")
}
if !followRedirects {
return http.ErrUseLastResponse
}
if !isValidLinkURL(req.URL.String()) {
return fmt.Errorf("blocked redirect to invalid URL: %s", req.URL)
}
return nil
},
}
req, err := http.NewRequest("HEAD", link, nil)
if err != nil {
logger.Log().Errorf("[link-check] %s", err.Error())
return 0, err
}
req.Header.Set("User-Agent", "Mailpit/"+config.Version)
res, err := client.Do(req)
if err != nil {
if res != nil {
return res.StatusCode, err
}
return 0, err
}
return res.StatusCode, nil
}
func isValidLinkURL(str string) bool {
u, err := url.Parse(str)
return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Hostname() != ""
}
This fix should mitigate the reported SSRF.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.29.1"
},
"package": {
"ecosystem": "Go",
"name": "github.com/axllent/mailpit"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.29.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-27808"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-02-26T15:18:46Z",
"nvd_published_at": "2026-02-26T00:16:26Z",
"severity": "MODERATE"
},
"details": "### Summary\nThe Link Check API (/api/v1/message/{ID}/link-check) is vulnerable to Server-Side Request Forgery (SSRF). The server performs HTTP HEAD requests to every URL found in an email without validating target hosts or filtering private/internal IP addresses. The response returns status codes and status text per link, making this a non-blind SSRF. In the default configuration (no authentication on SMTP or API), this is fully exploitable remotely with zero user interaction.\n\nThis is the same class of vulnerability that was fixed in the HTML Check API (CVE-2026-23845 / GHSA-6jxm-fv7w-rw5j) and the\nscreenshot proxy (CVE-2026-21859 / GHSA-8v65-47jx-7mfr), but the Link Check code path was not included in either fix.\n\n### Details\nThe doHead() function in https://github.com/axllent/mailpit/blob/v1.29.0/internal/linkcheck/status.go#L59-L98 creates a plain http.Transport{} and http.Client with no DialContext hook or IP validation:\n\n```\n func doHead(link string, followRedirects bool) (int, error) {\n timeout := time.Duration(10 * time.Second)\n tr := \u0026http.Transport{}\n // ...\n client := http.Client{\n Timeout: timeout,\n Transport: tr,\n // ...\n }\n req, err := http.NewRequest(\"HEAD\", link, nil)\n // ...\n res, err := client.Do(req) // No IP validation \u2014 requests any URL\n return res.StatusCode, nil\n }\n```\n\n The call chain is:\n\n 1. GET /api/v1/message/{ID}/link-check hits LinkCheck() in\n https://github.com/axllent/mailpit/blob/v1.29.0/server/apiv1/other.go#L84\n 2. Which calls linkcheck.RunTests() in https://github.com/axllent/mailpit/blob/v1.29.0/internal/linkcheck/main.go#L16\n 3. Which extracts all URLs from the email\u0027s HTML (\u003ca href\u003e, \u003cimg src\u003e, \u003clink href\u003e) and text body, then passes them to\n getHTTPStatuses() in https://github.com/axllent/mailpit/blob/v1.29.0/internal/linkcheck/status.go#L14\n 4. Which spawns goroutines calling doHead() for each URL with no filtering\n\n There is no check anywhere in this path to block requests to loopback (127.0.0.0/8), private (10.0.0.0/8, 172.16.0.0/12,\n 192.168.0.0/16), link-local (169.254.0.0/16), or IPv6 equivalents (::1, fc00::/7, fe80::/10).\n \n### PoC\nPrerequisites: Mailpit running with default settings (no auth flags). A listener on 127.0.0.1:8081 simulating an internal service.\n\n Step 1 \u2014 Start a listener to prove the SSRF:\n\n` python3 -m http.server 8081 --bind 127.0.0.1\n`\n\n Step 2 \u2014 Send a crafted email via SMTP:\n\n```\n swaks --to recipient@example.com \\\n --from attacker@example.com \\\n --server localhost:1025 \\\n --header \"Content-Type: text/html\" \\\n --body \u0027\u003chtml\u003e\u003cbody\u003e\u003ca href=\"http://127.0.0.1:8081/ssrf-proof\"\u003eclick\u003c/a\u003e\u003ca\n href=\"http://169.254.169.254/latest/meta-data/\"\u003emetadata\u003c/a\u003e\u003c/body\u003e\u003c/html\u003e\u0027\n```\n\n Step 3 \u2014 Get the message ID:\n\n` curl -s http://localhost:8025/api/v1/messages?limit=1 | jq -r \u0027.messages[0].ID\u0027\n`\n Or use the shorthand ID latest.\n\nStep 4 \u2014 Trigger the link check:\n\n` curl -s http://localhost:8025/api/v1/message/latest/link-check | jq .\n`\n \nExpected result:\n\n - The Python HTTP server on port 8081 logs a HEAD /ssrf-proof request from Mailpit.\n - The API response contains the status code and status text for each internal target:\n\n```\n {\n \"Errors\": 0,\n \"Links\": [\n {\"URL\": \"http://127.0.0.1:8081/ssrf-proof\", \"StatusCode\": 200, \"Status\": \"OK\"},\n {\"URL\": \"http://169.254.169.254/latest/meta-data/\", \"StatusCode\": 200, \"Status\": \"OK\"}\n ]\n }\n```\n\n\n-- This behavior can be identified by creating a email txt file as \n\n```\ncat email.txt \u003e \nFrom: sender@example.com\nTo: recipient@example.com\nSubject: Email Subject\n\nThis is the body of the email.\nIt can contain multiple lines of text.\nhttp://localhost:8408\n```\n\n- Start a Python server on port 8408\n\n- execute the command `mailpit sendmail \u003c email.txt ` \n\n- Observe a request to your python server and link status on the UI as OK\n\n\n The attacker now knows both internal services are reachable and gets their exact HTTP status codes, this allows internal port scanning\n\n### Impact\nWho is impacted: Any Mailpit deployment where an attacker can both send email (SMTP) and access the API. This includes the default configuration, which binds both services to all interfaces with no authentication.\n\n What an attacker can do:\n\n - Internal network scanning \u2014 Enumerate hosts and open ports on the internal network by reading status codes and error messages\n (connection refused vs. timeout vs. 200 OK).\n - Cloud metadata access \u2014 Reach cloud provider metadata endpoints (169.254.169.254) and infer sensitive information from response codes.\n - Service fingerprinting \u2014 Identify what services run on internal hosts from their HTTP status codes and response behavior.\n - Bypass network segmentation \u2014 Use the Mailpit server\u0027s network position to reach hosts that are not directly accessible to the attacker.\n\n This is a non-blind SSRF: the attacker gets direct, structured feedback (status code + status text) for every URL, making\n exploitation straightforward without any timing or side-channel inference.\n\n### Remediation\nThen standard Go library can be used to identify a local address being requested and deny it. \n\n```\nfunc isBlockedIP(ip net.IP) bool {\n return ip.IsLoopback() ||\n ip.IsPrivate() ||\n ip.IsLinkLocalUnicast() ||\n ip.IsLinkLocalMulticast() ||\n ip.IsUnspecified() ||\n ip.IsMulticast()\n }\n\n - IsLoopback() \u2014 127.0.0.0/8, ::1\n - IsPrivate() \u2014 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7\n - IsLinkLocalUnicast() \u2014 169.254.0.0/16, fe80::/10 (covers cloud metadata 169.254.169.254)\n - IsLinkLocalMulticast() \u2014 224.0.0.0/24, ff02::/16\n - IsUnspecified() \u2014 0.0.0.0, ::\n - IsMulticast() \u2014 224.0.0.0/4, ff00::/8\n```\n\n And the safe dialer that uses it:\n\n``` \n func safeDialContext(dialer *net.Dialer) func(ctx context.Context, network, address string) (net.Conn, error) {\n return func(ctx context.Context, network, address string) (net.Conn, error) {\n host, port, err := net.SplitHostPort(address)\n if err != nil {\n return nil, err\n }\n\n ips, err := net.DefaultResolver.LookupIPAddr(ctx, host)\n if err != nil {\n return nil, err\n }\n\n for _, ip := range ips {\n if isBlockedIP(ip.IP) {\n return nil, fmt.Errorf(\"blocked request to private/reserved address: %s (%s)\", host, ip.\n }\n }\n\n return dialer.DialContext(ctx, network, net.JoinHostPort(ips[0].IP.String(), port))\n }\n }\n```\n\n Then the doHead() change \u2014 replace the bare transport with one that uses the safe dialer, and re-validate URLs on\n redirect hops:\n\n```\n func doHead(link string, followRedirects bool) (int, error) {\n if !isValidLinkURL(link) {\n return 0, fmt.Errorf(\"invalid URL: %s\", link)\n }\n\n dialer := \u0026net.Dialer{\n Timeout: 5 * time.Second,\n KeepAlive: 30 * time.Second,\n }\n\n tr := \u0026http.Transport{\n DialContext: safeDialContext(dialer),\n }\n\n if config.AllowUntrustedTLS {\n tr.TLSClientConfig = \u0026tls.Config{InsecureSkipVerify: true} // #nosec\n }\n\n client := http.Client{\n Timeout: 10 * time.Second,\n Transport: tr,\n CheckRedirect: func(req *http.Request, via []*http.Request) error {\n if len(via) \u003e= 3 {\n return errors.New(\"too many redirects\")\n }\n if !followRedirects {\n return http.ErrUseLastResponse\n }\n if !isValidLinkURL(req.URL.String()) {\n return fmt.Errorf(\"blocked redirect to invalid URL: %s\", req.URL)\n }\n return nil\n },\n }\n\n req, err := http.NewRequest(\"HEAD\", link, nil)\n if err != nil {\n logger.Log().Errorf(\"[link-check] %s\", err.Error())\n return 0, err\n }\n\n req.Header.Set(\"User-Agent\", \"Mailpit/\"+config.Version)\n\n res, err := client.Do(req)\n if err != nil {\n if res != nil {\n return res.StatusCode, err\n }\n return 0, err\n }\n\n return res.StatusCode, nil\n }\n\n func isValidLinkURL(str string) bool {\n u, err := url.Parse(str)\n return err == nil \u0026\u0026 (u.Scheme == \"http\" || u.Scheme == \"https\") \u0026\u0026 u.Hostname() != \"\"\n }\n\n```\nThis fix should mitigate the reported SSRF.",
"id": "GHSA-mpf7-p9x7-96r3",
"modified": "2026-02-26T15:18:46Z",
"published": "2026-02-26T15:18:46Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/axllent/mailpit/security/advisories/GHSA-mpf7-p9x7-96r3"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-27808"
},
{
"type": "WEB",
"url": "https://github.com/axllent/mailpit/commit/10ad4df8cc0cd9e51dea1b4410009545eef7fbf5"
},
{
"type": "PACKAGE",
"url": "https://github.com/axllent/mailpit"
},
{
"type": "WEB",
"url": "https://github.com/axllent/mailpit/releases/tag/v1.29.2"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Mailpit is Vulnerable to Server-Side Request Forgery (SSRF) via Link Check API"
}
GHSA-MPGC-X575-HG38
Vulnerability from github – Published: 2023-11-27 18:31 – Updated: 2023-12-01 21:30The WPB Show Core WordPress plugin through 2.2 is vulnerable to server-side request forgery (SSRF) via the path parameter.
{
"affected": [],
"aliases": [
"CVE-2023-5974"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-11-27T17:15:09Z",
"severity": "CRITICAL"
},
"details": "The WPB Show Core WordPress plugin through 2.2 is vulnerable to server-side request forgery (SSRF) via the `path` parameter.",
"id": "GHSA-mpgc-x575-hg38",
"modified": "2023-12-01T21:30:29Z",
"published": "2023-11-27T18:31:14Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-5974"
},
{
"type": "WEB",
"url": "https://wpscan.com/vulnerability/c0136057-f420-4fe7-a147-ecbec7e7a9b5"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-MPHV-75CG-56WG
Vulnerability from github – Published: 2026-02-25 22:59 – Updated: 2026-02-25 22:59Summary
A redirect-based Server-Side Request Forgery (SSRF) bypass exists in RecursiveUrlLoader in @langchain/community. The loader validates the initial URL but allows the underlying fetch to follow redirects automatically, which permits a transition from a safe public URL to an internal or metadata endpoint without revalidation. This is a bypass of the SSRF protections introduced in 1.1.14 (CVE-2026-26019).
Affected Component
- Package:
@langchain/community - Component:
RecursiveUrlLoader - Configuration:
preventOutside(default:true) is insufficient to prevent this bypass when redirects are followed automatically.
Description
RecursiveUrlLoader is a web crawler that recursively follows links from a starting URL. The existing SSRF mitigation validates the initial URL before fetching, but it does not re-validate when the request follows redirects. Because fetch follows redirects by default, an attacker can supply a public URL that passes validation and then redirects to a private network address, localhost, or cloud metadata endpoint.
This constitutes a “check‑then‑act” gap in the request lifecycle: the safety check occurs before the redirect chain is resolved, and the final destination is never validated.
Impact
If an attacker can influence content on a page being crawled (e.g., user‑generated content, untrusted external pages), they can cause the crawler to:
- Fetch cloud instance metadata (AWS, GCP, Azure), potentially exposing credentials or tokens
- Access internal services on private networks (10.x, 172.16.x, 192.168.x)
- Connect to localhost services
- Exfiltrate response data through attacker-controlled redirect chains
This is exploitable in any environment where RecursiveUrlLoader runs with access to internal networks or metadata services, which includes most cloud-hosted deployments.
Attack Scenario
- The crawler is pointed at a public URL that passes initial SSRF validation.
- That URL responds with a 3xx redirect to an internal target.
- The fetch follows the redirect automatically without revalidation.
- The crawler accesses the internal or metadata endpoint.
Example redirector:
https://302.r3dir.me/--to/?url=http://169.254.169.254/latest/meta-data/
Root Cause
- SSRF validation (
validateSafeUrl) is only performed on the initial URL. - Redirects are followed automatically by fetch (
redirect: "follow"default), so the request can change destinations without additional validation.
Resolution
Upgrade to @langchain/community >= 1.1.18, which validates every redirect hop by disabling automatic redirects and re-validating Location targets before following them.
- Automatic redirects are disabled (redirect: "manual").
- Each 3xx Location is resolved and validated with validateSafeUrl() before the next request.
- A maximum redirect limit prevents infinite loops.
Reources
- Original SSRF fix (CVE-2026-26019): enforced origin comparison and added initial URL validation
- https://github.com/langchain-ai/langchainjs/security/advisories/GHSA-gf3v-fwqg-4vh7
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.1.17"
},
"package": {
"ecosystem": "npm",
"name": "@langchain/community"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.1.18"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-27795"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-02-25T22:59:48Z",
"nvd_published_at": "2026-02-25T18:23:41Z",
"severity": "MODERATE"
},
"details": "## Summary\nA redirect-based Server-Side Request Forgery (SSRF) bypass exists in `RecursiveUrlLoader` in `@langchain/community`. The loader validates the initial URL but allows the underlying fetch to follow redirects automatically, which permits a transition from a safe public URL to an internal or metadata endpoint without revalidation. This is a bypass of the SSRF protections introduced in 1.1.14 (CVE-2026-26019).\n\n## Affected Component\n- Package: `@langchain/community`\n- Component: `RecursiveUrlLoader`\n- Configuration: `preventOutside` (default: `true`) is insufficient to prevent this bypass when redirects are followed automatically.\n\n## Description\n`RecursiveUrlLoader` is a web crawler that recursively follows links from a starting URL. The existing SSRF mitigation validates the initial URL before fetching, but it does not re-validate when the request follows redirects. Because fetch follows redirects by default, an attacker can supply a public URL that passes validation and then redirects to a private network address, localhost, or cloud metadata endpoint.\n\nThis constitutes a \u201ccheck\u2011then\u2011act\u201d gap in the request lifecycle: the safety check occurs before the redirect chain is resolved, and the final destination is never validated.\n\n## Impact\nIf an attacker can influence content on a page being crawled (e.g., user\u2011generated content, untrusted external pages), they can cause the crawler to:\n- Fetch cloud instance metadata (AWS, GCP, Azure), potentially exposing credentials or tokens\n- Access internal services on private networks (`10.x`, `172.16.x`, `192.168.x`)\n- Connect to localhost services\n- Exfiltrate response data through attacker-controlled redirect chains\n\nThis is exploitable in any environment where `RecursiveUrlLoader` runs with access to internal networks or metadata services, which includes most cloud-hosted deployments.\n\n## Attack Scenario\n1. The crawler is pointed at a public URL that passes initial SSRF validation.\n2. That URL responds with a 3xx redirect to an internal target.\n3. The fetch follows the redirect automatically without revalidation.\n4. The crawler accesses the internal or metadata endpoint.\n\nExample redirector:\n```\nhttps://302.r3dir.me/--to/?url=http://169.254.169.254/latest/meta-data/\n```\n\n## Root Cause\n- SSRF validation (`validateSafeUrl`) is only performed on the initial URL.\n- Redirects are followed automatically by fetch (`redirect: \"follow\"` default), so the request can change destinations without additional validation.\n\n## Resolution\nUpgrade to `@langchain/community` **\u003e= 1.1.18**, which validates every redirect hop by disabling automatic redirects and re-validating `Location` targets before following them.\n- Automatic redirects are disabled (`redirect: \"manual\"`).\n- Each 3xx `Location` is resolved and validated with `validateSafeUrl()` before the next request.\n- A maximum redirect limit prevents infinite loops.\n\n## Reources\n- Original SSRF fix (CVE-2026-26019): enforced origin comparison and added initial URL validation\n- https://github.com/langchain-ai/langchainjs/security/advisories/GHSA-gf3v-fwqg-4vh7",
"id": "GHSA-mphv-75cg-56wg",
"modified": "2026-02-25T22:59:48Z",
"published": "2026-02-25T22:59:48Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/langchain-ai/langchainjs/security/advisories/GHSA-gf3v-fwqg-4vh7"
},
{
"type": "WEB",
"url": "https://github.com/langchain-ai/langchainjs/security/advisories/GHSA-mphv-75cg-56wg"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-27795"
},
{
"type": "WEB",
"url": "https://github.com/langchain-ai/langchainjs/pull/9990"
},
{
"type": "WEB",
"url": "https://github.com/langchain-ai/langchainjs/commit/2812d2b2b9fd9343c4850e2ab906b8cf440975ee"
},
{
"type": "WEB",
"url": "https://github.com/langchain-ai/langchainjs/commit/d5e3db0d01ab321ec70a875805b2f74aefdadf9d"
},
{
"type": "PACKAGE",
"url": "https://github.com/langchain-ai/langchainjs"
},
{
"type": "WEB",
"url": "https://github.com/langchain-ai/langchainjs/releases/tag/%40langchain%2Fcommunity%401.1.14"
},
{
"type": "WEB",
"url": "https://github.com/langchain-ai/langchainjs/releases/tag/%40langchain%2Fcommunity%401.1.18"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "LangChain Community: redirect chaining can lead to SSRF bypass via RecursiveUrlLoader"
}
GHSA-MPPC-G8X5-RQ8C
Vulnerability from github – Published: 2022-10-26 19:00 – Updated: 2022-10-28 19:00The url parameter of the /api/geojson endpoint in Metabase versions <44.5 can be used to perform Server Side Request Forgery attacks. Previously implemented blacklists could be circumvented by leveraging 301 and 302 redirects.
{
"affected": [],
"aliases": [
"CVE-2022-43776"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2022-10-26T18:15:00Z",
"severity": "MODERATE"
},
"details": "The url parameter of the /api/geojson endpoint in Metabase versions \u003c44.5 can be used to perform Server Side Request Forgery attacks. Previously implemented blacklists could be circumvented by leveraging 301 and 302 redirects.",
"id": "GHSA-mppc-g8x5-rq8c",
"modified": "2022-10-28T19:00:33Z",
"published": "2022-10-26T19:00:38Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-43776"
},
{
"type": "WEB",
"url": "https://www.tenable.com/security/research/tra-2022-34"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-MPQW-XP9Q-3FPC
Vulnerability from github – Published: 2026-06-24 09:30 – Updated: 2026-06-24 09:30The URL Preview plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 1.0 via the 'url' parameter. This makes it possible for unauthenticated attackers to make web requests to arbitrary locations originating from the web application and can be used to query and modify information from internal services.
{
"affected": [],
"aliases": [
"CVE-2026-12100"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-06-24T07:16:26Z",
"severity": "HIGH"
},
"details": "The URL Preview plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 1.0 via the \u0027url\u0027 parameter. This makes it possible for unauthenticated attackers to make web requests to arbitrary locations originating from the web application and can be used to query and modify information from internal services.",
"id": "GHSA-mpqw-xp9q-3fpc",
"modified": "2026-06-24T09:30:45Z",
"published": "2026-06-24T09:30:45Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-12100"
},
{
"type": "WEB",
"url": "https://plugins.trac.wordpress.org/browser/link-preview/trunk/class.linkpreview.php#L112"
},
{
"type": "WEB",
"url": "https://plugins.trac.wordpress.org/browser/link-preview/trunk/class.linkpreview.php#L30"
},
{
"type": "WEB",
"url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/05de038f-eff4-4b00-930c-3d2335345869?source=cve"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-MPVW-25MG-59VX
Vulnerability from github – Published: 2021-03-29 16:32 – Updated: 2024-10-26 18:34All versions of package reportlab at time of writing are vulnerable to Server-side Request Forgery (SSRF) via img tags. In order to reduce risk, use trustedSchemes & trustedHosts (see in Reportlab's documentation)
Steps to reproduce by Karan Bamal:
1. Download and install the latest package of reportlab
2. Go to demos -> odyssey -> dodyssey
3. In the text file odyssey.txt that needs to be converted to pdf inject <img src="http://127.0.0.1:5000" valign="top"/>
4. Create a nc listener nc -lp 5000
5. Run python3 dodyssey.py
6. You will get a hit on your nc showing we have successfully proceded to send a server side request
7. dodyssey.py will show error since there is no img file on the url, but we are able to do SSRF
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "reportlab"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.5.55"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2020-28463"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2021-03-19T22:04:29Z",
"nvd_published_at": "2021-02-18T16:15:00Z",
"severity": "HIGH"
},
"details": "All versions of package reportlab at time of writing are vulnerable to Server-side Request Forgery (SSRF) via img tags. In order to reduce risk, use trustedSchemes \u0026 trustedHosts (see in Reportlab\u0027s documentation) \n\nSteps to reproduce by Karan Bamal: \n1. Download and install the latest package of reportlab \n2. Go to demos -\u003e odyssey -\u003e dodyssey \n3. In the text file odyssey.txt that needs to be converted to pdf inject `\u003cimg src=\"http://127.0.0.1:5000\" valign=\"top\"/\u003e`\n4. Create a nc listener `nc -lp 5000`\n5. Run python3 dodyssey.py \n6. You will get a hit on your nc showing we have successfully proceded to send a server side request \n7. dodyssey.py will show error since there is no img file on the url, but we are able to do SSRF",
"id": "GHSA-mpvw-25mg-59vx",
"modified": "2024-10-26T18:34:55Z",
"published": "2021-03-29T16:32:27Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-28463"
},
{
"type": "WEB",
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=1930417"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-mpvw-25mg-59vx"
},
{
"type": "WEB",
"url": "https://github.com/pypa/advisory-database/tree/main/vulns/reportlab/PYSEC-2021-146.yaml"
},
{
"type": "PACKAGE",
"url": "https://hg.reportlab.com/hg-public/reportlab"
},
{
"type": "WEB",
"url": "https://hg.reportlab.com/hg-public/reportlab/file/f094d273903a/CHANGES.md#l71"
},
{
"type": "WEB",
"url": "https://hg.reportlab.com/hg-public/reportlab/rev/7f2231703dc7"
},
{
"type": "WEB",
"url": "https://lists.debian.org/debian-lts-announce/2023/09/msg00037.html"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/HMUJA5GZTPQ5WRYUCCK2GEZM4W43N7HH"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/YZQSFCID67K6BTC655EQY6MNOF35QI44"
},
{
"type": "WEB",
"url": "https://snyk.io/vuln/SNYK-PYTHON-REPORTLAB-1022145"
},
{
"type": "WEB",
"url": "https://www.reportlab.com/docs/reportlab-userguide.pdf"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Server-side Request Forgery (SSRF) via img tags in reportlab"
}
No mitigation information available for this CWE.
CAPEC-664: Server Side Request Forgery
An adversary exploits improper input validation by submitting maliciously crafted input to a target application running on a server, with the goal of forcing the server to make a request either to itself, to web services running in the server’s internal network, or to external third parties. If successful, the adversary’s request will be made with the server’s privilege level, bypassing its authentication controls. This ultimately allows the adversary to access sensitive data, execute commands on the server’s network, and make external requests with the stolen identity of the server. Server Side Request Forgery attacks differ from Cross Site Request Forgery attacks in that they target the server itself, whereas CSRF attacks exploit an insecure user authentication mechanism to perform unauthorized actions on the user's behalf.