Skip to content

Access Control

Team-mode gate for who can invoke the agent. Configure via .codebuddy/access.json at the workspace root, or set a default via editor settings.

ModeBehavior
openNo restrictions. Everyone in. Default.
allowOnly users in the users array may invoke the agent.
denyUsers in the users array are blocked; everyone else allowed.
{
"mode": "allow",
"users": ["alice@company.com", "bob-dev"],
"admins": ["alice@company.com"],
"logDenied": true
}
FieldTypeDefaultPurpose
modestringopenopen / allow / deny
usersstring[][]Emails or GitHub usernames (max 200)
adminsstring[][]Bypass restrictions AND skip escalation prompts (max 50)
logDeniedbooleantrueLog denied attempts to the audit ring

File capped at 64 KB.

sequenceDiagram participant ACL participant GH as GitHub auth participant Git as git config participant Cache ACL->>Cache: 5-min TTL check alt Hit Cache-->>ACL: identity else Miss ACL->>GH: getSession(silent) alt GitHub session GH-->>ACL: username else No session ACL->>Git: git config user.email Git-->>ACL: email end ACL->>Cache: store end ACL->>ACL: lowercase + validate ACL->>ACL: check allow/deny

Order: silent GitHub session → git config --get user.email (3 s timeout) → unknown fallback.

Validation: emails match user@domain.tld (max 254 chars per RFC 5321). GitHub usernames = 1–39 alphanumeric/hyphen, no leading/trailing hyphens.

Cache: 5-min TTL to avoid repeated auth + git lookups.

Users in admins get:

  • Bypass the allow/deny gate regardless of mode.
  • Skip escalation prompts for sensitive operations (destructive file ops etc.) — auto-approved.
  • Still audited. Full trail retained.

Every access decision recorded when logDenied is on:

{
"timestamp": 1711612800000,
"user": "bob-dev",
"action": "agent_invoke",
"allowed": false
}

In-memory ring buffer, 500-entry cap (oldest evicted). Denied-access log writes throttled to one per 100 ms to prevent flooding.

.codebuddy/access.json is watched:

  1. Changes debounced.
  2. Concurrent reload requests serialized (single loadConfig at a time).
  3. onAccessChanged fires so UI can react.
CodeSeverityMeaning
no-configinfoNo access.json — running in open mode
config-loadedinfoConfig loaded
no-user-identitywarnCould not determine current user
empty-user-listwarnMode is allow/deny but list is empty
user-deniedcriticalCurrent user denied
user-allowedinfoCurrent user allowed
{ "codebuddy.accessControl.defaultMode": "open" }

Workspace .codebuddy/access.json takes priority when present.

  • Path traversal — config path resolved + verified within workspace boundary.
  • Size limit — 64 KB before parsing.
  • Input validation — every identity, mode, and list entry sanitized.
  • No token exposure — identity resolution uses silent auth, reads username/email only, never tokens.
  • Security — the broader security layers this fits into
  • Credential proxy — the other team-mode control (centralized keys)