T09 · Insecure Skill Coding Practices
- Location
scripts/plutio-cli.py:361- Finding
Plutio API credentials are exposed through command-line arguments
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This Plutio skill mostly matches its stated task-management purpose, but it needs review because it handles long-lived API credentials unsafely and can read or change workspace data.
Review before installing. Use a Plutio API application with the narrowest permissions possible, avoid pasting secrets into chat or putting them in command history/profile files, prefer a password manager or OS credential store, and rotate credentials if they were already used in exposed examples. Treat people-list output and task data as sensitive business data, and require explicit confirmation before bulk updates, closures, or any direct API deletion.
scripts/plutio-cli.py:361Plutio API credentials are exposed through command-line arguments
references/setup-guide.md:59Setup documentation recommends persistent plaintext credential storage
scripts/plutio-cli.py:67OAuth bearer token cache is written before restrictive permissions are applied
The manifest overstates supported capabilities and omits at least one actual capability, creating a misleading trust boundary for users and agents. When a skill says it can safely manage or update resources that it does not actually support, operators may supply credentials and authorize actions under false assumptions, while undeclared behavior like listing people expands data exposure unexpectedly.
The documentation states that access tokens are cached locally and refreshed automatically, but it does not describe storage protections, file permissions, encryption, or cache location hardening. Because these tokens authorize API access, insecure local caching could allow other local users, malware, or over-privileged tools to steal and reuse them.
- Windows PowerShell: `$env:PLUTIO_APP_KEY = "..."`
4. **Python 3** must be installed
The skill caches access tokens locally (valid for ~1 hour), then automatically refreshes when needed.
## Quick Start
The authentication flow explicitly exchanges long-lived app credentials for access tokens and stores tokens locally for reuse, but the documentation does not define safeguards around those credentials or cached tokens. In the context of a project-management integration, stolen tokens or app secrets could expose project data, people lists, and permit unauthorized task operations.
## How It Works
1. **Authentication**: Exchanges app key + secret for temporary access token
2. **API Calls**: Uses token for authenticated requests to Plutio REST API
3. **Token Caching**: Stores token locally for faster subsequent calls
4. **Error Handling**: Reports API errors clearly with troubleshooting hints
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
**Base URL**: `https://api.plutio.com/v1.8/`
**Authentication**: OAuth 2.0 (app key + secret → access token)
**Rate Limit**: 1000 calls/hour
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
**Base URL**: `https://api.plutio.com/v1.8/`
**Authentication**: OAuth 2.0 (app key + secret → access token)
**Rate Limit**: 1000 calls/hour
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
**Base URL**: `https://api.plutio.com/v1.8/`
**Authentication**: OAuth 2.0 (app key + secret → access token)
**Rate Limit**: 1000 calls/hour
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
**Base URL**: `https://api.plutio.com/v1.8/`
**Authentication**: OAuth 2.0 (app key + secret → access token)
**Rate Limit**: 1000 calls/hour
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
**Base URL**: `https://api.plutio.com/v1.8/`
**Authentication**: OAuth 2.0 (app key + secret → access token)
**Rate Limit**: 1000 calls/hour
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
POST /tokens
Documenting a raw DELETE endpoint for tasks gives the skill a potentially destructive parameterizable action that can be triggered with only a task ID. Because the skill context is task management and the manifest does not declare deletion, this makes the endpoint especially risky: an agent could be induced to delete arbitrary tasks through prompt manipulation, confusion, or overbroad automation.
DELETE /tasks/{taskId}
Response (204 No Content)
The connection test passes the app key and secret directly as command-line arguments. Process arguments are commonly visible to local users via process-listing tools and may also be captured by shell history, monitoring tools, crash reports, or orchestration logs.
The alias usage continues the unsafe pattern of supplying secrets via command-line flags, reinforcing insecure operational practice. Because this is presented as a convenience workflow, users are more likely to repeat it frequently, increasing the chance of credential disclosure through process inspection and logs.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
### Token Cache Issues
Token is cached locally for ~1 hour. To force a refresh:
- Delete the token file and retry:
- **macOS/Linux**: `rm ~/.config/plutio/token.json`
- **Windows**: `Remove-Item $env:USERPROFILE\.config\plutio\token.json`
### "Rate Limited" (429 Error)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
self.token_expires_at = None
def get_token(self) -> str:
"""Get or refresh access token"""
# Try loading from cache first
if TOKEN_FILE.exists():
try:
The skill declares no explicit tool scope even though its documented behavior clearly implies shell execution, network access to the Plutio API, and local file writes for token caching. Missing scope boundaries increases the chance that an agent invokes the skill with broader-than-necessary capabilities, making misuse, credential leakage, or unintended local side effects more likely.
The setup instructions include a natural-language example that tells users to paste a client ID and secret directly into chat, without warning that chat transcripts, logs, or prompts may be retained. In an agent environment, this is a real credential-handling risk because it normalizes disclosing secrets through potentially persistent channels.
The documentation says task updates are restricted or unsupported, yet earlier sections present updating and closing tasks as supported operations. This inconsistency can cause an agent or user to attempt privileged state changes with credentials they would not otherwise provide, or to rely on behavior that fails in unpredictable ways, increasing the chance of unsafe workarounds.
The skill advertises full-field task creation, but the limitations section states only title, board ID, and group ID are actually supported. This mismatch can lead users to pass sensitive task metadata or assume fields were applied when they were silently ignored, causing confidentiality, integrity, and workflow issues.
The manifest says the skill supports creating, updating, closing, and querying tasks, but the reference additionally documents a hard delete endpoint. This undocumented destructive capability creates a scope mismatch that could let an agent perform irreversible actions users do not expect or approve.
A destructive DELETE operation is presented without warnings about irreversibility, confirmation requirements, or safer alternatives. In an agent context, omission of such guardrails increases the chance of accidental or automated data loss from normal language requests or prompt misunderstandings.
The skill is described as managing projects and tasks, but the reference also exposes People endpoints that enumerate workspace users and return names, emails, roles, and status. This expands the accessible data surface beyond the declared scope and could enable unnecessary collection of personal and organizational information if an agent uses the broader reference opportunistically.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
When a calendar event is created, automatically add a task to Plutio:
#!/bin/bash
The workflow bulk-closes tasks selected by a filter without any warning, dry-run, confirmation, or rollback guidance. In practice this can cause accidental mass state changes and operational disruption, especially if the project ID or jq filter is wrong.
The manifest describes managing Plutio projects and tasks, with examples centered on listing projects, viewing tasks, creating tasks, updating task details, and closing tasks. This example introduces a separate list-people capability to enumerate people records in Plutio, which is not mentioned in the stated skill scope and expands behavior beyond project/task management.
This example extends the skill from Plutio task management into external Matrix messaging, creating an outbound communication path not described in the skill's stated scope. Scope expansion matters because it can enable silent data exfiltration of task metadata to third-party systems and normalize chaining this skill with messaging actions outside user expectations.
No suspicious patterns detected.