Back to skill

Security audit

flight-scout

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Flight Scout API client, but it needs review because it can send a stored API key and travel details to any configured API URL without endpoint or HTTPS validation.

Review before installing. Use only a trusted HTTPS Flight Scout API base URL, avoid placing broad or production API keys in a shared skill .env, rotate the key if it was ever used with an untrusted or plaintext endpoint, and consider account quota/billing exposure from the usage and search commands.

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

Error
Location
scripts/call_api.py:41
Finding

API Credential Disclosure Through an Unrestricted or Unencrypted API Endpoint

Content
View full analysis
dict[str, str]: return { "Content-Type": "application/json", "X-API-Key": env_required("FLIGHT_SCOUT_API_KEY"), } ``` ```python def request_json(method: str, path: str, *, body: dict | None = None, query: dict | None = None, idempotency_key: str | None = None) -> dict: base_url = env_required("FLIGHT_SCOUT_API_BASE_URL").rstrip("/") timeout = int(os.getenv("FLIGHT_SCOUT_API_TIMEOUT_SECONDS", "30")) url = f"{base_url}{path}" if query: url = f"{url}?{urlencode(query)}" headers = build_base_headers() if idempotency_key: headers["Idempotency-Key"] = idempotency_key data = None if body is None else json.dumps(body, ensure_ascii=False).encode("utf-8") req = Request(url, data=data, headers=headers, method=method.upper()) ``` ### Technical Analysis The client obtains `FLIGHT_SCOUT_API_BASE_URL` directly from the environment and uses it to construct the destination passed to `urllib.request.urlopen`. No validation is performed on the URL scheme, hostname, port, user-information component, or redirect destination. At the same time, `build_base_headers()` unconditionally places the value of `FLIGHT_SCOUT_API_KEY` in the `X-API-Key` request header. Consequently, every supported API operation sends the credential to whichever endpoint is specified by `FLIGHT_SCOUT_API_BASE_URL`. Although sending an API key is necessary for the Skill's declared authenticated API functionality, allowing the key to be sent to an unrestricted destination is not required. In particular: - An `http://` URL can expose the API key and flight-query data through plaintext network traffic. - A malicious or incorrectly configured host can directly collect the API key. - Red ...[truncated 2413 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (13)

Tainted flow: 'timeout' from os.getenv (line 106, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/call_api.py (reported line 116)May include surrounding context.

python
data = None if body is None else json.dumps(body, ensure_ascii=False).encode("utf-8")
    req = Request(url, data=data, headers=headers, method=method.upper())
    try:
        with urlopen(req, timeout=timeout) as resp:
            raw = resp.read().decode("utf-8")
            parsed = parse_json_envelope(raw, status_code=getattr(resp, "status", 200), headers=resp.headers)
            if parsed is not None:

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 · README.md (reported line 26)May include surrounding context.

bash
cd skills/flight-scout
cp .env.example .env
# edit .env and fill a real FLIGHT_SCOUT_API_KEY
python3 scripts/call_api.py search --from SHA --to HND --date 2026-06-12
python3 scripts/call_api.py usage --period month

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 · README.md (reported line 27)May include surrounding context.

bash
cd skills/flight-scout
cp .env.example .env
# edit .env and fill a real FLIGHT_SCOUT_API_KEY
python3 scripts/call_api.py search --from SHA --to HND --date 2026-06-12
python3 scripts/call_api.py usage --period month

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description understates the actual behavior by omitting airport search, account usage queries, and quota/billing metadata handling. This mismatch can cause users to authorize the skill for simple flight lookups without realizing it can also query account-related information and expose operational or billing details from the remote service.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

Loading secrets from a repository-adjacent .env file is a credential-handling risk in agent environments because it allows the skill to consume local secrets without explicit user intent. Combined with user-controlled or environment-controlled base URLs, this can result in authenticated requests using host credentials, increasing the risk of secret misuse, SSRF-like access to internal services, or unauthorized billing against the account tied to the key.

Content

Scanner excerpt · scripts/call_api.py (reported line 13)May include surrounding context.

python
def load_local_env() -> None:
    env_path = Path(__file__).resolve().parents[1] / ".env"
    try:
        lines = env_path.read_text(encoding="utf-8").splitlines()
    except OSError:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares capabilities that include reading environment variables, reading local files, and making network requests, but it does not explicitly scope or disclose those permissions in the manifest. That weakens least-privilege guarantees and makes it harder for users or hosting platforms to evaluate what data the skill can access and transmit, especially because it loads secrets from a local .env and sends requests to a user-provided remote API endpoint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documentation instructs the agent to send API credentials and travel query details to a remote commercial API but does not clearly warn that this data leaves the local environment and is processed by an external service. Because the base URL is user-supplied, the risk is higher: credentials and itinerary data could be sent to an untrusted or mistyped endpoint, resulting in secret leakage or disclosure of potentially sensitive travel information.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill’s user-facing description and default prompt are entirely in Chinese, which indicates a language-specific interaction pattern without offering the user a language choice or documenting that the skill is region-specific. This can violate language/locale policy when users are not explicitly given an opt-in or alternative locale.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This markdown file contains natural-language instructions entirely in Chinese and example request bodies that set locale to zh-CN and zh-HK. Under the stated policy, forcing a specific language or locale without user opt-in is a natural-language policy concern unless a justified regional constraint is documented, which is not present here.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script reads API credentials and configuration from a local .env file and process environment, which conflicts with the stated model of user-supplied API base URL and API key. In an agent setting, this can cause unintended use of host-provided secrets or internal configuration, enabling silent credential reuse and requests to endpoints the user did not explicitly authorize.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Several subcommands set default locale values such as "zh-CN" and "zh-HK", which imposes a specific language/locale choice when the user does not explicitly provide one. This is a natural-language policy concern because the file does not offer opt-in language selection by default or document a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest describes the skill as supporting flight search, price calendar, synchronous hidden-city search, and asynchronous hidden-city task lookup after the user provides API base URL and API key. This file also implements an airport search command and a usage/account quota query command, which are additional user-facing API operations outside that stated scope.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

Line L35 switches to Chinese for a substantive usage/security note, while the rest of the README is in English. This can violate a language/locale policy when the skill does not offer the user a language option or explain that the content is intentionally region-specific.

Content

No source excerpt is available for this finding.