T09 · Insecure Skill Coding Practices
- Location
scripts/gusnais_plugin_client.py:166- Finding
Credential Exfiltration Through Attacker-Controlled OAuth and API Destinations
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a real Gusnais OAuth/API helper, but it handles reusable credentials and content-changing actions with enough scoping and disclosure gaps that users should review it before installing.
Install only if you trust the Gusnais account and OAuth client involved, are comfortable with a local plaintext token store, and will use the read/write actions deliberately. Prefer a private token-store path outside shared directories, rotate/revoke tokens if the file may have been exposed, and treat delete/publish/update actions as potentially irreversible or public.
scripts/gusnais_plugin_client.py:166Credential Exfiltration Through Attacker-Controlled OAuth and API Destinations
scripts/gusnais_bootstrap.py:89Bearer Tokens Are Disclosed in Request Query Strings
scripts/gusnais_bootstrap.py:141Non-Atomic Token-Store Writes Permit Symlink Attacks and Temporary Secret Exposure
scripts/gusnais_bootstrap.py:40Predictable OAuth State Is Not Validated During Authorization-Code Exchange
scripts/gusnais_plugin_client.py:104Destructive Actions Execute Before Documented Capability Checks
The description overstates the scope substantially. The code does support part of the claim about connecting with only CLIENT_ID and CLIENT_SECRET and auto-filling core OAuth/API endpoints, but its actual function is narrowly limited to OAuth bootstrap: generating an authorization URL, exchanging a code, optionally refreshing/persisting tokens, and calling /users/me to verify identity. There is no evidence of parity with gusnais.com capabilities, no permissions model handling, no UX logic, and no API read/write support for the named plugin domains. Therefore the declared description does not accurately represent the code chunk's actual behavior.
Referenced artifact was not completely inspected
Use `scripts/gusnais_plugin_client.py` for plugin API read/write calls with:
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).
- `GET /posts/:id`
- `POST /posts`
- `PUT /posts/:id`
- `DELETE /posts/:id`
- `PUT /posts/:id/publish`
- `POST /posts/preview`
- `GET /admin/posts`
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).
- `GET /api/v3/press/posts/:id`
- `POST /api/v3/press/posts`
- `PUT /api/v3/press/posts/:id`
- `DELETE /api/v3/press/posts/:id`
- `PUT /api/v3/press/posts/:id/publish`
- `POST /api/v3/press/posts/preview`
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).
- `GET /notes/:id`
- `POST /notes`
- `PUT /notes/:id`
- `DELETE /notes/:id`
- `POST /notes/preview`
- `GET /admin/notes`
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).
- `GET /api/v3/note/notes/:id`
- `POST /api/v3/note/notes`
- `PUT /api/v3/note/notes/:id`
- `DELETE /api/v3/note/notes/:id`
- `POST /api/v3/note/notes/preview`
### Site (`site-master`)
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).
- `GET /api/v3/site/sites/:id`
- `POST /api/v3/site/sites`
- `PUT /api/v3/site/sites/:id`
- `DELETE /api/v3/site/sites/:id`
- `GET /api/v3/site/site_nodes`
Notes:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Features:
- Load/save token store JSON (generated by gusnais_bootstrap.py)
- Auto-refresh access token before expiry or on 401
- One-shot action runner for plugin read/write endpoints
- Capability gating helper from `abilities`
- Action-specific payload guardrails (avoid obvious 400/500)
The skill advertises behavior that depends on network, file, environment, and shell-capable helper scripts, but it declares no explicit tool scope or permission boundaries. In practice this increases the blast radius of the skill because a caller cannot tell in advance that it may read secrets, persist tokens, or invoke local scripts, which is especially risky for an OAuth-integrating skill handling credentials.
The skill explicitly asks for CLIENT_ID and CLIENT_SECRET and recommends persisting refreshable tokens to a JSON file, but it does not warn about secret exposure, local filesystem risk, or secure storage requirements. For OAuth material, silent persistence can lead to credential theft, token replay, or accidental disclosure through logs, backups, or permissive file permissions.
The file documents OAuth authorization, token issuance, and token revocation endpoints, which are security-sensitive behaviors affecting authentication state. The markdown does not include any caution about handling tokens securely, protecting credentials, or the impact of revoking access.
This markdown file documents POST, PUT, and DELETE API operations such as creating, updating, and deleting topics, but it provides no warning that these actions modify or remove user data. Under the markdown-specific SQP-2 criteria, descriptions of behaviors that can affect user data or system integrity should disclose those risks.
The plugin API contract includes DELETE endpoints and publish/update operations for posts, notes, and sites, but the markdown does not warn that these actions can permanently remove content or make changes publicly visible. For markdown files, safety-relevant descriptions should disclose effects on user data and system state.
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.
API mapping used by this skill:
- List jobs: `GET /api/v3/topics?node_id=25&type=last_actived`
- Create job topic: `POST /api/v3/topics` with `node_id=25`
- Detail/update/delete: core topic endpoints (`/api/v3/topics/:id`)
The script persists highly sensitive OAuth material to disk, including the client_secret, access_token, and refresh_token, in a long-lived JSON file. Although it sets file mode 0600, storing reusable credentials on disk increases exposure through backup systems, accidental path selection, local compromise, container volume leakage, or later exfiltration by other processes.
The client refresh flow sends a refresh token, client ID, and client secret to the OAuth token endpoint, and the main request flow also transmits access tokens to remote API endpoints. Although the module docstring describes token refresh behavior, it does not warn users that credentials and bearer tokens will be sent over the network when the script runs.
No suspicious patterns detected.