T09 · Insecure Skill Coding Practices
- Location
scripts/simplefin_api.js:24- Finding
Arbitrary Command Execution Through an Unsafely Constructed Shell Command
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill has a coherent banking-data purpose, but it handles live financial access credentials unsafely and can turn user-provided SimpleFIN URLs or tokens into shell commands.
Review before installing. This skill can read sensitive financial balances and transactions, and its current helper script should be fixed before use: replace shell-based curl calls with a native HTTP client, validate SimpleFIN URLs, avoid plaintext workspace storage, and never print or pass the full Access URL through logs or command-line arguments.
scripts/simplefin_api.js:24Arbitrary Command Execution Through an Unsafely Constructed Shell Command
scripts/simplefin_api.js:24Server-Side Request Forgery Through Unrestricted Claim and Access URLs
SKILL.md:30SimpleFIN Access Credentials Exposed Through Output, Process Arguments, and Plaintext Storage
Referenced artifact was not completely inspected
node scripts/simplefin_api.js claim "THE_SETUP_TOKEN_HERE"
Referenced artifact was not completely inspected
node scripts/simplefin_api.js claim "THE_SETUP_TOKEN_HERE"
Referenced artifact was not completely inspected
node scripts/simplefin_api.js claim "THE_SETUP_TOKEN_HERE"
Referenced artifact was not completely inspected
node scripts/simplefin_api.js claim "THE_SETUP_TOKEN_HERE"
Referenced artifact was not completely inspected
node scripts/simplefin_api.js claim "THE_SETUP_TOKEN_HERE"
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- A user gets a Setup Token from this server.
- The user gives the Setup Token to your application.
- Your application sends the Setup Token to this server and receives an Access Token in return.
- Your application uses the Access Token to get the user's transaction data from this server.
- At any point, the user can disable the Access Token.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- A user gets a Setup Token from this server.
- The user gives the Setup Token to your application.
- Your application sends the Setup Token to this server and receives an Access Token in return.
- Your application uses the Access Token to get the user's transaction data from this server.
- At any point, the user can disable the Access Token.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- A user gets a Setup Token from this server.
- The user gives the Setup Token to your application.
- Your application sends the Setup Token to this server and receives an Access Token in return.
- Your application uses the Access Token to get the user's transaction data from this server.
- At any point, the user can disable the Access Token.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- A user gets a Setup Token from this server.
- The user gives the Setup Token to your application.
- Your application sends the Setup Token to this server and receives an Access Token in return.
- Your application uses the Access Token to get the user's transaction data from this server.
- At any point, the user can disable the Access Token.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
You can only do the above step once. Once you receive an ACCESS_URL, save it—the corresponding SETUP_TOKEN will no longer work.
Make an HTTP GET request to {ACCESS_URL}/accounts with Basic Auth credentials.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
## Limits
The SimpleFIN Bridge is intended to provide daily updates to transaction data. As such, you are expected to make 24 requests or fewer per day. There is a little leeway above this limit, which is helpful when doing initial setup. Quotas are replenished throughout the day.
Requests for all accounts `GET /accounts` have a quota. Requests for individual accounts have their own quota `GET /accounts?account=...`.
Making more requests than expected will eventually cause warning messages to appear in the "errors" array. Exceeding the expected rate limits beyond the warning level will result in Access Tokens being disabled.
The date range of requests to `/accounts` (i.e. difference between start-date and end-date) is limited to 90 days at a time. The number of days of history available varies for each institution.
The skill invokes shell commands (node scripts/simplefin_api.js ...) but does not declare any explicit tool scope or allowed-tools boundary. That omission weakens least-privilege controls and makes it easier for an agent/runtime to execute broader shell actions than the skill's banking purpose requires.
The skill tells the agent to search workspace files and environment/config sources for a stored SimpleFIN access URL, which is a credential. Even if related to the skill's function, this introduces secret-discovery behavior and increases the chance of accessing credentials from unintended locations or exposing them during processing.
The skill normalizes persistent reuse of a credential-bearing access URL without labeling it as sensitive or warning about handling risks. In the context of bank-account access, this is especially dangerous because compromise of the URL can directly expose balances and transaction history, and possibly require full token reissuance to recover.
The skill instructs saving a full SimpleFIN Access URL containing embedded username/password credentials into a workspace file for later reuse. Storing live banking credentials in plaintext within shared workspace storage creates a high risk of credential leakage, lateral access by other skills/processes, and unauthorized financial data retrieval.
The claim flow builds a shell command by interpolating a URL derived from an attacker-controlled setup token and executes it with execSync. Even though the URL is wrapped in double quotes, shell metacharacters such as command substitution can still be evaluated, enabling command injection and arbitrary code execution on the host running the skill.
The API fetch path constructs a shell command containing a user-supplied access URL and then executes it via execSync. This creates command-injection risk from crafted URLs and also grants the skill unnecessary subprocess capability in a banking context, increasing the blast radius to arbitrary command execution and possible exposure of financial credentials.
Detected: suspicious.dangerous_exec