T09 · Insecure Skill Coding Practices
- Location
scripts/fetch_models.py:27- Finding
Unnecessary Automatic Transmission of an API Credential
- Content
View full analysis
Vulnerability Details
File Location:
scripts/fetch_models.py, lines 27–33 and 53–62
Vulnerability Type: Automatic credential use without explicit per-run consent
Risk Level: LowVulnerable Code
python def fetch(api_key: str | None) -> dict: headers = {} if api_key: headers["Authorization"] = f"Bearer {api_key}" req = urllib.request.Request(API_URL, headers=headers) try: with urllib.request.urlopen(req, timeout=30) as resp: body = resp.read().decode("utf-8")python parser.add_argument( "--api-key", default=os.environ.get("OPENROUTER_API_KEY"), help="Optional. OpenRouter API key, or set OPENROUTER_API_KEY. " "Endpoint is public; key only affects rate limits / attribution.", ) parser.add_argument("--out", type=Path, default=DEFAULT_OUT) args = parser.parse_args() data = fetch(args.api_key)Technical Analysis
The OpenRouter model-catalog endpoint is documented by the Skill as public and does not require authentication. Nevertheless, the default argument value is automatically populated from
OPENROUTER_API_KEY. If that environment variable exists, an ordinary invocation ofpython3 scripts/fetch_models.pysilently adds the credential to anAuthorization: Bearerheader and sends it to the configured OpenRouter endpoint.This behavior exceeds the minimum privilege needed for the declared catalog-retrieval function. Although the credential is sent over HTTPS to the declared OpenRouter domain rather than an unrelated host, authentication should require explicit opt-in when the operation works anonymously. The alternative
--api-key KEYinterface also places a secret in command-line arguments, where it may be retained in shell history or exposed through process inspection.Attack Path
- A user has a valid OpenRouter credential stored in
OPENROUTER_API_KEY. - The user or agent follows t ...[truncated 1280 chars]
- A user has a valid OpenRouter credential stored in
- Remediation
View remediation
Remediation Suggestions
- Change the default value of
--api-keytoNoneso public retrieval is anonymous by default. - Require an explicit option such as
--authenticatedor--use-env-api-keybefore readingOPENROUTER_API_KEY. - Avoid accepting secrets directly as command-line values. If authenticated requests are necessary, read the credential from the environment or a permission-restricted file only after explicit user consent.
- Clearly report when authenticated mode is active without printing the credential.
- Update
SKILL.mdto explain that authentication is unnecessary for normal operation and document the exact circumstances in which a credential will be transmitted. - Consider separating anonymous and authenticated retrieval paths so the normal quick-start flow cannot access credentials.
A safer interface would resemble:
python parser.add_argument( "--use-env-api-key", action="store_true", help="Explicitly authenticate using OPENROUTER_API_KEY.", ) args = parser.parse_args() api_key = os.environ.get("OPENROUTER_API_KEY") if args.use_env_api_key else None if args.use_env_api_key and not api_key: parser.error("OPENROUTER_API_KEY is not set") data = fetch(api_key)- Change the default value of
