Security Guidelines
Relevant source files
The following files were used as context for generating this wiki page:
The putio-cli security architecture focuses on protecting user credentials, ensuring input integrity, and providing safety guardrails for automated agents. The system is designed to handle sensitive OAuth tokens through multi-layered redaction and hardened configuration storage while mitigating risks such as prompt injection and directory traversal.
The scope of security covers authentication, authorization, token exposure prevention, and unsafe shell behavior. Developers and users are encouraged to report technical vulnerabilities involving credential exposure or access-control bypass directly to devs@put.io.
Sources: SECURITY.md:1-20, README.md:95-103
Authentication and Credential Management
The CLI manages authentication through OAuth tokens which can be provided via environment variables, persisted configuration files, or named profiles. Named profiles allow for isolated environments (e.g., devs-fe-auto for automation).
Auth Precedence and Storage
The system resolves authentication using a specific hierarchy to prevent accidental exposure of long-lived credentials.
| Source | Identifier | Priority | Description |
|---|---|---|---|
| Environment | PUTIO_CLI_TOKEN | High | Overrides all persisted config; ideal for headless/CI. |
| Profile Env | PUTIO_CLI_PROFILE | Medium | Selects a specific named profile from the config. |
| Persisted Config | default_profile | Low | Uses the configured default in config.json. |
| Legacy Config | auth_token | Lowest | Supported for single-token legacy setups. |
Sources: README.md:104-110, src/internal/state.ts:402-460
Secure Configuration Storage
Persisted state is stored in config.json with restricted file system permissions. The application ensures that the configuration file and its parent directories are created with private permissions (0o600) to prevent unauthorized local access.
Sources: src/internal/state.test.ts:70-90, src/internal/state.ts:250-265
Output Redaction and Sanitization
The CliOutputService implements a recursive sanitization engine to prevent the accidental leakage of tokens in terminal and structured outputs.
Sensitive Data Redaction
The system identifies sensitive keys (e.g., auth_token, password, secret) using a regex pattern and replaces their values with [REDACTED]. This applies to:
- Plain Objects: Recursive redaction of sensitive keys.
- Strings: Regex-based redaction of Bearer tokens and URI query parameters (e.g.,
oauth_token=...). - URLs: Redaction of tokens embedded in download links or API endpoints.
const SENSITIVE_KEY_PATTERN =
/^(auth_?token|token|access_?token|refresh_?token|authorization|password|secret|cookie)$/i;
const REDACTED_VALUE = "[REDACTED]";
Sources: src/internal/output-service.ts:65-105, src/internal/output.test.ts:16-55
Terminal Safety
To prevent "terminal spoofing" or malicious control sequence execution, the terminal renderer strips escape sequences and control characters from API-returned text before display.
Sources: src/internal/output-service.ts:75-85, skills/putio-cli/references/guardrails.md:20-25
Agent Safety and Prompt Injection Guardrails
The CLI is "agent-first" and includes specific logic to protect AI agents from consuming untrusted API content as instructions.
Prompt Injection Detection
The system scans API-returned text for prompt injection patterns (e.g., "ignore previous instructions"). If a suspicious string is detected, the CLI does not rewrite the content but instead attaches safety metadata (_meta.agentSafety).
Safety Flow for Automated Agents
The following diagram illustrates how the CLI processes API responses to protect automated operators:
mermaid
graph TD
A[API Response Received] --> B{Scan for Patterns}
B -- Injection Pattern Found --> C[Mark JSON Path as Untrusted]
B -- Sensitive Key Found --> D[Replace Value with REDACTED]
C --> E[Attach _meta.agentSafety]
D --> F[Render Sanitized Output]
E --> F
F --> G[Agent Receives JSON/NDJSON]
The agentSafety metadata includes a list of untrustedTextPaths which instructs the agent to treat those specific JSON paths as hostile content.
Sources: src/internal/output-service.ts:140-190, src/internal/output.test.ts:125-155, skills/putio-cli/references/guardrails.md:5-15
Input Hardening and Validation
The CLI implements strict input validation to prevent common injection attacks and path traversal.
Resource and Identifier Hardening
- Path Traversal: Commands like
files renameandfiles mkdirreject names containing control characters or traversal segments (e.g.,../,%2e). - Field Selection: The
--fieldsflag rejects nested paths, brackets, or query fragments to ensure only top-level fields are accessed. - Type Safety: The CLI utilizes
Effect.Schemato enforce strict types (e.g.,NonBlankStringSchema,NonEmptyIdsSchema) before executing API requests.
| Input Type | Protection Mechanism |
|---|---|
| File Names | Rejects ../, %2e, and control characters. |
| Field Selectors | Rejects dots, brackets, and path fragments. |
| JSON Payloads | Validated against strict schemas with custom rules. |
| Resource IDs | Must be valid integers; rejects non-numeric segments. |
Sources: src/commands/files.ts:60-95, src/internal/command-specs.js:235-245, skills/putio-cli/references/guardrails.md:15-20
Operational Guardrails
Users and agents are encouraged to follow "Safe Mutation" workflows to prevent destructive actions:
- Dry Runs: Use the
--dry-runflag before any mutating command (delete, move, rename) to preview the plan. - Explicit Profiles: Use
PUTIO_CLI_PROFILEfor stable, non-human sessions to isolate credentials. - Restricted Reads: Use
--fieldsto minimize the data surface area returned by the API.
Sources: README.md:104-120, src/internal/agent-dx.ts:90-115
Conclusion
The putio-cli security model prioritizes credential isolation and the safe handling of untrusted API content. By combining restricted file permissions, robust output redaction, and specific metadata for agent safety, the CLI provides a secure environment for both human operators and automated workflows. Consistency in using --dry-run and structured output modes further reinforces this security posture.