If you discover a security vulnerability, please report it privately:
- Do not open a public issue
- Email the maintainer or use GitHub's private vulnerability reporting
- Include steps to reproduce the issue
- Allow reasonable time for a fix before public disclosure
Only the latest version receives security updates.
| Version | Supported |
|---|---|
| Latest | Yes |
| Older | No |
This section documents the authorization and security model for claude-threads.
Claude-threads uses a multi-layer authorization model:
-
Platform-level (
allowedUsersin config)- Defines who can start new sessions and use the
!killcommand - Checked via
client.isUserAllowed(username)
- Defines who can start new sessions and use the
-
Session-level (
sessionAllowedUsersper session)- Defines who can participate in a specific session
- Includes the session owner + invited users
- Checked via
session.sessionAllowedUsers.has(username)
-
Role-based (session owner vs. invited users)
- Some actions require session ownership (owner or globally allowed)
- Enforced via
requireSessionOwner()in commands
| Action | Session Owner | Invited User | Global Allowed | Unauthorized |
|---|---|---|---|---|
| Start new session | N/A | N/A | Yes | No |
| Send message to session | Yes | Yes | Yes | Needs approval |
| Resume paused session | Yes | Yes | Yes | No |
!cd change directory |
Yes | No | Yes | No |
!invite user |
Yes | No | Yes | No |
!kick user |
Yes | No | Yes | No |
!permissions interactive |
Yes | No | Yes | No |
!worktree management |
Yes | No | Yes | No |
!update force/defer |
Yes | No | Yes | No |
!kill emergency shutdown |
N/A | N/A | Yes | No |
| Answer question (reaction) | Yes | Yes | Yes | No |
| Approve plan (reaction) | Yes | Yes | Yes | No |
| Cancel session (reaction) | Yes | Yes | Yes | No |
| Interrupt session (reaction) | Yes | Yes | Yes | No |
| Toggle task list | Yes | Yes | Yes | No |
src/message-handler.ts- Entry point for all messages- Lines 61-64:
!killrequiresclient.isUserAllowed() - Lines 110-115: Commands require
session.isUserAllowedInSession() - Lines 256-260: Unauthorized users get message approval flow
- Lines 61-64:
src/session/manager.ts:417-422- Reaction authorization (primary gate)- All reactions are validated here before reaching MessageManager/executors
- Both
sessionAllowedUsersandplatform.isUserAllowed()checked - Unauthorized reactions are silently dropped
src/operations/commands/handler.ts- Command authorizationrequireSessionOwner()function enforces ownership for sensitive commands- Applied to:
changeDirectory(),inviteUser(),kickUser(),enableInteractivePermissions()
src/operations/executors/message-approval.ts- Handles unauthorized message approval- Validates user before allowing message to be sent
When an unauthorized user sends a message to an active session:
- Message is intercepted before reaching Claude CLI
- Approval request posted with reaction options: Allow once / Invite / Deny
- Session owner or allowed user must react to approve
- Only after approval is the message forwarded to Claude
The Claude CLI permission system works via MCP (Model Context Protocol):
- MCP server spawned per session with platform credentials
- When Claude needs permission (file write, etc.), MCP server posts to chat
- Users react to approve/deny
- MCP server validates reacting user is in allowed list
- Permission response returned to Claude CLI
- Defense in Depth - Multiple authorization checks at different layers
- Principle of Least Privilege - Invited users have fewer permissions than owners
- Fail Closed - Unknown users are rejected by default
- Audit Trail - All authorization decisions are logged