Back to skill

Security audit

Flight Search

Security checks for vulnerabilities and agentic risk

Overview

This flight-search skill is mostly purpose-aligned, but users should review it because its credential handling and security documentation create real exposure risks.

Review before installing. Use only official Amadeus and AviationStack HTTPS endpoints, add your own .gitignore entry for config.json and .env before entering keys, prefer environment variables or a secret manager, and do not treat this skill as authorized to book flights. Keep price monitoring limited and user-directed so it does not consume API quota unexpectedly.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
lib/amadeus_client.py:17
Finding
Unrestricted API endpoint configuration can exfiltrate credentials<![CDATA[ ## Vulnerability Details **File Location**: `lib/amadeus_client.py:17-42`; the same design flaw also appears in `lib/aviationstack_client.py:17-20, 51-74, 199-210` **Vulnerability Type**: User-controlled credential transmission destination **Risk Level**: High ### Vulnerable Code ```python def __init__(self, api_key: str, api_secret: str, sandbox: bool = True, base_url_test: str = None, base_url_production: str = None): self.api_key = api_key self.api_secret = api_secret self.sandbox = sandbox # Use URLs from config or defaults test_url = base_url_test or "https://test.api.amadeus.com" prod_url = base_url_production or "https://api.amadeus.com" self.auth_url = f"{test_url if sandbox else prod_url}/v1/security/oauth2/token" self.api_url = test_url if sandbox else prod_url self.token = None self.token_expires_at = None def authenticate(self) -> bool: """Get OAuth2 token from Amadeus API""" url = self.auth_url data = { "grant_type": "client_credentials", "client_id": self.api_key, "client_secret": self.api_secret } try: response = requests.post(url, data=data, timeout=30) ``` The equivalent AviationStack behavior is: ```python def __init__(self, api_key: str, base_url: str = None): self.api_key = api_key # Default to HTTPS for security (API key sent in query params) self.base_url = base_url or "https://api.aviationstack.com/v1" self.request_count = 0 self.monthly_limit = 100 # Free tier limit ``` ```python url = f"{self.base_url}/flights" params = {"access_key": self.api_key} # Add optional parameters if flight_iata: params["flight_iata"] = flight_iata.upper() elif flight_icao: params["flight_icao"] = flight_icao.upper() if flight_number: params["flight_number"] = flight_number if date: params["flight_date"] = date if dep_iata: params["dep_iata"] = dep_iata.upper() if arr_iata: params["arr_i ...[truncated 2867 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Allowlist official API origins** - Accept only `https://test.api.amadeus.com` and `https://api.amadeus.com` for Amadeus. - Accept only `https://api.aviationstack.com` with the expected API path for AviationStack. - Compare parsed, normalized origins rather than using string-prefix checks. 2. **Enforce HTTPS** - Parse URLs with `urllib.parse.urlsplit`. - Reject every scheme other than `https`. - Reject embedded usernames or passwords, unexpected ports, malformed hosts, fragments, and protocol-relative URLs. 3. **Remove production endpoint overrides where unnecessary** - Hardcode trusted production origins. - If custom endpoints are needed for testing, require an explicit development-only option and display a prominent warning. - Prevent production credentials from being used with custom endpoints. 4. **Harden redirect behavior** - Disable redirects on credential-bearing authentication requests with `allow_redirects=False`, or validate every redirect destination against the same allowlist before following it. 5. **Protect AviationStack keys** - Use an authorization header if supported by the provider. - Ensure request URLs containing keys are never logged. - Document the unavoidable query-string exposure if the provider requires that authentication method. 6. **Respond to suspected exploitation** - Revoke and rotate affected credentials. - Review API usage and billing records. - Remove untrusted endpoint overrides from configuration. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:49
Finding
Documentation falsely claims plaintext credential configuration is ignored by Git<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:49-68`; related claims appear in `SECURITY.md:19-23, 63-68` and `QUICKSTART.md:163-168` **Vulnerability Type**: Unsafe credential-storage guidance and missing repository safeguard **Risk Level**: Medium ### Vulnerable Documentation ```markdown After installing, copy `config.example.json` to `config.json` and add your credentials: ```json { "apis": { "amadeus": { "api_key": "YOUR_AMADEUS_API_KEY", "api_secret": "YOUR_AMADEUS_API_SECRET", "sandbox_mode": true }, "aviationstack": { "enabled": false, "api_key": "YOUR_AVIATIONSTACK_API_KEY" } } } ``` **🔒 Security:** - `config.json` is in `.gitignore` by default - Never commit API keys to version control - Use environment variables or secure config files - Rotate keys if accidentally exposed ``` The audited project directory contains no `.gitignore` file, despite the statement that `config.json` is ignored by default. ### Technical Analysis The setup instructions direct users to place live API credentials in plaintext inside `config.json`. They then state that this file is already protected by a repository `.gitignore` rule, but the referenced `.gitignore` is absent from the audited package. A user following the documented process can therefore create an untracked credential file that Git does not automatically exclude. The warning not to commit credentials does not replace an actual ignore rule, especially because the documentation explicitly assures users that the safeguard already exists. Environment-variable use is mentioned as an alternative, but the executable clients shown in the audit load credentials directly from JSON configuration and do not implement the documented environment-variable approach in their command-line paths. ### Attack Path 1. A user copies `config.example.json` to `config.json` as instructed. 2. The user inserts valid Amadeus and optionally AviationStack credenti ...[truncated 1139 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Add the missing `.gitignore` file** Include at minimum: ```gitignore /config.json /.env /.monitored_flights.json __pycache__/ *.pyc ``` 2. **Prefer secure credential sources** - Add first-class support for `AMADEUS_API_KEY`, `AMADEUS_API_SECRET`, and `AVIATIONSTACK_API_KEY` environment variables. - Prefer a platform secret manager for deployed environments. - Avoid requiring persistent plaintext secrets in the project directory. 3. **Correct all documentation** - Do not claim that an ignore rule exists unless it is shipped and verified. - Clearly state that Git ignore rules do not protect files already tracked. - Provide commands such as `git check-ignore -v config.json` so users can verify protection. 4. **Harden local secret files** - Recommend restrictive permissions, such as `chmod 600 config.json`. - Validate permissions at startup and warn when the file is readable by other users. 5. **Add preventive repository controls** - Use pre-commit secret scanning. - Add CI checks that reject committed `config.json`, `.env`, or recognized credential patterns. - Consider providing a safe configuration generator rather than asking users to manually copy a plaintext template. 6. **Handle existing exposure** - Revoke and rotate any committed credentials immediately. - Remove secrets from Git history using an appropriate history-rewriting tool. - Review forks, mirrors, CI logs, and release artifacts for copies of the exposed file. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (27)

Credential Access

High
Category
Privilege Escalation
Content
## 🔐 Using Environment Variables

### **Create .env file:**

```bash
# .env (add to .gitignore!)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## 🔐 Using Environment Variables

### **Create .env file:**

```bash
# .env (add to .gitignore!)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description centers on flight search, price comparison, and airfare monitoring via the Amadeus API. The actual code is a client for the AviationStack Flight Status API, with functions to get a flight's status and to list flights by route/date. It returns operational flight information such as scheduled/estimated/actual times, gates, delays, aircraft, and live status. There is no fare data, no pricing comparison, no airfare monitoring logic, and no booking functionality. While there is some overlap with the 'flight status' trigger and limited route-based flight lookup, the primary purpose and external service are materially different from the declared description.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
There is a clear description-behavior mismatch. The declared purpose emphasizes flight search, price comparison, airfare monitoring, and Amadeus integration. The actual code only checks flight status, which is a narrower and materially different function. While 'flight status' appears among the triggers, the implementation does not support the core declared capabilities such as searching flights or comparing prices, and it relies on AviationStack rather than Amadeus. This is more than a supporting implementation detail because the external resource/API and primary function differ from the description.

Lp3

Medium
Category
MCP Least Privilege
Confidence
82% confidence
Finding
The skill declares required credentials and describes configuration plus external API use, but it does not declare any explicit tool scope or allowed-tools despite capabilities implying file read, file write, and network access. In an agent environment, missing scope declarations can lead to overbroad execution privileges and make it harder to enforce least-privilege boundaries or review what the skill is actually allowed to do.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
88% confidence
Finding
The trigger 'search flights' conflicts with a built-in 'search' command, creating command-shadowing risk. This can cause the skill to intercept user intent meant for a safer or more general built-in action, resulting in unintended network requests, quota usage, or routing of user data to external services.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
87% confidence
Finding
The trigger 'find flights' conflicts with a built-in 'find' command and may hijack generic user requests. In context, this is more dangerous because the skill is network-enabled and tied to third-party APIs, so accidental dispatch can expose travel-related queries externally or consume limited API quotas without clear user intent.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The trigger phrases are broad and overlap with ordinary travel conversation, increasing the chance the skill is invoked unintentionally. Because the skill expects credentials and network access, accidental activation could cause unnecessary external API calls, quota consumption, or unexpected disclosure of travel-related user queries to third-party services.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The documentation explicitly states that production mode can 'actually book' flights, which exceeds the manifest’s declared scope of searching, comparing, and monitoring airfare. This creates scope ambiguity that could lead users or downstream agents to treat the skill as authorized for transactional actions, increasing the risk of unintended purchases or privilege creep if booking-related code is later added or invoked.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The guidance to create bookings in order to obtain discounted search pricing encourages transactional behavior that is outside the stated skill purpose. Even if framed as cost optimization, it normalizes bookings as part of expected use and may push operators or agents toward executing real-world transactions without the skill being declared or reviewed for that capability.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The example phrases are broad natural-language commands such as monitoring and listing requests without explicit activation boundaries, confirmation steps, or parameter validation guidance. In an agent setting, ambiguous triggers can cause the skill to activate on loosely related user text and perform state-changing actions like adding routes to monitoring or exposing stored monitoring data when the user intent was unclear.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The multi-route and seasonal examples are especially ambiguous because they bundle multiple destinations, date ranges, passenger details, and conditional alerting into very open-ended phrasing. This increases the chance of misparsing, unintended background monitoring, excessive API usage, or monitoring the wrong travel parameters, which is more dangerous here because the skill can create persistent tasks and consume quota over time.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The file’s implemented behavior materially differs from the skill manifest: it performs flight-status and tracking lookups via AviationStack rather than flight search, price comparison, or airfare monitoring. This is dangerous because capability drift can mislead reviewers and users about what data is accessed, what external service is contacted, and what actions the skill actually performs, reducing transparency and trust boundaries.

External Transmission

Medium
Category
Data Exfiltration
Content
def __init__(self, api_key: str, base_url: str = None):
        self.api_key = api_key
        # Default to HTTPS for security (API key sent in query params)
        self.base_url = base_url or "https://api.aviationstack.com/v1"
        self.request_count = 0
        self.monthly_limit = 100  # Free tier limit
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
def __init__(self, api_key: str, base_url: str = None):
        self.api_key = api_key
        # Default to HTTPS for security (API key sent in query params)
        self.base_url = base_url or "https://api.aviationstack.com/v1"
        self.request_count = 0
        self.monthly_limit = 100  # Free tier limit
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
def __init__(self, api_key: str, base_url: str = None):
        self.api_key = api_key
        # Default to HTTPS for security (API key sent in query params)
        self.base_url = base_url or "https://api.aviationstack.com/v1"
        self.request_count = 0
        self.monthly_limit = 100  # Free tier limit
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
def __init__(self, api_key: str, base_url: str = None):
        self.api_key = api_key
        # Default to HTTPS for security (API key sent in query params)
        self.base_url = base_url or "https://api.aviationstack.com/v1"
        self.request_count = 0
        self.monthly_limit = 100  # Free tier limit
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
def __init__(self, api_key: str, base_url: str = None):
        self.api_key = api_key
        # Default to HTTPS for security (API key sent in query params)
        self.base_url = base_url or "https://api.aviationstack.com/v1"
        self.request_count = 0
        self.monthly_limit = 100  # Free tier limit
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The CLI documentation explicitly states the tool checks flight status, which contradicts the manifest’s airfare-search and price-comparison claims. Such contradictory documentation is a security-relevant integrity issue because it indicates the packaged skill may expose undeclared functionality and may send user inputs to an unexpected third-party API.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The markdown invites activation with the phrase "monitor this route," but it does not define the context, scope, or constraints for when that phrase should invoke the skill. Because the phrase is short and could plausibly appear in ordinary conversation about flights, it risks unintended invocation without clearer triggering rules or exclusions.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The phrase "Say \"track {{FLIGHT_NUMBER}}\"" is presented as an invocation trigger in a markdown file, but it does not define any scope, context, or exclusion conditions. Because "track" is common conversational language and no negative examples or activation boundaries are given, this could cause unintended skill invocation.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The template states that flight data comes from AviationStack, while the skill metadata says it uses the Amadeus API. This inconsistency can mislead users and operators about the true data source, which affects trust, incident response, privacy expectations, and compliance review if different providers have different terms, retention, or accuracy characteristics.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The document defines `"locale": "en-US"` as the default locale, and later repeats this default in the full example. Under the policy, forcing a specific locale without user opt-in can be a natural-language policy violation unless the constraint is documented and justified.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
The config sets a fixed default locale of "en-US", which can impose a language/locale choice without indicating user selection or a documented regional requirement. This matches the policy concern for language or locale constraints in natural-language/config values.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
This markdown file consists entirely of quoted example queries in English, presenting them as the way to use the skill. There is no indication that other languages are supported or that English is merely illustrative, which can violate a language/locale policy if users are expected to interact in a forced language without opt-in.

Static analysis

No suspicious patterns detected.