diff --git a/docs/09-security.md b/docs/09-security.md index c18e0767..009303ab 100644 --- a/docs/09-security.md +++ b/docs/09-security.md @@ -100,16 +100,14 @@ All four filesystem tools (`read_file`, `write_file`, `list_files`, `edit`) impl | **Deny patterns** | Per-binary regex deny lists on arguments + verbose flags | Sensitive operations per CLI (e.g., `auth`, `ssh-key`) | | **Output scrub** | Credential values registered for dynamic scrubbing | Credentials in stdout/stderr | -**Edge case mitigations** (13 scenarios analyzed): -- Shell operators in command string → Blocked by early regex scan -- Argument injection via spaces → Protected by shell-word parsing (not shell evaluation) -- Binary PATH manipulation → Absolute path required + config match -- Symlink attacks → Verified by `exec.LookPath()` + config match -- Env var exfiltration → Command runs without shell, env vars never expand -- Output parsing tricks → Dynamic scrubbing catches all registered credential values -- Timeout abuse → Configurable per-binary timeout with context deadline -- Sandbox escape → Docker container isolation if sandbox enabled -- Verbose flag leakage → Separate deny_verbose list blocks verbose/debug output +| Attack Surface | Mitigation | +|----------------|------------| +| Shell operator injection, argument injection via spaces | Early regex scan + shell-word parsing (no shell evaluation) | +| Binary PATH manipulation, symlink attacks | `exec.LookPath()` + absolute path required + config match | +| Env var exfiltration, output parsing tricks | No-shell exec (env vars never expand) + dynamic credential scrubbing | +| Timeout abuse | Configurable per-binary timeout with context deadline | +| Sandbox escape | Docker container isolation when sandbox enabled | +| Verbose flag leakage | Separate deny_verbose list blocks verbose/debug output | **Agent-level grant enforcement** -- The gate runs **before** any process spawn, blocking ungranted agents from executing registered binaries: diff --git a/docs/20-api-keys-auth.md b/docs/20-api-keys-auth.md index b6591a65..7ebb133e 100644 --- a/docs/20-api-keys-auth.md +++ b/docs/20-api-keys-auth.md @@ -30,7 +30,7 @@ Or in WebSocket `connect`: ### Security -The gateway token is compared using **constant-time comparison** (`crypto/subtle.ConstantTimeCompare`) in both HTTP (`auth.go:tokenMatch`) and WebSocket (`router.go:handleConnect`) to prevent timing attacks. The comparison reveals no information about where the provided token first differs from the expected token. +The gateway token is compared using **constant-time comparison** (`crypto/subtle.ConstantTimeCompare`) in both HTTP and WebSocket auth paths to prevent timing attacks. The comparison reveals no information about where the provided token first differs from the expected token. --- @@ -78,7 +78,7 @@ Each API key is assigned one or more scopes that determine what operations it ca ### Role Derivation -The highest-privilege scope determines the effective role via `RoleFromScopes()` in `permissions/policy.go`: +The highest-privilege scope determines the effective role: ``` if admin scope present → RoleAdmin diff --git a/docs/21-agent-evolution-and-skill-management.md b/docs/21-agent-evolution-and-skill-management.md index 81642c26..21be814c 100644 --- a/docs/21-agent-evolution-and-skill-management.md +++ b/docs/21-agent-evolution-and-skill-management.md @@ -133,14 +133,7 @@ No skill is created without explicit user approval ("save as skill" or "skip"). Both stored in `agents.other_config` JSONB. Parsed by `ParseSkillEvolve()` and `ParseSkillNudgeInterval()` in `agent_store.go`. -**Predefined agents only.** Enforced at resolver level: - -```go -// resolver.go:346 -SkillEvolve: ag.AgentType == "predefined" && ag.ParseSkillEvolve(), -``` - -Open agents always get `skillEvolve=false` regardless of DB setting. +**Predefined agents only.** Enforced at the resolver level: `SkillEvolve` is set to `true` only when `AgentType == "predefined"` and the `skill_evolve` config flag is enabled. Open agents always get `skillEvolve=false` regardless of DB setting. **UI:** Config tab → Skill Learning section (toggle + interval input). @@ -254,8 +247,8 @@ reusable skill? Reply "save as skill" or "skip"._ When `skill_evolve=false`, `skill_manage` is completely hidden from the LLM: -1. **API params** (`loop.go:528-537`): filtered from `toolDefs` before sending to provider -2. **System prompt tooling** (`loop_history.go:135-144`): filtered from `toolNames` used in prompt construction +1. **API params**: filtered from `toolDefs` before sending to provider +2. **System prompt tooling**: filtered from `toolNames` used in prompt construction The tool remains in the shared registry (admin can see it) but the agent has zero awareness of it.