AgentPaaS is a multi-tenant Agent Platform as a Service. Security is critical because:
External Attacker Malicious Tenant Compromised Agent
| | |
v v v
[API Gateway] [Tenant Boundary] [Sandbox]
- Auth bypass - Data leakage - Code injection
- CORS abuse - Quota bypass - Resource exhaustion
- Rate limit bypass - Privilege escalation - Secret exfiltration
- Input injection - SQL injection - Subprocess escape
API Key Authentication:
secrets.token_hex(16) (128-bit entropy)Authorization headerRBAC (Role-Based Access Control):
| Role | Permissions |
|---|---|
| Admin | tenants:*, agents:*, keys:*, billing:read, secrets:*, admin:* |
| Developer | agents:read/write/execute, keys:read/write, runs:read, secrets:read |
| Viewer | agents:read, runs:read, billing:read |
Requirements:
tenant_id filter via parameterized queries.format())Encryption:
cryptography library (MUST NOT fall back to base64)AGENTPAAS_MASTER_KEY environment variableInjection:
%, _)Implementation:
lambdagent/tool_gateway.py(2026-03-28)All tool calls pass through
GatedToolbefore execution. This closes the gap whereguard.dangerousCommandBlockandguard.highRiskConfirmationwere declared in YAML configs but had zero runtime effect.
How it works in the PaaS context:
guard config via POST /api/v1/agentsPOST /api/v1/agents/{id}/run, compiler calls build_agent(config)build_agent() reads guard → creates ToolGateway(GatewayPolicy.from_guard_config(...))Tool in the agent is wrapped as GatedToolRisk classification (5 levels, 50+ regex patterns):
| Level | Action when dangerousCommandBlock: true |
|---|---|
| CRITICAL | Always BLOCK (e.g., rm -rf /, curl\|sh, credential access) |
| HIGH | BLOCK, or CONFIRM if highRiskConfirmation: true (e.g., sudo, rm -r, pip install) |
| MEDIUM | LOG_ONLY (e.g., mv, sed -i, git rebase) |
| LOW / SAFE | ALLOW (e.g., ls, cat, git status, terminate) |
Output control:
guard.maxOutputLength now enforced: GatedTool truncates output, Guard triggers retry/fallbackAudit trail:
gateway.audit.entries / gateway.audit.statsGatewayPolicy.audit_fileConfirmation flow for multi-tenant:
highRiskConfirmation: true triggers policy.confirm_callback(tool, input, reason)Per-tenant policy:
guard config creates its own GatewayPolicydangerousCommandBlock: false (dev mode)dangerousCommandBlock: true + highRiskConfirmation: truemacOS sandbox fix:
RLIMIT_NPROC (block subprocess creation) previously failed silently on macOSsubprocess/os.system/os.exec**)~/.agentpaas/config.json): plaintext (acceptable for dev)~/.agentpaas/wechat/credentials.json): SHOULD be encryptedAll security-relevant operations MUST be logged:
| ID | Item | Status |
|---|---|---|
| SEC-09 | Fix sandbox code injection | ✅ Input via JSON in sandbox.py |
| SEC-22 | macOS RLIMIT_NPROC fallback |
✅ Python-level monkey-patch in sandbox.py |
| SEC-24 | ToolGateway — runtime tool permission enforcement | ✅ lambdagent/tool_gateway.py |
| SEC-25 | guard.dangerousCommandBlock enforcement | ✅ compiler.py → GatedTool wraps all tools |
| SEC-26 | guard.highRiskConfirmation enforcement | ✅ confirm_callback flow in GatedTool |
| SEC-27 | guard.maxOutputLength enforcement | ✅ truncation in GatedTool + retry in Guard |
| SEC-28 | Tool call audit logging | ✅ AuditLog in tool_gateway.py |
/api/v1/admin/* routes (2026-04-01)allow_origins=["*"] with configurable whitelist (2026-04-01)scoped_query() from tenant/isolation.py (SQL injection risk) (2026-04-01)api/v1/agents.py (2026-04-01)AGENTPAAS_MASTER_KEY — error on startup if not set (non-dev mode) (2026-04-01)TenantContext.rate_limitos.environmax_length on RunRequest.input, config fieldscryptography library, no base64 fallback/api/v1/traces endpoint/api/v1/status/agents/{id}/healthstrict() for all agents)secrets.token_urlsafe(32)