diff --git a/dashboard/api.py b/dashboard/api.py index f0a9726..97aeb83 100644 --- a/dashboard/api.py +++ b/dashboard/api.py @@ -110,10 +110,26 @@ class TaskBoardHandler(SimpleHTTPRequestHandler): path = data.get('path', '') content = data.get('content', '') - workspace = Path('/home/moltbot/clawd') - target = (workspace / path).resolve() + # Allow access to clawd and workspace + allowed_dirs = [ + Path('/home/moltbot/clawd'), + Path('/home/moltbot/workspace') + ] - if not str(target).startswith(str(workspace)): + # Try to resolve against each allowed directory + target = None + workspace = None + for base in allowed_dirs: + try: + candidate = (base / path).resolve() + if str(candidate).startswith(str(base)): + target = candidate + workspace = base + break + except: + continue + + if target is None: self.send_json({'error': 'Access denied'}, 403) return @@ -641,15 +657,27 @@ class TaskBoardHandler(SimpleHTTPRequestHandler): path = params.get('path', [''])[0] action = params.get('action', ['list'])[0] - # Security: only allow access within workspace - workspace = Path('/home/moltbot/clawd') - try: - target = (workspace / path).resolve() - if not str(target).startswith(str(workspace)): - self.send_json({'error': 'Access denied'}, 403) - return - except: - self.send_json({'error': 'Invalid path'}, 400) + # Security: only allow access within allowed directories + allowed_dirs = [ + Path('/home/moltbot/clawd'), + Path('/home/moltbot/workspace') + ] + + # Try to resolve against each allowed directory + target = None + workspace = None + for base in allowed_dirs: + try: + candidate = (base / path).resolve() + if str(candidate).startswith(str(base)): + target = candidate + workspace = base + break + except: + continue + + if target is None: + self.send_json({'error': 'Access denied'}, 403) return if action == 'list':