Overview
Tank uses a capability-based permission system where skills must explicitly declare required capabilities in their manifest. This is inspired by:- Deno: Explicit
--allow-net,--allow-read, etc. - Android: App permissions requested at install time
- Web browsers: Permission prompts for camera, location, notifications
Permission Categories
Frompackages/shared/src/schemas/permissions.ts:
1. Network Permission
Field:permissions.network.outbound
Type: string[] (array of domain patterns)
Purpose: Controls which domains a skill can make HTTP/HTTPS requests to
Patterns:
"api.example.com"— exact domain"*.example.com"— all subdomains"*"— all domains (discouraged, triggers warning)
- Stage 2 (Static Analysis) cross-checks detected network calls vs declared domains
- Undeclared network access → High severity finding
- HTTP client library intercepts all requests
- Checks destination domain against allowlist
- Rejects request if not allowed
2. Filesystem Permission
Fields:permissions.filesystem.read, permissions.filesystem.write
Type: string[] (array of glob patterns relative to project root)
Purpose: Controls which files/directories a skill can access
Patterns:
"src/**/*.ts"— all TypeScript files in src/".env"— specific file (dangerous, triggers warning)"docs/*.md"— all markdown files in docs/"**"— all files (discouraged)
- Stage 2 (Static Analysis) flags hardcoded sensitive paths (
.ssh,.aws,.env) - Stage 4 (Secrets) flags attempts to read credentials
- File system operations intercepted
- Path matched against glob patterns
- Rejects access if not allowed
3. Subprocess Permission
Field:permissions.subprocess
Type: boolean
Purpose: Controls whether skill can spawn child processes
Default: false
Example:
- Stage 2 (Static Analysis) detects subprocess usage (
subprocess.run,child_process.exec,os.system) - If code uses subprocesses but
subprocess: false→ High severity finding
subprocessmodule patched to check permission- Throws error if permission not granted
Permission Declaration
Permissions are declared inSKILL.md frontmatter (parsed at publish time):
package.json (if using npm-style packaging):
Permission Escalation Detection
When publishing a new version of a skill, Tank compares permissions vs the previous version. Fromapps/web/lib/permission-escalation.ts:
Rules
| Old Version | New Version | Permission Change | Allowed? |
|---|---|---|---|
| 1.0.0 | 1.1.0 | Added network.outbound | ❌ (minor bump, must be 2.0.0) |
| 1.0.0 | 2.0.0 | Added network.outbound | ✅ (major bump) |
| 1.0.0 | 1.0.1 | None | ✅ (patch is OK) |
| 1.0.0 | 1.1.0 | Removed a permission | ✅ (reduction is safe) |
Install-Time User Review
When a user runstank install my-skill, the CLI displays:
Audit Score Impact
Fromapps/web/lib/audit-score.ts, permissions affect the 0-10 score:
Check 3: Permissions Declared (+1 point)
- Passes if
permissionsobject is non-empty - Fails if
permissions = {}or missing
- Don’t need any capabilities (unlikely)
- Forgot to declare (incomplete manifest)
- Intentionally hiding capabilities (malicious)
- Stage 2 (Static Analysis) extracts permissions from code (e.g., detects
fetch()calls) - Compares extracted vs declared
- Passes if extracted ⊆ declared
- Fails if code uses undeclared capabilities
CLI Command: tank permissions
View permissions for an installed skill:
Default Permissions
Frompackages/shared/src/constants/permissions.ts:
Permission Categories Reference
| Category | Default | Description | Enforcement Status |
|---|---|---|---|
network.outbound | undefined (deny all) | HTTP/HTTPS requests to specific domains | Planned (v2.0) |
filesystem.read | undefined (deny all) | Read access to files/directories | Planned (v2.0) |
filesystem.write | undefined (deny all) | Write access to files/directories | Planned (v2.0) |
subprocess | false | Ability to spawn child processes | Planned (v2.0) |
Best Practices for Skill Authors
1. Principle of Least Privilege
Only request permissions you actually need. Bad:2. Be Specific with Domains
Avoid wildcards unless necessary. OK:"*.github.com" (GitHub has many subdomains)
Bad: "*" (all domains)
3. Explain in README
Document WHY your skill needs each permission.4. Avoid Subprocess
Most skills should NOT spawn processes. If you must, explain why.5. Version Bumps for New Permissions
If adding a new permission, bump the MAJOR version (e.g., 1.2.0 → 2.0.0).Runtime Enforcement Roadmap (v2.0)
Planned Implementation:- Interceptor Layer: Patch Node.js/Python built-ins at skill import time
- Permission Checks: Before each operation, check against declared permissions
- Denial Handling: Throw
PermissionDeniedErrorwith helpful message
Next Steps
Audit Score
How permissions affect the 0-10 score
Best Practices
Security guidelines for skill authors