GHSA-89V5-38XR-9M4J
Vulnerability from github – Published: 2026-03-27 15:47 – Updated: 2026-03-27 15:47
VLAI
Summary
Postiz has Multiple SSRF Vectors - Webhooks, RSS Feed, URL Loader
Details
Summary
Postiz has multiple SSRF vulnerabilities where user-provided URLs are fetched server-side without any IP validation or SSRF protection.
Vulnerable Code
1. Webhook Send Endpoint (Most Critical)
apps/backend/src/api/routes/webhooks.controller.ts lines 58-70:
async sendWebhook(@Body() body: any, @Query('url') url: string) {
try {
await fetch(url, { // No URL validation
method: 'POST',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' },
});
} catch (err) { }
return { send: true };
}
Accepts arbitrary URL via query parameter and fetches directly.
2. Stored Webhook Delivery
apps/orchestrator/src/activities/post.activity.ts lines 256-281:
async sendWebhooks(postId: string, orgId: string, integrationId: string) {
const webhooks = await this._webhookService.getWebhooks(orgId);
return Promise.all(
webhooks.map(async (webhook) => {
await fetch(webhook.url, { // Stored URL, no validation
method: 'POST',
body: JSON.stringify(post),
});
})
);
}
3. RSS/XML Feed Parser
libraries/nestjs-libraries/src/database/prisma/autopost/autopost.service.ts line 135:
async loadXML(url: string) {
const { items } = await parser.parseURL(url); // No URL validation
}
4. HTML Content Loader
libraries/nestjs-libraries/src/database/prisma/autopost/autopost.service.ts line 185:
async loadUrl(url: string) {
const loadDom = new JSDOM(await (await fetch(url)).text()); // No validation
}
Missing Protections
- No
request-filtering-agentor SSRF library - No private IP range filtering
- No cloud metadata endpoint blocking
- No DNS rebinding protection
- URL validation only via
@IsUrl()decorator (format only, no IP check)
Attack Scenarios
POST /webhooks/send?url=http://169.254.169.254/latest/meta-data/→ AWS metadata theftPOST /autopost/send?url=http://127.0.0.1:6379→ Internal Redis access- Create webhook with
http://10.0.0.1:8080/admin→ Internal service access on post publish
Impact
- Cloud metadata theft: AWS/GCP/Azure credentials
- Internal network scanning: Full access to private IP ranges
- Multiple entry points: Webhooks, RSS feeds, URL loader all vulnerable
Severity
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "postiz"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "2.0.12"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-27T15:47:57Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "## Summary\n\nPostiz has multiple SSRF vulnerabilities where user-provided URLs are fetched server-side without any IP validation or SSRF protection.\n\n## Vulnerable Code\n\n### 1. Webhook Send Endpoint (Most Critical)\n\n**`apps/backend/src/api/routes/webhooks.controller.ts` lines 58-70:**\n```typescript\nasync sendWebhook(@Body() body: any, @Query(\u0027url\u0027) url: string) {\n try {\n await fetch(url, { // No URL validation\n method: \u0027POST\u0027,\n body: JSON.stringify(body),\n headers: { \u0027Content-Type\u0027: \u0027application/json\u0027 },\n });\n } catch (err) { }\n return { send: true };\n}\n```\n\nAccepts arbitrary URL via query parameter and fetches directly.\n\n### 2. Stored Webhook Delivery\n\n**`apps/orchestrator/src/activities/post.activity.ts` lines 256-281:**\n```typescript\nasync sendWebhooks(postId: string, orgId: string, integrationId: string) {\n const webhooks = await this._webhookService.getWebhooks(orgId);\n return Promise.all(\n webhooks.map(async (webhook) =\u003e {\n await fetch(webhook.url, { // Stored URL, no validation\n method: \u0027POST\u0027,\n body: JSON.stringify(post),\n });\n })\n );\n}\n```\n\n### 3. RSS/XML Feed Parser\n\n**`libraries/nestjs-libraries/src/database/prisma/autopost/autopost.service.ts` line 135:**\n```typescript\nasync loadXML(url: string) {\n const { items } = await parser.parseURL(url); // No URL validation\n}\n```\n\n### 4. HTML Content Loader\n\n**`libraries/nestjs-libraries/src/database/prisma/autopost/autopost.service.ts` line 185:**\n```typescript\nasync loadUrl(url: string) {\n const loadDom = new JSDOM(await (await fetch(url)).text()); // No validation\n}\n```\n\n## Missing Protections\n\n- No `request-filtering-agent` or SSRF library\n- No private IP range filtering\n- No cloud metadata endpoint blocking\n- No DNS rebinding protection\n- URL validation only via `@IsUrl()` decorator (format only, no IP check)\n\n## Attack Scenarios\n\n1. `POST /webhooks/send?url=http://169.254.169.254/latest/meta-data/` \u2192 AWS metadata theft\n2. `POST /autopost/send?url=http://127.0.0.1:6379` \u2192 Internal Redis access\n3. Create webhook with `http://10.0.0.1:8080/admin` \u2192 Internal service access on post publish\n\n## Impact\n\n- **Cloud metadata theft**: AWS/GCP/Azure credentials\n- **Internal network scanning**: Full access to private IP ranges\n- **Multiple entry points**: Webhooks, RSS feeds, URL loader all vulnerable",
"id": "GHSA-89v5-38xr-9m4j",
"modified": "2026-03-27T15:47:57Z",
"published": "2026-03-27T15:47:57Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/gitroomhq/postiz-app/security/advisories/GHSA-89v5-38xr-9m4j"
},
{
"type": "WEB",
"url": "https://github.com/gitroomhq/postiz-app/commit/0ad89ccd26b1c387c4f3f3544b18c20d33586466"
},
{
"type": "WEB",
"url": "https://github.com/gitroomhq/postiz-app/commit/be5d871896e97cb1f5a2c9241f156b6a1e1debe8"
},
{
"type": "PACKAGE",
"url": "https://github.com/gitroomhq/postiz-app"
},
{
"type": "WEB",
"url": "https://github.com/gitroomhq/postiz-app/releases/tag/v2.21.2"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:N/SC:H/SI:L/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Postiz has Multiple SSRF Vectors - Webhooks, RSS Feed, URL Loader"
}
Loading…
Loading…
Experimental. This forecast is provided for visualization only and may change without notice. Do not use it for operational decisions.
Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Loading…
The MITRE ATT&CK techniques below are AI-generated suggestions, inferred from the description of the
vulnerability by the CIRCL/vulnerability-attack-technique-classification-roberta-base
model, served locally by ML-Gateway.
They have not been verified by an analyst and are provided for guidance only.
Loading…
Loading…