Vibe-Trading FastAPI endpoints permit unauthenticated access, file upload, and an RCE chain
### Summary: 5 findings — unauthenticated full-API exposure (F1, lead Critical), read-side authorization gap that persists even with `API_AUTH_KEY` set (F2), unauthenticated file write of `.py`/`.sh`/`.yaml` to a server-returned path (F3), default-permissive CORS that combines with a loopback-only check to grant any browser page on whitelisted localhost ports credentialed cross-origin access (F-A4), and partial API-key disclosure via `_mask_secret()` (F-A5). --- ### Shared baseline (applies to all 5 findings) The shipped `agent/.env.example` line 112 ships `# API_AUTH_KEY=` commented out. `require_auth()` at `agent/api_server.py` line 303 executes `if not api_key: return` and returns `None` immediately when `API_AUTH_KEY` is unset, so every endpoint decorated with `dependencies=[Depends(require_auth)]` operates as unauthenticated. The shipped `Dockerfile` does **not** contain a `USER` directive, so the FastAPI process runs as `uid=0(root)` inside the container (verified: `docker exec id` returns `uid=0(root) gid=0(root)`). The `docker-compose.yml` binds `0.0.0.0:8899` with no network restriction. The only operator action required beyond a clean install is supplying a working LLM API key so the agent loop can complete its tool-call round trip — this is the normal first step to make the agent functional, not an additional security opt-in. F-A4 and F-A5 do *not* require an LLM key (see per-finding notes); F1 and F3 do not require an LLM key for the unauth surface itself, only fo
- Products
- vibe-trading-ai
- Affected versions
- 0.1.0, 0.1.1, 0.1.2, 0.1.3, 0.1.4, 0.1.5, 0.1.6
- Fixed versions
- 0.1.7
- CVEs
- CVE-2026-114108
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 31 Oct 2026, 14:09 UTC · Revision 1
Source evidence
Vibe-Trading FastAPI endpoints permit unauthenticated access, file upload, and an RCE chain
core-osv · Original sourcePublished 2 Oct 2026, 22:44 UTC
### Summary: 5 findings — unauthenticated full-API exposure (F1, lead Critical), read-side authorization gap that persists even with `API_AUTH_KEY` set (F2), unauthenticated file write of `.py`/`.sh`/`.yaml` to a server-returned path (F3), default-permissive CORS that combines with a loopback-only check to grant any browser page on whitelisted localhost ports credentialed cross-origin access (F-A4), and partial API-key disclosure via `_mask_secret()` (F-A5). --- ### Shared baseline (applies to all 5 findings) The shipped `agent/.env.example` line 112 ships `# API_AUTH_KEY=` commented out. `require_auth()` at `agent/api_server.py` line 303 executes `if not api_key: return` and returns `None` immediately when `API_AUTH_KEY` is unset, so every endpoint decorated with `dependencies=[Depends(require_auth)]` operates as unauthenticated. The shipped `Dockerfile` does **not** contain a `USER` directive, so the FastAPI process runs as `uid=0(root)` inside the container (verified: `docker exec id` returns `uid=0(root) gid=0(root)`). The `docker-compose.yml` binds `0.0.0.0:8899` with no network restriction. The only operator action required beyond a clean install is supplying a working LLM API key so the agent loop can complete its tool-call round trip — this is the normal first step to make the agent functional, not an additional security opt-in. F-A4 and F-A5 do *not* require an LLM key (see per-finding notes); F1 and F3 do not require an LLM key for the unauth surface itself, only fo
osv:GHSA-v2f8-6655-7grj
vibe-trading-ai
Fixed versions: 0.1.7
Complete source record
{
"id": "053dbb92e597f3fd423d7eb5c831601399bd29023ba178f811edef53f39c9e87",
"url": "https://osv.dev/vulnerability/GHSA-v2f8-6655-7grj",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "Vibe-Trading FastAPI endpoints permit unauthenticated access, file upload, and an RCE chain",
"summary": "### Summary: 5 findings — unauthenticated full-API exposure (F1, lead Critical), read-side authorization gap that persists even with `API_AUTH_KEY` set (F2), unauthenticated file write of `.py`/`.sh`/`.yaml` to a server-returned path (F3), default-permissive CORS that combines with a loopback-only check to grant any browser page on whitelisted localhost ports credentialed cross-origin access (F-A4), and partial API-key disclosure via `_mask_secret()` (F-A5). --- ### Shared baseline (applies to all 5 findings) The shipped `agent/.env.example` line 112 ships `# API_AUTH_KEY=` commented out. `require_auth()` at `agent/api_server.py` line 303 executes `if not api_key: return` and returns `None` immediately when `API_AUTH_KEY` is unset, so every endpoint decorated with `dependencies=[Depends(require_auth)]` operates as unauthenticated. The shipped `Dockerfile` does **not** contain a `USER` directive, so the FastAPI process runs as `uid=0(root)` inside the container (verified: `docker exec id` returns `uid=0(root) gid=0(root)`). The `docker-compose.yml` binds `0.0.0.0:8899` with no network restriction. The only operator action required beyond a clean install is supplying a working LLM API key so the agent loop can complete its tool-call round trip — this is the normal first step to make the agent functional, not an additional security opt-in. F-A4 and F-A5 do *not* require an LLM key (see per-finding notes); F1 and F3 do not require an LLM key for the unauth surface itself, only fo",
"evidence": "osv:GHSA-v2f8-6655-7grj",
"products": [
{
"name": {
"value": "vibe-trading-ai",
"evidence": "/affected/0/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "0.1.7",
"evidence": "/affected/0/ranges"
}
],
"affected_versions": [
{
"value": "0.1.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.1.1",
"evidence": "/affected/0/versions"
},
{
"value": "0.1.2",
"evidence": "/affected/0/versions"
},
{
"value": "0.1.3",
"evidence": "/affected/0/versions"
},
{
"value": "0.1.4",
"evidence": "/affected/0/versions"
},
{
"value": "0.1.5",
"evidence": "/affected/0/versions"
},
{
"value": "0.1.6",
"evidence": "/affected/0/versions"
}
]
}
],
"severity": "critical",
"structured": {
"id": "GHSA-v2f8-6655-7grj",
"aliases": [
"CVE-2026-114108",
"GHSA-v2f8-6655-7grj"
],
"metrics": [
{
"type": "CVSS_V3",
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H"
}
],
"affected": [
{
"ranges": [
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "0.1.0"
},
{
"fixed": "0.1.7"
}
]
}
],
"package": {
"name": "vibe-trading-ai",
"purl": "pkg:pypi/vibe-trading-ai",
"ecosystem": "PyPI"
},
"versions": [
"0.1.0",
"0.1.1",
"0.1.2",
"0.1.3",
"0.1.4",
"0.1.5",
"0.1.6"
],
"database_specific": {
"source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-v2f8-6655-7grj/GHSA-v2f8-6655-7grj.json"
}
}
],
"modified": "2026-10-21T10:57:26.240527692Z",
"provider": "osv",
"references": [
"https://github.com/HKUDS/Vibe-Trading/security/advisories/GHSA-v2f8-6655-7grj",
"https://github.com/HKUDS/Vibe-Trading/commit/9454d4a27a763b80e1d6eb5763b86c88e9e4e714",
"https://github.com/HKUDS/Vibe-Trading",
"https://github.com/HKUDS/Vibe-Trading/releases/tag/v0.1.7"
],
"provider_metadata": {
"cwe_ids": [
"CWE-200",
"CWE-306",
"CWE-434",
"CWE-862",
"CWE-942"
],
"severity": "CRITICAL",
"github_reviewed": true,
"nvd_published_at": null,
"github_reviewed_at": "2026-10-02T22:44:26Z"
}
},
"related_cves": [
{
"value": "CVE-2026-114108",
"evidence": "/aliases"
}
],
"security_relevant": true,
"severity_evidence": "/database_specific/severity"
},
"source_id": "core-osv",
"document_id": 392982,
"published_at": "2026-10-02T22:44:26+00:00"
}