Back to skill

Security audit

API Credit Health Bar Lite

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a disclosed API balance tracker, but its OpenAI auto-check asks for an organization-admin API key, which is broader access than users may expect.

Install only if you are comfortable with local balance tracking and provider API calls. Prefer manual sync or narrowly scoped billing/read-only keys where available, avoid exposing an OpenAI organization-admin key, and use a pinned/isolated Python environment before enabling auto-checks.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T08 · Insecure Dependencies

Warning
Location
README.md:60
Finding

Unpinned Third-Party Runtime Dependencies

Content
View full analysis
Remediation
View remediation
requests== ``` 2. Generate and verify cryptographic hashes, using a workflow such as: ```bash pip-compile --generate-hashes requirements.in pip install --require-hashes -r requirements.txt ``` 3. Pin transitive dependencies through a lockfile rather than pinning only direct dependencies. 4. Use an explicitly trusted package index and disable unexpected fallback indexes where practical: ```bash python3 -m pip install \ --index-url https://pypi.org/simple \ --require-hashes \ -r requirements.txt ``` 5. Run dependency vulnerability and provenance checks during releases. 6. Test and review dependency upgrades before updating the lockfile. 7. Execute automatic checks in a restricted environment containing only the single credential required for that provider. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/check_openai.py:1
Finding

OpenAI Balance Checker Requests an Organization-Administrator Credential

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (13)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · .gitignore (reported line 29)May include surrounding context.

text
*.egg

# Virtual environments
.env
.venv
env/
venv/

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The README advertises automated API balance pulls but does not warn users that enabling this feature involves using provider credentials and making outbound network requests. That omission can mislead users about the sensitivity of the operation and increases the risk of unintentionally granting a skill access to billing-related APIs.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README tells users they can invoke the skill with broad, everyday phrases such as asking how much credit is left or whether anything is running low. In agent environments, vague natural-language triggers can cause accidental activation during unrelated conversation, which is more concerning here because the skill handles account balance data and may initiate balance updates or checks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README lists environment variables for provider API keys without accompanying guidance on secure handling, least-privilege use, storage, rotation, or exposure risks. In agent skill ecosystems, this can normalize casually supplying sensitive credentials to a skill without understanding how they will be used or protected.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SECURITY.md (reported line 122)May include surrounding context.

bash
# Read/write for owner only
chmod 600 config.json

# View permissions
ls -l config.json

Session Persistence

Medium
Category
Rogue Agent
Confidence
82% confidence
Finding

The skill explicitly persists account balance information by reading and writing config.json, creating a session-persistence/privacy risk if financial usage data remains on disk longer than the user expects. While the stored data appears limited to provider balances rather than secrets, local persistence can expose spending patterns or account state to other local users, backups, or later processes.

Content

Scanner excerpt · SKILL.md (reported line 10)May include surrounding context.

md
- VERCEL_AI_GATEWAY_KEY
permissions:
  - network: Contact OpenAI, OpenRouter, and Vercel APIs to check balances (optional)
  - filesystem: Read/write config.json and health bar display
---

# API Credits Lite

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring describes the script as a balance checker and its primary usage examples emphasize checking credits balance. However, the implementation later supports an --update mode that writes provider data back to ../config.json, which is a state-changing side effect not reflected in the stated behavior.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · check_vercel.py (reported line 1)May include surrounding context.

