Back to skill

Security audit

OpenRouter Usage

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed OpenRouter usage-reporting skill, with the main caution that its optional local credentials file can expose API keys if handled carelessly.

Install only if you are comfortable giving the skill OpenRouter account keys for usage reporting. Use environment variables or a managed secret mechanism where possible; if you use credentials.env, keep it out of source control and shared archives, restrict its permissions, and rotate keys if exposure is suspected.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/stats.py:27
Finding

Plaintext API Credential File Lacks Access-Control and Repository Protections

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (12)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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


How to run (recommended)

Set environment variables (recommended) or create a credentials.env file:

bash
export OPENROUTER_API_KEY=your_key_here

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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


How to run (recommended)

Set environment variables (recommended) or create a credentials.env file:

bash
export OPENROUTER_API_KEY=your_key_here

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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


How to run (recommended)

Set environment variables (recommended) or create a credentials.env file:

bash
export OPENROUTER_API_KEY=your_key_here

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/stats.py (reported line 109)May include surrounding context.

python
---
## How to run (recommended)
Set environment variables (recommended) or create a `credentials.env` file:

```bash
export OPENROUTER_API_KEY=your_key_here

Lp1

High
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The script makes outbound network requests to OpenRouter APIs, but network capability is reportedly not covered by declared permissions. Undeclared network access is a real security concern because any code with HTTP capability can exfiltrate data or access external systems outside reviewer expectations.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The script makes outbound network requests to OpenRouter APIs, but network capability is reportedly not covered by declared permissions. Undeclared network access is a real security concern because any code with HTTP capability can exfiltrate data or access external systems outside reviewer expectations.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The documentation advertises loading credentials from a local credentials.env fallback, signaling that the skill is designed to read secrets from a file within the skill directory. File-based secret loading increases exposure because credentials can be accidentally committed, copied, or read by other components with filesystem access.

Content

Scanner excerpt · scripts/stats.py (reported line 11)May include surrounding context.

python
Credentials are loaded from:
  1. Environment variables (recommended for security)
  2. credentials.env file (fallback)

Required:
  OPENROUTER_API_KEY - for real-time totals and balance

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

The code constructs a path to credentials.env in the skill directory, explicitly enabling local secret-file access. In an agent-skill context, embedding secret lookup in the package directory is risky because it normalizes storing long-lived API keys alongside executable code and increases accidental disclosure risk.

Content

Scanner excerpt · scripts/stats.py (reported line 27)May include surrounding context.

python
# Credentials file in skill directory (same level as scripts/)
SCRIPT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
CRED_FILE = os.path.join(SCRIPT_DIR, "credentials.env")

def load_creds():
    """Load credentials from environment variables first, then fallback to credentials.env file."""

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The function directly reads OPENROUTER_API_KEY and OPENROUTER_MGMT_KEY from process environment state. Accessing secrets is expected for this skill's purpose, but it remains a sensitive capability that can become dangerous if permissions are overbroad or if the skill later gains unintended output or exfiltration paths.

Content

Scanner excerpt · scripts/stats.py (reported line 30)May include surrounding context.

python
CRED_FILE = os.path.join(SCRIPT_DIR, "credentials.env")

def load_creds():
    """Load credentials from environment variables first, then fallback to credentials.env file."""
    creds = {
        "OPENROUTER_API_KEY": os.environ.get("OPENROUTER_API_KEY", ""),
        "OPENROUTER_MGMT_KEY": os.environ.get("OPENROUTER_MGMT_KEY", "")

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The fallback branch opens and parses credentials.env, meaning the running code will consume secrets from local disk if present. This materially increases the chance of secret leakage through source control mistakes, backups, artifact packaging, or broader filesystem access than intended.

Content

Scanner excerpt · scripts/stats.py (reported line 36)May include surrounding context.

python
"OPENROUTER_MGMT_KEY": os.environ.get("OPENROUTER_MGMT_KEY", "")
    }

    # If not in environment, try credentials.env file
    if not creds["OPENROUTER_API_KEY"] or not creds["OPENROUTER_MGMT_KEY"]:
        if os.path.exists(CRED_FILE):
            with open(CRED_FILE) as f:

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The docstring states OPENROUTER_API_KEY is required for both real-time totals and balance, implying balance is a defined guaranteed function. However, the implementation wraps balance retrieval in a broad exception handler and proceeds with a zero balance when the credits endpoint is inaccessible, which contradicts that stated behavior.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The manifest describes fetching real-time usage totals and historical per-model spend, but this code also calls a separate credits endpoint and computes account balance from total credits minus usage. Balance/account credits are adjacent to spend reporting, but they are not explicitly claimed in the manifest description.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.