Security practices, threat model, and mitigation strategies
AgentStack handles sensitive data including API keys, user content, and system operations. This document outlines security considerations and best practices.
| Asset | Sensitivity | Description |
|---|---|---|
| API Keys | Critical | LLM provider credentials |
| Memory Content | High | User-stored data and context |
| Configuration | Medium | System settings and paths |
| Embeddings | Medium | Vector representations of content |
| Task Data | Medium | Task inputs and outputs |
- Malicious Plugins: Untrusted code loaded at runtime
- Prompt Injection: Malicious content in stored memory
- Local Attacker: Access to filesystem or database
- Network Attacker: Interception of API calls
Current Implementation:
- API keys read from config file or environment variables
- Environment variable interpolation:
${ANTHROPIC_API_KEY} - Keys passed directly to provider constructors
Best Practices:
# Use environment variables (recommended)
export ANTHROPIC_API_KEY="sk-..."
export OPENAI_API_KEY="sk-..."
# Config file references env vars
{
"providers": {
"anthropic": {
"apiKey": "${ANTHROPIC_API_KEY}"
}
}
}Recommendations:
- Never commit API keys to version control
- Use environment variables in production
- Rotate keys periodically
- Use scoped/limited API keys when possible
SQLite Implementation:
- Embedded database (no network exposure)
- File-based storage (filesystem permissions apply)
- Parameterized queries prevent SQL injection
Input Validation:
// Zod validation for all inputs
const schema = z.object({
key: z.string().min(1).max(255),
content: z.string().max(1_000_000),
namespace: z.string().max(100).optional()
});FTS5 Query Escaping:
function escapeFtsQuery(query: string): string {
// Escape special characters to prevent FTS injection
return query.replace(/["'*()-:]/g, char => `"${char}"`);
}Risks:
- Plugins execute arbitrary code
- Access to all exports and APIs
- No sandboxing
Current Mitigations:
- Manual plugin installation required
- Plugin validation on load
- Plugin registry tracking
Recommendations:
- Only install plugins from trusted sources
- Review plugin code before installation
- Use separate environments for untrusted plugins
- Monitor plugin behavior
Implementation:
- Uses
ghCLI (requires pre-authentication) - Subprocess execution with timeout
- No direct token handling in most cases
Subprocess Security:
// Proper argument handling (no shell injection)
execFileSync('gh', ['issue', 'create', '--title', title], {
timeout: 30000,
encoding: 'utf-8'
});Risks:
- Authenticated gh CLI has repository access
- Commands could be influenced by user input
Mitigations:
- Input validation before gh commands
- Timeout on all subprocess calls
- No shell interpolation (execFileSync)
Purpose: Prevent agents in different sessions from accessing each other's memory (cross-session contamination).
Implementation (v1.5.2+):
- Each session gets a dedicated namespace:
session:{sessionId} - Memory operations are scoped to the caller's session
- Cross-session access attempts are blocked and logged
sessionIdis required for all write/delete operations
Access Control (src/memory/access-control.ts):
// Validate that memory operations stay within session boundaries
validateAccess(context: MemoryAccessContext, namespace: string, operation: 'read'|'write'|'delete'): void
// Check if context can access a specific entry
canAccessEntry(context: MemoryAccessContext, entryNamespace: string, entryAgentId?: string): booleanSession Cleanup:
- When a session ends, all session-scoped memory is automatically deleted
- Agents in the session are stopped
- Audit logging tracks cleanup operations
REST API Protection:
POST /api/v1/memoryrequiressessionIdfor write operationsDELETE /api/v1/memory/:keyrequiressessionIdfor delete operations- Read operations can optionally filter by session
Transport:
- stdio transport (no network exposure)
- Process-level isolation from client
Input Validation:
- All tool inputs validated with Zod schemas
- Unknown tools return error
Output Handling:
- JSON serialization of results
- Error messages sanitized
{
"providers": {
"anthropic": {
"apiKey": "${ANTHROPIC_API_KEY}"
}
},
"github": {
"enabled": false
},
"plugins": {
"enabled": false
}
}- Disable unused features: Set
github.enabledandplugins.enabledto false if not needed - Use environment variables: Never hardcode API keys
- Restrict file permissions:
chmod 600 aistack.config.json
-
Filesystem:
# Secure config file chmod 600 aistack.config.json # Secure database chmod 600 ./data/aistack.db
-
Process Isolation:
- Run as non-root user
- Use container isolation if possible
-
Network:
- AgentStack makes outbound HTTPS calls to:
api.anthropic.comapi.openai.comlocalhost:11434(Ollama, if enabled)
- No inbound connections (stdio transport)
- AgentStack makes outbound HTTPS calls to:
Logging:
- All tool calls logged
- Errors logged with context
- API keys truncated in logs
What to Monitor:
- Unusual API call patterns
- Failed authentication attempts
- Plugin load events
- Error rates
- SQLite database is unencrypted
- Embeddings stored as plaintext BLOBs
- Mitigation: Use filesystem encryption
- Session-based memory isolation prevents cross-session contamination (v1.5.2+)
- All MCP tools available to any MCP client (no per-tool ACLs)
- No user authentication at the protocol level
- Mitigation: Process-level access control, session-based isolation
- No code signing or verification
- Full API access
- Mitigation: Manual review and trusted sources
- Stored content could contain sensitive data
- No automatic PII detection
- Mitigation: User responsibility for content
- API keys in environment variables
- Config file permissions restricted
- Database file permissions restricted
- Unused features disabled
- Plugins reviewed (if enabled)
- API keys rotated periodically
- Logs reviewed for anomalies
- Dependencies updated
- Database backed up securely
-
API Key Compromise:
- Immediately rotate affected keys
- Review API usage logs
- Update configuration
-
Database Exposure:
- Assess data sensitivity
- Consider re-encryption
- Review access logs
-
Plugin Vulnerability:
- Disable affected plugin
- Review plugin actions
- Update or remove plugin
Report security issues to the repository maintainers via:
- GitHub Security Advisories
- Private disclosure to maintainers
- OPERATIONS.md - Operational security
- DATA.md - Data storage details
- API.md - Input validation details