python
#!/usr/bin/env python3\n\"\"\"\nCheck Vercel AI Gateway balance via API.\n\nRequires: VERCEL_AI_GATEWAY_KEY environment variable\n\nUsage:\n    VERCEL_AI_GATEWAY_KEY=... python3 check_vercel.py\n    VERCEL_AI_GATEWAY_KEY=... python3 check_vercel.py --update\n\"\"\"\n\nimport os\nimport json\nimport sys\nfrom datetime import datetime\n\ntry:\n    import requests\nexcept ImportError:\n    print(\"❌ requests library not installed. Install with: pip install requests\")\n    sys.exit(1)\n\ndef load_config():\n    \"\"\"Load config from the skill directory\"\"\"\n    script_dir = os.path.dirname(os.path.abspath(__file__))\n    config_path = os.path.join(script_dir, '..', 'config.json')\n    \n    try:\n        with open(config_path, 'r') as f:\n            return json.load(f)\n    except FileNotFoundError:\n        return {'providers': {}, 'thresholds': {'warning': 50, 'critical': 25}}\n\ndef save_config(config):\n    \"\"\"Save config back to file\"\"\"\n    script_dir = os.path.dirname(os.path.abspath(__file__))\n    config_path = os.path.join(script_dir, '..', 'config.json')\n    \n    with open(config_path, 'w') as f:\n        json.dump(config, f, indent=2)\n\ndef check_vercel_balance(api_key):\n    \"\"\"\n    Check Vercel AI Gateway balance using API.\n    \n    Returns: (balance, limit, timestamp)\n    \"\"\"\n    try:\n        response = requests.get(\n            'https://api.vercel.com/v1/billing',\n            headers={\n                'Authorization': f'Bearer {api_key}',\n                'Content-Type': 'application/json'\n            }\n        )\n        \n        if response.status_code != 200:\n            print(f\"❌ API error: {response.status_code}\")\n            if response.status_code == 401:\n                print(\"   Invalid API key\")\n            return None, None, None\n        \n        data = response.json()\n        \n        # Vercel returns balance and usage info\n        balance = float(data.get('balance', 0))\n        limit = float(data
...[truncated 26 chars]

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/check_vercel.py (reported line 1)May include surrounding context.

python
#!/usr/bin/env python3\n\"\"\"\nCheck Vercel AI Gateway balance via API.\n\nRequires: VERCEL_AI_GATEWAY_KEY environment variable\n\nUsage:\n    VERCEL_AI_GATEWAY_KEY=... python3 check_vercel.py\n    VERCEL_AI_GATEWAY_KEY=... python3 check_vercel.py --update\n\"\"\"\n\nimport os\nimport json\nimport sys\nfrom datetime import datetime\n\ntry:\n    import requests\nexcept ImportError:\n    print(\"❌ requests library not installed. Install with: pip install requests\")\n    sys.exit(1)\n\ndef load_config():\n    \"\"\"Load config from the skill directory\"\"\"\n    script_dir = os.path.dirname(os.path.abspath(__file__))\n    config_path = os.path.join(script_dir, '..', 'config.json')\n    \n    try:\n        with open(config_path, 'r') as f:\n            return json.load(f)\n    except FileNotFoundError:\n        return {'providers': {}, 'thresholds': {'warning': 50, 'critical': 25}}\n\ndef save_config(config):\n    \"\"\"Save config back to file\"\"\"\n    script_dir = os.path.dirname(os.path.abspath(__file__))\n    config_path = os.path.join(script_dir, '..', 'config.json')\n    \n    with open(config_path, 'w') as f:\n        json.dump(config, f, indent=2)\n\ndef check_vercel_balance(api_key):\n    \"\"\"\n    Check Vercel AI Gateway balance using API.\n    \n    Returns: (balance, limit, timestamp)\n    \"\"\"\n    try:\n        response = requests.get(\n            'https://api.vercel.com/v1/billing',\n            headers={\n                'Authorization': f'Bearer {api_key}',\n                'Content-Type': 'application/json'\n            }\n        )\n        \n        if response.status_code != 200:\n            print(f\"❌ API error: {response.status_code}\")\n            if response.status_code == 401:\n                print(\"   Invalid API key\")\n            return None, None, None\n        \n        data = response.json()\n        \n        # Vercel returns balance and usage info\n        balance = float(data.get('balance', 0))\n        limit = float(data
...[truncated 26 chars]

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The top-level docstring says 'Check Vercel AI Gateway balance via API' and its usage examples frame the script as a checker. However, the implementation supports an '--update' mode that writes provider state back into ../config.json, which is a meaningful side effect not reflected in the stated intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown file documents network calls to provider APIs and read/write access to config.json, but it does not include a user-facing warning about privacy or local data modification effects. Because the skill can contact external services and persist balance information, the description should more explicitly disclose those behaviors before use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This Python file performs a file write to config.json in save_config(), and the user-facing usage text only mentions the --update flag without clearly warning that it will modify the local configuration file. Although the function names and comments imply updating config, there is no explicit disclosure at invocation time beyond a generic 'Config updated' message after the write occurs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code overwrites a persistent config file via save_config(), but the script provides no user-facing notice at the time of the write beyond returning JSON output afterward. While the module docstring implies balance updates, there is no explicit warning in comments, help text, or runtime output that running the command will modify ../config.json.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.