Security improvements: per-group session isolation, remove built-in Gmail
- Isolate Claude sessions per-group (data/sessions/{group}/.claude/)
to prevent cross-group access to conversation history
- Remove Gmail MCP from built-in (now available via /add-gmail skill)
- Add SECURITY.md documenting the security model
- Move docs to docs/ folder (SPEC.md, REQUIREMENTS.md, SECURITY.md)
- Update documentation to reflect changes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,8 +19,8 @@ src/container-runner.ts container/agent-runner/
|
|||||||
│ │
|
│ │
|
||||||
├── data/env/env ──────────────> /workspace/env-dir/env
|
├── data/env/env ──────────────> /workspace/env-dir/env
|
||||||
├── groups/{folder} ───────────> /workspace/group
|
├── groups/{folder} ───────────> /workspace/group
|
||||||
├── data/ipc ──────────────────> /workspace/ipc
|
├── data/ipc/{folder} ────────> /workspace/ipc
|
||||||
├── ~/.claude/ ────────────────> /home/node/.claude/ (sessions)
|
├── data/sessions/{folder}/.claude/ ──> /home/node/.claude/ (isolated per-group)
|
||||||
└── (main only) project root ──> /workspace/project
|
└── (main only) project root ──> /workspace/project
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -171,14 +171,7 @@ mounts.push({
|
|||||||
|
|
||||||
### 6. MCP Server Failures
|
### 6. MCP Server Failures
|
||||||
|
|
||||||
If an MCP server fails to start, the agent may exit. Test MCP servers individually:
|
If an MCP server fails to start, the agent may exit. Check the container logs for MCP initialization errors.
|
||||||
|
|
||||||
```bash
|
|
||||||
# Test Gmail MCP
|
|
||||||
container run --rm --entrypoint /bin/bash nanoclaw-agent:latest -c '
|
|
||||||
npx -y @gongrzhe/server-gmail-autoauth-mcp --help
|
|
||||||
'
|
|
||||||
```
|
|
||||||
|
|
||||||
## Manual Container Testing
|
## Manual Container Testing
|
||||||
|
|
||||||
@@ -267,7 +260,7 @@ container run --rm --entrypoint /bin/bash nanoclaw-agent:latest -c '
|
|||||||
|
|
||||||
## Session Persistence
|
## Session Persistence
|
||||||
|
|
||||||
Claude sessions are stored in `~/.claude/projects/` on the host, mounted to `/home/node/.claude/projects/` inside the container.
|
Claude sessions are stored per-group in `data/sessions/{group}/.claude/` for security isolation. Each group has its own session directory, preventing cross-group access to conversation history.
|
||||||
|
|
||||||
**Critical:** The mount path must match the container user's HOME directory:
|
**Critical:** The mount path must match the container user's HOME directory:
|
||||||
- Container user: `node`
|
- Container user: `node`
|
||||||
@@ -277,11 +270,11 @@ Claude sessions are stored in `~/.claude/projects/` on the host, mounted to `/ho
|
|||||||
To clear sessions:
|
To clear sessions:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Clear all sessions
|
# Clear all sessions for all groups
|
||||||
rm -rf ~/.claude/projects/
|
rm -rf data/sessions/
|
||||||
|
|
||||||
# Clear sessions for a specific group
|
# Clear sessions for a specific group
|
||||||
rm -rf ~/.claude/projects/*workspace-group*/
|
rm -rf data/sessions/{groupFolder}/.claude/
|
||||||
|
|
||||||
# Also clear the session ID from NanoClaw's tracking
|
# Also clear the session ID from NanoClaw's tracking
|
||||||
echo '{}' > data/sessions.json
|
echo '{}' > data/sessions.json
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: setup
|
name: setup
|
||||||
description: Run initial NanoClaw setup. Use when user wants to install dependencies, authenticate WhatsApp/Gmail, register their main channel, or start the background services. Triggers on "setup", "install", "configure nanoclaw", or first-time setup requests.
|
description: Run initial NanoClaw setup. Use when user wants to install dependencies, authenticate WhatsApp, register their main channel, or start the background services. Triggers on "setup", "install", "configure nanoclaw", or first-time setup requests.
|
||||||
---
|
---
|
||||||
|
|
||||||
# NanoClaw Setup
|
# NanoClaw Setup
|
||||||
@@ -286,34 +286,7 @@ Tell the user:
|
|||||||
> }
|
> }
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
## 9. Gmail Authentication (Optional)
|
## 9. Configure launchd Service
|
||||||
|
|
||||||
Ask the user:
|
|
||||||
> Do you want to enable Gmail integration for reading/sending emails?
|
|
||||||
>
|
|
||||||
> **Note:** This requires setting up Google Cloud Platform OAuth credentials, which involves:
|
|
||||||
> 1. Creating a GCP project
|
|
||||||
> 2. Enabling the Gmail API
|
|
||||||
> 3. Creating OAuth 2.0 credentials
|
|
||||||
> 4. Downloading a credentials file
|
|
||||||
>
|
|
||||||
> This takes about 5-10 minutes. Skip if you don't need email integration.
|
|
||||||
|
|
||||||
If yes, guide them through the prerequisites:
|
|
||||||
1. Go to https://console.cloud.google.com
|
|
||||||
2. Create a new project (or use an existing one)
|
|
||||||
3. Enable the Gmail API (APIs & Services → Enable APIs → search "Gmail API")
|
|
||||||
4. Create OAuth 2.0 credentials (APIs & Services → Credentials → Create Credentials → OAuth client ID → Desktop app)
|
|
||||||
5. Download the JSON file and save to `~/.gmail-mcp/gcp-oauth.keys.json`
|
|
||||||
|
|
||||||
Then run:
|
|
||||||
```bash
|
|
||||||
npx -y @gongrzhe/server-gmail-autoauth-mcp
|
|
||||||
```
|
|
||||||
|
|
||||||
This will open a browser for OAuth consent. After authorization, credentials are cached.
|
|
||||||
|
|
||||||
## 10. Configure launchd Service
|
|
||||||
|
|
||||||
Generate the plist file with correct paths automatically:
|
Generate the plist file with correct paths automatically:
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {}
|
||||||
"gmail": {
|
|
||||||
"command": "npx",
|
|
||||||
"args": ["-y", "@gongrzhe/server-gmail-autoauth-mcp"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# NanoClaw
|
# NanoClaw
|
||||||
|
|
||||||
Personal Claude assistant. See [README.md](README.md) for philosophy and setup. See [REQUIREMENTS.md](REQUIREMENTS.md) for architecture decisions.
|
Personal Claude assistant. See [README.md](README.md) for philosophy and setup. See [docs/REQUIREMENTS.md](docs/REQUIREMENTS.md) for architecture decisions.
|
||||||
|
|
||||||
## Quick Context
|
## Quick Context
|
||||||
|
|
||||||
|
|||||||
@@ -45,10 +45,10 @@ Then run `/setup`. Claude Code handles everything: dependencies, authentication,
|
|||||||
- **WhatsApp I/O** - Message Claude from your phone
|
- **WhatsApp I/O** - Message Claude from your phone
|
||||||
- **Isolated group context** - Each group has its own `CLAUDE.md` memory, isolated filesystem, and runs in its own container sandbox with only that filesystem mounted
|
- **Isolated group context** - Each group has its own `CLAUDE.md` memory, isolated filesystem, and runs in its own container sandbox with only that filesystem mounted
|
||||||
- **Main channel** - Your private channel (self-chat) for admin control; every other group is completely isolated
|
- **Main channel** - Your private channel (self-chat) for admin control; every other group is completely isolated
|
||||||
- **Email** - Read and send via Gmail (optional)
|
|
||||||
- **Scheduled tasks** - Recurring jobs that run Claude and can message you back
|
- **Scheduled tasks** - Recurring jobs that run Claude and can message you back
|
||||||
- **Web access** - Search and fetch content
|
- **Web access** - Search and fetch content
|
||||||
- **Container isolation** - Agents sandboxed in Apple containers
|
- **Container isolation** - Agents sandboxed in Apple containers
|
||||||
|
- **Optional integrations** - Add Gmail (`/add-gmail`) and more via skills
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ Yes. Run Claude Code and say "make this run on Linux." ~30 min of back-and-forth
|
|||||||
|
|
||||||
**Is this secure?**
|
**Is this secure?**
|
||||||
|
|
||||||
Agents run in containers, not behind application-level permission checks. They can only access explicitly mounted directories. You should still review what you're running, but the codebase is small enough that you actually can.
|
Agents run in containers, not behind application-level permission checks. They can only access explicitly mounted directories. You should still review what you're running, but the codebase is small enough that you actually can. See [docs/SECURITY.md](docs/SECURITY.md) for the full security model.
|
||||||
|
|
||||||
**Why no configuration files?**
|
**Why no configuration files?**
|
||||||
|
|
||||||
|
|||||||
@@ -243,15 +243,13 @@ async function main(): Promise<void> {
|
|||||||
'Bash',
|
'Bash',
|
||||||
'Read', 'Write', 'Edit', 'Glob', 'Grep',
|
'Read', 'Write', 'Edit', 'Glob', 'Grep',
|
||||||
'WebSearch', 'WebFetch',
|
'WebSearch', 'WebFetch',
|
||||||
'mcp__nanoclaw__*',
|
'mcp__nanoclaw__*'
|
||||||
'mcp__gmail__*'
|
|
||||||
],
|
],
|
||||||
permissionMode: 'bypassPermissions',
|
permissionMode: 'bypassPermissions',
|
||||||
allowDangerouslySkipPermissions: true,
|
allowDangerouslySkipPermissions: true,
|
||||||
settingSources: ['project'],
|
settingSources: ['project'],
|
||||||
mcpServers: {
|
mcpServers: {
|
||||||
nanoclaw: ipcMcp,
|
nanoclaw: ipcMcp
|
||||||
gmail: { command: 'npx', args: ['-y', '@gongrzhe/server-gmail-autoauth-mcp'] }
|
|
||||||
},
|
},
|
||||||
hooks: {
|
hooks: {
|
||||||
PreCompact: [{ hooks: [createPreCompactHook()] }]
|
PreCompact: [{ hooks: [createPreCompactHook()] }]
|
||||||
|
|||||||
@@ -142,10 +142,6 @@ A personal Claude assistant accessible via WhatsApp, with minimal custom code.
|
|||||||
- Messages stored in SQLite, polled by router
|
- Messages stored in SQLite, polled by router
|
||||||
- QR code authentication during setup
|
- QR code authentication during setup
|
||||||
|
|
||||||
### Email (Gmail)
|
|
||||||
- Read-only MCP integration (can read and send, but not an I/O channel)
|
|
||||||
- Optional, enabled during setup
|
|
||||||
|
|
||||||
### Scheduler
|
### Scheduler
|
||||||
- Built-in scheduler runs on the host, spawns containers for task execution
|
- Built-in scheduler runs on the host, spawns containers for task execution
|
||||||
- Custom `nanoclaw` MCP server (inside container) provides scheduling tools
|
- Custom `nanoclaw` MCP server (inside container) provides scheduling tools
|
||||||
@@ -175,7 +171,7 @@ A personal Claude assistant accessible via WhatsApp, with minimal custom code.
|
|||||||
- Each user gets a custom setup matching their exact needs
|
- Each user gets a custom setup matching their exact needs
|
||||||
|
|
||||||
### Skills
|
### Skills
|
||||||
- `/setup` - Install dependencies, authenticate WhatsApp/Gmail, configure scheduler, start services
|
- `/setup` - Install dependencies, authenticate WhatsApp, configure scheduler, start services
|
||||||
- `/customize` - General-purpose skill for adding capabilities (new channels like Telegram, new integrations, behavior changes)
|
- `/customize` - General-purpose skill for adding capabilities (new channels like Telegram, new integrations, behavior changes)
|
||||||
|
|
||||||
### Deployment
|
### Deployment
|
||||||
@@ -191,7 +187,6 @@ These are the creator's settings, stored here for reference:
|
|||||||
- **Trigger**: `@Andy` (case insensitive)
|
- **Trigger**: `@Andy` (case insensitive)
|
||||||
- **Response prefix**: `Andy:`
|
- **Response prefix**: `Andy:`
|
||||||
- **Persona**: Default Claude (no custom personality)
|
- **Persona**: Default Claude (no custom personality)
|
||||||
- **Gmail**: Enabled
|
|
||||||
- **Main channel**: Self-chat (messaging yourself in WhatsApp)
|
- **Main channel**: Self-chat (messaging yourself in WhatsApp)
|
||||||
|
|
||||||
---
|
---
|
||||||
119
docs/SECURITY.md
Normal file
119
docs/SECURITY.md
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# NanoClaw Security Model
|
||||||
|
|
||||||
|
## Trust Model
|
||||||
|
|
||||||
|
| Entity | Trust Level | Rationale |
|
||||||
|
|--------|-------------|-----------|
|
||||||
|
| Main group | Trusted | Private self-chat, admin control |
|
||||||
|
| Non-main groups | Untrusted | Other users may be malicious |
|
||||||
|
| Container agents | Sandboxed | Isolated execution environment |
|
||||||
|
| WhatsApp messages | User input | Potential prompt injection |
|
||||||
|
|
||||||
|
## Security Boundaries
|
||||||
|
|
||||||
|
### 1. Container Isolation (Primary Boundary)
|
||||||
|
|
||||||
|
Agents execute in Apple Container (lightweight Linux VMs), providing:
|
||||||
|
- **Process isolation** - Container processes cannot affect the host
|
||||||
|
- **Filesystem isolation** - Only explicitly mounted directories are visible
|
||||||
|
- **Non-root execution** - Runs as unprivileged `node` user (uid 1000)
|
||||||
|
- **Ephemeral containers** - Fresh environment per invocation (`--rm`)
|
||||||
|
|
||||||
|
This is the primary security boundary. Rather than relying on application-level permission checks, the attack surface is limited by what's mounted.
|
||||||
|
|
||||||
|
### 2. Mount Security
|
||||||
|
|
||||||
|
**External Allowlist** - Mount permissions stored at `~/.config/nanoclaw/mount-allowlist.json`, which is:
|
||||||
|
- Outside project root
|
||||||
|
- Never mounted into containers
|
||||||
|
- Cannot be modified by agents
|
||||||
|
|
||||||
|
**Default Blocked Patterns:**
|
||||||
|
```
|
||||||
|
.ssh, .gnupg, .aws, .azure, .gcloud, .kube, .docker,
|
||||||
|
credentials, .env, .netrc, .npmrc, id_rsa, id_ed25519,
|
||||||
|
private_key, .secret
|
||||||
|
```
|
||||||
|
|
||||||
|
**Protections:**
|
||||||
|
- Symlink resolution before validation (prevents traversal attacks)
|
||||||
|
- Container path validation (rejects `..` and absolute paths)
|
||||||
|
- `nonMainReadOnly` option forces read-only for non-main groups
|
||||||
|
|
||||||
|
### 3. Session Isolation
|
||||||
|
|
||||||
|
Each group has isolated Claude sessions at `data/sessions/{group}/.claude/`:
|
||||||
|
- Groups cannot see other groups' conversation history
|
||||||
|
- Session data includes full message history and file contents read
|
||||||
|
- Prevents cross-group information disclosure
|
||||||
|
|
||||||
|
### 4. IPC Authorization
|
||||||
|
|
||||||
|
Messages and task operations are verified against group identity:
|
||||||
|
|
||||||
|
| Operation | Main Group | Non-Main Group |
|
||||||
|
|-----------|------------|----------------|
|
||||||
|
| Send message to own chat | ✓ | ✓ |
|
||||||
|
| Send message to other chats | ✓ | ✗ |
|
||||||
|
| Schedule task for self | ✓ | ✓ |
|
||||||
|
| Schedule task for others | ✓ | ✗ |
|
||||||
|
| View all tasks | ✓ | Own only |
|
||||||
|
| Manage other groups | ✓ | ✗ |
|
||||||
|
|
||||||
|
### 5. Credential Handling
|
||||||
|
|
||||||
|
**Mounted Credentials:**
|
||||||
|
- Claude auth tokens (filtered from `.env`, read-only)
|
||||||
|
|
||||||
|
**NOT Mounted:**
|
||||||
|
- WhatsApp session (`store/auth/`) - host only
|
||||||
|
- Mount allowlist - external, never mounted
|
||||||
|
- Any credentials matching blocked patterns
|
||||||
|
|
||||||
|
**Credential Filtering:**
|
||||||
|
Only these environment variables are exposed to containers:
|
||||||
|
```typescript
|
||||||
|
const allowedVars = ['CLAUDE_CODE_OAUTH_TOKEN', 'ANTHROPIC_API_KEY'];
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** Anthropic credentials are mounted so that Claude Code can authenticate when the agent runs. However, this means the agent itself can discover these credentials via Bash or file operations. Ideally, Claude Code would authenticate without exposing credentials to the agent's execution environment, but I couldn't figure this out. **PRs welcome** if you have ideas for credential isolation.
|
||||||
|
|
||||||
|
## Privilege Comparison
|
||||||
|
|
||||||
|
| Capability | Main Group | Non-Main Group |
|
||||||
|
|------------|------------|----------------|
|
||||||
|
| Project root access | `/workspace/project` (rw) | None |
|
||||||
|
| Group folder | `/workspace/group` (rw) | `/workspace/group` (rw) |
|
||||||
|
| Global memory | Implicit via project | `/workspace/global` (ro) |
|
||||||
|
| Additional mounts | Configurable | Read-only unless allowed |
|
||||||
|
| Network access | Unrestricted | Unrestricted |
|
||||||
|
| MCP tools | All | All |
|
||||||
|
|
||||||
|
## Security Architecture Diagram
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────────────────────────────────────────────────────────┐
|
||||||
|
│ UNTRUSTED ZONE │
|
||||||
|
│ WhatsApp Messages (potentially malicious) │
|
||||||
|
└────────────────────────────────┬─────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼ Trigger check, input escaping
|
||||||
|
┌──────────────────────────────────────────────────────────────────┐
|
||||||
|
│ HOST PROCESS (TRUSTED) │
|
||||||
|
│ • Message routing │
|
||||||
|
│ • IPC authorization │
|
||||||
|
│ • Mount validation (external allowlist) │
|
||||||
|
│ • Container lifecycle │
|
||||||
|
│ • Credential filtering │
|
||||||
|
└────────────────────────────────┬─────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼ Explicit mounts only
|
||||||
|
┌──────────────────────────────────────────────────────────────────┐
|
||||||
|
│ CONTAINER (ISOLATED/SANDBOXED) │
|
||||||
|
│ • Agent execution │
|
||||||
|
│ • Bash commands (sandboxed) │
|
||||||
|
│ • File operations (limited to mounts) │
|
||||||
|
│ • Network access (unrestricted) │
|
||||||
|
│ • Cannot modify security config │
|
||||||
|
└──────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
@@ -54,7 +54,7 @@ A personal Claude assistant accessible via WhatsApp, with persistent memory per
|
|||||||
│ │ Volume mounts: │ │
|
│ │ Volume mounts: │ │
|
||||||
│ │ • groups/{name}/ → /workspace/group │ │
|
│ │ • groups/{name}/ → /workspace/group │ │
|
||||||
│ │ • groups/global/ → /workspace/global/ (non-main only) │ │
|
│ │ • groups/global/ → /workspace/global/ (non-main only) │ │
|
||||||
│ │ • ~/.claude/ → /home/node/.claude/ (sessions) │ │
|
│ │ • data/sessions/{group}/.claude/ → /home/node/.claude/ │ │
|
||||||
│ │ • Additional dirs → /workspace/extra/* │ │
|
│ │ • Additional dirs → /workspace/extra/* │ │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
│ │ Tools (all groups): │ │
|
│ │ Tools (all groups): │ │
|
||||||
@@ -63,7 +63,7 @@ A personal Claude assistant accessible via WhatsApp, with persistent memory per
|
|||||||
│ │ • WebSearch, WebFetch (internet access) │ │
|
│ │ • WebSearch, WebFetch (internet access) │ │
|
||||||
│ │ • agent-browser (browser automation) │ │
|
│ │ • agent-browser (browser automation) │ │
|
||||||
│ │ • mcp__nanoclaw__* (scheduler tools via IPC) │ │
|
│ │ • mcp__nanoclaw__* (scheduler tools via IPC) │ │
|
||||||
│ │ • mcp__gmail__* (email) │ │
|
│ │ │ │
|
||||||
│ └──────────────────────────────────────────────────────────────┘ │
|
│ └──────────────────────────────────────────────────────────────┘ │
|
||||||
│ │
|
│ │
|
||||||
└──────────────────────────────────────────────────────────────────────┘
|
└──────────────────────────────────────────────────────────────────────┘
|
||||||
@@ -87,7 +87,10 @@ A personal Claude assistant accessible via WhatsApp, with persistent memory per
|
|||||||
```
|
```
|
||||||
nanoclaw/
|
nanoclaw/
|
||||||
├── CLAUDE.md # Project context for Claude Code
|
├── CLAUDE.md # Project context for Claude Code
|
||||||
├── SPEC.md # This specification document
|
├── docs/
|
||||||
|
│ ├── SPEC.md # This specification document
|
||||||
|
│ ├── REQUIREMENTS.md # Architecture decisions
|
||||||
|
│ └── SECURITY.md # Security model
|
||||||
├── README.md # User documentation
|
├── README.md # User documentation
|
||||||
├── package.json # Node.js dependencies
|
├── package.json # Node.js dependencies
|
||||||
├── tsconfig.json # TypeScript configuration
|
├── tsconfig.json # TypeScript configuration
|
||||||
@@ -338,7 +341,7 @@ Sessions enable conversation continuity - Claude remembers what you talked about
|
|||||||
├── cwd: groups/{group-name}/
|
├── cwd: groups/{group-name}/
|
||||||
├── prompt: conversation history + current message
|
├── prompt: conversation history + current message
|
||||||
├── resume: session_id (for continuity)
|
├── resume: session_id (for continuity)
|
||||||
└── mcpServers: gmail, scheduler
|
└── mcpServers: nanoclaw (scheduler)
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
8. Claude processes message:
|
8. Claude processes message:
|
||||||
@@ -400,7 +403,7 @@ NanoClaw has a built-in scheduler that runs tasks as full agents in their group'
|
|||||||
### How Scheduling Works
|
### How Scheduling Works
|
||||||
|
|
||||||
1. **Group Context**: Tasks created in a group run with that group's working directory and memory
|
1. **Group Context**: Tasks created in a group run with that group's working directory and memory
|
||||||
2. **Full Agent Capabilities**: Scheduled tasks have access to all tools (WebSearch, Gmail, file operations, etc.)
|
2. **Full Agent Capabilities**: Scheduled tasks have access to all tools (WebSearch, file operations, etc.)
|
||||||
3. **Optional Messaging**: Tasks can send messages to their group using the `send_message` tool, or complete silently
|
3. **Optional Messaging**: Tasks can send messages to their group using the `send_message` tool, or complete silently
|
||||||
4. **Main Channel Privileges**: The main channel can schedule tasks for any group and view all tasks
|
4. **Main Channel Privileges**: The main channel can schedule tasks for any group and view all tasks
|
||||||
|
|
||||||
@@ -472,18 +475,6 @@ The `nanoclaw` MCP server is created dynamically per agent call with the current
|
|||||||
| `cancel_task` | Delete a task |
|
| `cancel_task` | Delete a task |
|
||||||
| `send_message` | Send a WhatsApp message to the group |
|
| `send_message` | Send a WhatsApp message to the group |
|
||||||
|
|
||||||
### Gmail MCP (@gongrzhe/server-gmail-autoauth-mcp)
|
|
||||||
|
|
||||||
Provides email capabilities. Requires Google Cloud OAuth setup.
|
|
||||||
|
|
||||||
**Available Tools:**
|
|
||||||
| Tool | Purpose |
|
|
||||||
|------|---------|
|
|
||||||
| `search_messages` | Search inbox |
|
|
||||||
| `get_message` | Read full email |
|
|
||||||
| `send_message` | Send email |
|
|
||||||
| `reply_message` | Reply to thread |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
@@ -593,9 +584,8 @@ WhatsApp messages could contain malicious instructions attempting to manipulate
|
|||||||
|
|
||||||
| Credential | Storage Location | Notes |
|
| Credential | Storage Location | Notes |
|
||||||
|------------|------------------|-------|
|
|------------|------------------|-------|
|
||||||
| Claude CLI Auth | ~/.claude/ | Mounted to /home/node/.claude/ in container |
|
| Claude CLI Auth | data/sessions/{group}/.claude/ | Per-group isolation, mounted to /home/node/.claude/ |
|
||||||
| WhatsApp Session | store/auth/ | Auto-created, persists ~20 days |
|
| WhatsApp Session | store/auth/ | Auto-created, persists ~20 days |
|
||||||
| Gmail OAuth Tokens | ~/.gmail-mcp/ | Created during setup (optional) |
|
|
||||||
|
|
||||||
### File Permissions
|
### File Permissions
|
||||||
|
|
||||||
@@ -96,25 +96,15 @@ function buildVolumeMounts(group: RegisteredGroup, isMain: boolean): VolumeMount
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Claude sessions directory (for session persistence)
|
// Per-group Claude sessions directory (isolated from other groups)
|
||||||
// Container runs as 'node' user with HOME=/home/node
|
// Each group gets their own .claude/ to prevent cross-group session access
|
||||||
const claudeDir = path.join(homeDir, '.claude');
|
const groupSessionsDir = path.join(DATA_DIR, 'sessions', group.folder, '.claude');
|
||||||
if (fs.existsSync(claudeDir)) {
|
fs.mkdirSync(groupSessionsDir, { recursive: true });
|
||||||
mounts.push({
|
mounts.push({
|
||||||
hostPath: claudeDir,
|
hostPath: groupSessionsDir,
|
||||||
containerPath: '/home/node/.claude',
|
containerPath: '/home/node/.claude',
|
||||||
readonly: false
|
readonly: false
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
const gmailDir = path.join(homeDir, '.gmail-mcp');
|
|
||||||
if (fs.existsSync(gmailDir)) {
|
|
||||||
mounts.push({
|
|
||||||
hostPath: gmailDir,
|
|
||||||
containerPath: '/home/node/.gmail-mcp',
|
|
||||||
readonly: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Per-group IPC namespace: each group gets its own IPC directory
|
// Per-group IPC namespace: each group gets its own IPC directory
|
||||||
// This prevents cross-group privilege escalation via IPC
|
// This prevents cross-group privilege escalation via IPC
|
||||||
|
|||||||
Reference in New Issue
Block a user