Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
c0620bc
fix: add LiteLLM local proxy to sanitize empty content blocks for Ope…
datasciencemonkey Mar 11, 2026
42a78b7
docs: update design doc with clearer architecture description
datasciencemonkey Mar 11, 2026
cc7fb63
fix: remove invalid CLI flags from LiteLLM startup
datasciencemonkey Mar 11, 2026
ba49d30
fix: replace LiteLLM with lightweight custom proxy
datasciencemonkey Mar 11, 2026
517d21d
fix: comprehensive content-filter proxy with request + response fixes
datasciencemonkey Mar 11, 2026
b71a263
fix: robust multi-pass orphan detection with diagnostic logging
datasciencemonkey Mar 11, 2026
c31bf4e
fix: use @ai-sdk/openai for GPT models (Responses API support)
datasciencemonkey Mar 11, 2026
228af71
fix: explicitly install @ai-sdk/openai for GPT Responses API
datasciencemonkey Mar 11, 2026
f432f99
fix: rename LiteLLM references to content-filter proxy
datasciencemonkey Mar 11, 2026
01d8ad8
fix: add Gemini compatibility — strip unsupported schema keys
datasciencemonkey Mar 11, 2026
9f3bc1b
fix: strip $schema from tool params for ALL models, not just Gemini
datasciencemonkey Mar 11, 2026
96ee510
fix: logging not writing — use explicit FileHandler
datasciencemonkey Mar 11, 2026
c497445
fix: logging to stderr (FileHandler buffering prevented writes)
datasciencemonkey Mar 11, 2026
951e520
fix: kill stale proxy from previous deploy before starting new one
datasciencemonkey Mar 11, 2026
1684dc7
fix: kill stale proxy by port instead of PID file
datasciencemonkey Mar 11, 2026
396dbb8
fix: replace empty assistant content with placeholder instead of keeping
datasciencemonkey Mar 11, 2026
c023699
feat: add DeepWiki and Exa MCP servers to OpenCode config
datasciencemonkey Mar 11, 2026
a03d981
refactor: remove all LiteLLM references
datasciencemonkey Mar 11, 2026
d91aa17
fix: update DeepWiki MCP URL from /sse to /mcp
datasciencemonkey Mar 11, 2026
d1ad4e2
security: fail closed when app_owner can't be resolved (#57)
datasciencemonkey Mar 11, 2026
30a9e4e
security: add Content-Security-Policy header (#58)
datasciencemonkey Mar 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 41 additions & 3 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ def handle_sigterm(signum, frame):
"steps": [
{"id": "git", "label": "Configuring git identity", "status": "pending", "started_at": None, "completed_at": None, "error": None},
{"id": "micro", "label": "Installing micro editor", "status": "pending", "started_at": None, "completed_at": None, "error": None},
{"id": "proxy", "label": "Starting content-filter proxy", "status": "pending", "started_at": None, "completed_at": None, "error": None},
{"id": "claude", "label": "Configuring Claude CLI", "status": "pending", "started_at": None, "completed_at": None, "error": None},
{"id": "codex", "label": "Configuring Codex CLI", "status": "pending", "started_at": None, "completed_at": None, "error": None},
{"id": "opencode", "label": "Configuring OpenCode CLI", "status": "pending", "started_at": None, "completed_at": None, "error": None},
Expand Down Expand Up @@ -251,6 +252,11 @@ def run_setup():
_run_step("micro", ["bash", "-c",
"mkdir -p ~/.local/bin && bash install_micro.sh && mv micro ~/.local/bin/ 2>/dev/null || true"])

# --- Content-filter proxy (must be running before OpenCode starts) ---
# Sanitizes requests/responses between OpenCode and Databricks
# (see OpenCode #5028, docs/plans/2026-03-11-litellm-empty-content-blocks-design.md)
_run_step("proxy", ["python", "setup_proxy.py"])

# --- Parallel agent setup (all independent of each other) ---
parallel_steps = [
("claude", ["python", "setup_claude.py"]),
Expand Down Expand Up @@ -296,16 +302,33 @@ def get_request_user():
request.headers.get("X-Databricks-User-Email")


def _is_databricks_apps():
"""Detect if we're running on Databricks Apps (not local dev)."""
return os.environ.get("DATABRICKS_APP_PORT") or os.path.isdir("/app/python/source_code")


def check_authorization():
"""Check if the current user is authorized to access the app."""
# If owner not set (local dev or SDK unavailable), allow access
"""Check if the current user is authorized to access the app.

Fails CLOSED on Databricks Apps: if we can't determine the owner,
deny all access rather than allowing unauthenticated terminal access.
Fails open only for local development.
Fixes: https://github.com/datasciencemonkey/coding-agents-databricks-apps/issues/57
"""
# Fail closed on Databricks Apps if owner couldn't be resolved
if not app_owner:
return True, None
if _is_databricks_apps():
logger.error("SECURITY: app_owner not resolved — denying all access (fail-closed)")
return False, "unknown"
return True, None # Local dev only

current_user = get_request_user()

# If no user identity in request (local dev), allow access
if not current_user:
if _is_databricks_apps():
logger.warning("No user identity in request on Databricks Apps — denying access")
return False, "unknown"
return True, None

# Check if current user is the owner
Expand Down Expand Up @@ -571,6 +594,21 @@ def set_security_headers(response):
response.headers["X-Frame-Options"] = "DENY"
response.headers["X-XSS-Protection"] = "1; mode=block"
response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
# CSP: restrict scripts to self + inline (needed for embedded <script> block),
# styles to self + inline, block all other sources. Prevents external script injection.
# connect-src allows WebSocket + API calls to self.
# Fixes: https://github.com/datasciencemonkey/coding-agents-databricks-apps/issues/58
response.headers["Content-Security-Policy"] = (
"default-src 'none'; "
"script-src 'self' 'unsafe-inline'; "
"style-src 'self' 'unsafe-inline'; "
"img-src 'self' data:; "
"font-src 'self'; "
"connect-src 'self' ws: wss:; "
"frame-ancestors 'none'; "
"base-uri 'self'; "
"form-action 'self'"
)
return response


Expand Down
Loading