HKUDS/Vibe-Trading · error · HTTPException
invalid shadow_id
Error message
invalid shadow_id
What it means
The shadow report endpoint validates shadow_id against a regex before using it in a filesystem path. IDs failing the pattern are rejected with 400 to prevent path traversal and unexpected file lookups.
Source
Thrown at agent/src/api/uploads_routes.py:103
import sys as _sys
host = _sys.modules.get("api_server") or _sys.modules.get("agent.api_server")
return host.MAX_UPLOAD_SIZE if host else MAX_UPLOAD_SIZE
def _host_chunk_size() -> int:
import sys as _sys
host = _sys.modules.get("api_server") or _sys.modules.get("agent.api_server")
return host._UPLOAD_CHUNK_SIZE if host else _UPLOAD_CHUNK_SIZE
@app.get("/shadow-reports/{shadow_id}", dependencies=[Depends(require_auth)])
async def get_shadow_report(shadow_id: str, format: str = "html"):
"""Serve a rendered Shadow Account report.
Reports live under ``~/.vibe-trading/shadow_reports/<shadow_id>.{html,pdf}``.
"""
if not _SHADOW_ID_RE.match(shadow_id):
raise HTTPException(status_code=400, detail="invalid shadow_id")
if format not in ("html", "pdf"):
raise HTTPException(status_code=400, detail="format must be html or pdf")
reports_dir = Path.home() / ".vibe-trading" / "shadow_reports"
path = reports_dir / f"{shadow_id}.{format}"
if not path.exists():
raise HTTPException(status_code=404, detail=f"Shadow report not found: {shadow_id}.{format}")
media_type = "text/html; charset=utf-8" if format == "html" else "application/pdf"
return FileResponse(
path,
media_type=media_type,
headers={"Content-Disposition": f'inline; filename="{shadow_id}.{format}"'},
)
@app.post("/upload", dependencies=[Depends(require_auth)])
async def upload_file(file: UploadFile):
"""Upload any document or data file (max 50MB).View on GitHub (pinned to 80ffdda44c)
Solutions
- Use the exact shadow_id returned when the shadow report was generated
- Trim whitespace/newlines from user-supplied IDs before the request
- Check the ID matches the expected pattern (alphanumeric/dash style) client-side
Example fix
// before
fetch(`/uploads/shadow-report?shadow_id=${rawInput}`)
// after
const id = rawInput.trim();
if (!/^[A-Za-z0-9_-]+$/.test(id)) throw new Error('bad shadow id');
fetch(`/uploads/shadow-report?shadow_id=${id}`) Defensive patterns
Strategy: type-guard
Validate before calling
import re assert re.fullmatch(r'[A-Za-z0-9_-]+', shadow_id), 'invalid shadow_id'
Type guard
def is_valid_shadow_id(sid: str) -> bool:
return bool(re.fullmatch(r'[A-Za-z0-9_-]+', sid or '')) Prevention
- Pass through the exact ID returned at report creation
- Trim user input before sending
When it happens
Trigger: GET /uploads/shadow-report?shadow_id=../../etc/passwd or shadow_id with spaces, slashes, or characters outside the allowed ID pattern; also fabricated/guessed IDs.
Common situations: Client truncating or mutating the ID returned at report creation, copy-paste with whitespace/newlines, or injection attempts hitting the path construction.
Related errors
- format must be html or pdf
- exit_threshold must be below enter_threshold
- Missing filename
- Invalid swarm agent id {agent_id!r}: artifact path escapes t
- artifact_path escapes the current run_dir
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/2be3f4687041c985.
Report an issue: GitHub.