Implement audit roadmap: security hardening, reliability, and CI.#3
Conversation
Close permission bypasses for all tools, fix Docker argv isolation and goal resume, add tests and DevOps docs, and stop tracking personal config.yaml. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
There was a problem hiding this comment.
Pull request overview
This PR implements a broad “audit roadmap” hardening pass across OctaAI’s tool execution pipeline: tightening permission checks (paths/commands/URLs), improving Docker isolation behavior, adding resumability improvements, introducing project-directory handling, and adding documentation + CI to support safer operation.
Changes:
- Added centralized path resolution (
ResolveProjectPath) and expanded safety policies (command normalization, HTTP SSRF checks, browser domain restrictions, SSH host-key verification). - Improved execution reliability: Docker argv preservation, step-view output evaluation, goal resume/checkpoint behavior, and configurable retry/max-attempts.
- Added operational docs and tooling:
SECURITY.md,CONTRIBUTING.md,AGENTS.md, Dockerfile, and GitHub Actions CI; removed personalconfig.yamland added it to.gitignore.
Reviewed changes
Copilot reviewed 40 out of 44 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| SECURITY.md | Adds security policy, configuration guidance, and threat-model notes. |
| pkg/tools/ssh.go | Enforces known_hosts verification; shell-quotes remote paths for file ops. |
| pkg/tools/ISSUE.md | Removes old internal issue tracking doc from repo. |
| pkg/tools/git.go | Resolves git paths under projects root for clone/init/commit/push. |
| pkg/tools/filesystem.go | Uses centralized project-path resolution for filesystem operations. |
| pkg/tools/filesystem_test.go | Adds filesystem allowlist + read/write behavior tests. |
| pkg/tools/command.go | Normalizes deny-command matching; resolves cwd under projects root. |
| pkg/tools/command_test.go | Adds test for deny-pattern bypass via case/whitespace changes. |
| pkg/storage/storage.go | Adds project_name to persisted goals. |
| pkg/storage/sqlite.go | Migrates goals schema for project_name; updates queries; ignores unmarshal errors. |
| pkg/plugin/registry.go | Small formatting-only adjustment to capability constants. |
| pkg/planner/replan.go | Uses planner-configured max-attempts instead of hardcoded 3. |
| pkg/planner/project.go | Adds project-name sanitization + heuristics for when a goal needs a project directory. |
| pkg/planner/project_test.go | Adds unit tests for project-name sanitization/heuristics. |
| pkg/planner/planner.go | Introduces planner maxAttempts config; persists project name to memory; uses sanitization helper. |
| pkg/permission/url.go | Adds SSRF + browser-domain URL checks (new). |
| pkg/permission/shellquote.go | Adds shell quoting helper for safe remote shell use (new). |
| pkg/permission/normalize.go | Adds command normalization helper for policy matching (new). |
| pkg/permission/manager.go | Hardens tool gating across command/filesystem/git/http/browser/ssh; denies unknown tools. |
| pkg/permission/manager_test.go | Adds unit tests covering core permission behaviors. |
| pkg/isolation/docker.go | Fixes docker workdir computation; preserves argv boundaries via _docker_argv. |
| pkg/isolation/docker_test.go | Adds test ensuring docker wrapping preserves argv and original command string. |
| pkg/evaluator/evaluator.go | Minor formatting-only alignment change. |
| pkg/evaluator/evaluator_test.go | Adds tests for ToolResultEvaluator behaviors. |
| pkg/engine/step.go | Adds ViewWithOutput to evaluate steps with runtime output not yet persisted. |
| pkg/engine/step_test.go | Adds unit test validating ViewWithOutput behavior. |
| pkg/engine/runner.go | Runs permission checks pre-isolation; executes docker argv directly; improves Data handling. |
| pkg/engine/prompts.go | Strengthens system/task prompts around projects root + “write code locally” guidance. |
| pkg/engine/engine.go | Improves resumability/retry loop + checkpoint persistence + evaluation flow refactor. |
| pkg/engine/checkpoint.go | Formatting-only alignment changes. |
| pkg/config/path_test.go | Adds tests for ExpandPath and ResolveProjectPath. |
| pkg/config/config.go | Adds allow_http_hosts; implements ExpandPath + ResolveProjectPath; expands tilde/env on load. |
| pkg/config/browser.go | Adds browser token generation for WebSocket auth (new). |
| pkg/browser/server.go | Requires browser WS token; restricts allowed Origin prefixes; ignores encode errors. |
| go.mod | Promotes websocket/uuid dependencies from indirect to direct. |
| Dockerfile | Adds multi-stage build + runtime image for the daemon. |
| CONTRIBUTING.md | Adds contributor guidance and security-sensitive contribution notes. |
| config.yaml | Removes personal config from repo tracking. |
| config.example.yaml | Adds allow_http_hosts and browser config examples. |
| cmd/octa-agentd/main.go | Adds daemon entrypoint with polling, concurrency, and browser server lifecycle. |
| cmd/octa-agent/main.go | Adds CLI for goals, status/logs, and approvals; supports --project. |
| AGENTS.md | Adds repo/architecture + operational command guide for agent tooling. |
| .gitignore | Stops tracking local config.yaml; tweaks ignored binary paths. |
| .github/workflows/ci.yml | Adds CI workflow (deps/vet/test/build) on PRs and main branches. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 5 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 741df8e. Configure here.
| } else if goal.State != StateExecuting { | ||
| if err := e.transitionGoal(goal, StateExecuting); err != nil { | ||
| return err | ||
| } |
There was a problem hiding this comment.
Approved goals cannot resume
High Severity
When a goal is approved via octa-agent approve, it enters an IDLE state. ProcessGoal then tries to transition it directly to EXECUTING, but CanTransition only permits IDLE to PLANNING. This invalid state change causes the goal to error continuously and prevents approved actions from running.
Reviewed by Cursor Bugbot for commit 741df8e. Configure here.
| func (m *Manager) CheckBrowserDomain(rawURL string) CheckResult { | ||
| if len(m.cfg.Browser.BrowserDomains) == 0 { | ||
| return CheckResult{Decision: DecisionAllow} | ||
| } |
There was a problem hiding this comment.
Empty browser_domains allows all
Medium Severity
CheckBrowserDomain returns allow when browser_domains is empty. With browser automation enabled and the default browser_domains: [], navigate is permitted to any host, so the new domain gate does not restrict navigation unless operators populate the list.
Reviewed by Cursor Bugbot for commit 741df8e. Configure here.
| var err error | ||
|
|
||
| if argv, ok := dockerArgv(execArgs); ok { | ||
| result, err = r.runDockerArgv(runCtx, argv) |
There was a problem hiding this comment.
Injected docker argv bypasses tools
High Severity
Runner.Run runs runDockerArgv whenever tool args contain _docker_argv, without requiring _isolated or stripping caller-controlled keys. LLM JSON can pass a benign command/path for CheckTool then execute arbitrary host argv, bypassing the named tool and Docker isolation when isolation is off or for non-command tools.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 741df8e. Configure here.
| return fmt.Errorf("failed to get goal: %w", err) | ||
| } | ||
|
|
||
| switch goal.State { |
There was a problem hiding this comment.
Shared loopCount races goals
Medium Severity
The daemon runs multiple ProcessGoal goroutines on one Engine, but loopCount is a single field reset and incremented per goal. Concurrent goals corrupt each other’s loop counters and checkpoint step indices, causing wrong max-loop exits or evaluation timing.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 741df8e. Configure here.
| } | ||
| } | ||
|
|
||
| return CheckResult{Decision: DecisionAllow} |
There was a problem hiding this comment.
HTTP redirect SSRF gap
Medium Severity
CheckURL validates the initial host at permission time, but HTTPTool uses a default http.Client that follows redirects without re-checking. A public URL can redirect to localhost or private addresses after approval.
Reviewed by Cursor Bugbot for commit 741df8e. Configure here.


Close permission bypasses for all tools, fix Docker argv isolation and goal resume, add tests and DevOps docs, and stop tracking personal config.yaml.
Note
High Risk
Broad changes to permission enforcement, SSRF/SSH/browser auth, and the goal state machine affect every tool invocation and resume path; mistakes could block legitimate work or leave bypasses.
Overview
This PR implements an audit roadmap: tightens tool permissions and isolation, improves goal execution reliability, and adds CI, container, and contributor docs.
Security & permissions:
permission.Managernow gates every built-in tool (unknown tools deny by default), resolves paths viaprojects_root, normalizes deny-list matching, checks commandcwd, HTTP/git URLs with SSRF rules and optionalallow_http_hosts, browser domains and JS execution approvals, and git push approval. SSH usesknown_hostsinstead of insecure host-key skip and quotes remote paths. Browser WebSocket requires a token, rejects missing auth, and restrictsOriginto extensions/localhost. Personalconfig.yamlis removed from the repo and ignored.Execution & reliability: The engine resumes goals in
EXECUTING/EVALUATING/RETRYING, skips terminal states, resets stuckrunningtasks, and persists checkpoints during loops. Step evaluation usesViewWithOutputso evaluators see fresh tool results. Docker isolation passes_docker_argvand runs viaexecwithout flattening the command string; permissions run before wrapping.Product & DX: New
octa-agentCLI (goals with--project, status, logs, approvals) andocta-agentd(5s polling, concurrent goals, graceful shutdown, optional browser server). Goals storeproject_name; planner sanitizes names and tiesmax_attemptsto engine config. LLM prompts steer file writes underprojects_root. GitHub Actions runsmake deps,vet,test,buildon Go 1.23 with CGO sqlite deps; multi-stage Dockerfile ships both binaries.Reviewed by Cursor Bugbot for commit 741df8e. Bugbot is set up for automated code reviews on this repo. Configure here.