Back to skill

Security audit

Duffel Flights

Security checks for vulnerabilities and agentic risk

Overview

This Duffel flight skill is mostly coherent, but it can make real bookings and cancellations while relying on weak shared temporary files and limited safety warnings.

Review before installing. Prefer a Duffel test token first, require explicit user confirmation before any booking or cancellation, avoid using numeric indexes from shared cached state for real purchases, and clear the /tmp Duffel cache files after use. Production use can spend real account funds and send traveler details to Duffel and travel providers.

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/duffel.py:58
Finding
Predictable Shared Temporary Files Allow Booking and Cancellation State Tampering## Vulnerability Details **File Location**: `scripts/duffel.py:18`, `scripts/duffel.py:58-74`, and `scripts/duffel.py:375-399` **Vulnerability Type**: Predictable and insecure temporary-file handling **Risk Level**: High The CLI stores security-sensitive offer and cancellation state in fixed, globally predictable files under `/tmp`. These files are created and read without secure creation, ownership validation, symlink protection, restrictive permissions, session isolation, or verification that the stored cancellation belongs to the order supplied by the user. **Vulnerable code:** ```python LAST_SEARCH_FILE = "/tmp/duffel-last-search.json" ``` ```python def save_search(offers_data): """Save search results for index-based reference.""" with open(LAST_SEARCH_FILE, "w") as f: json.dump(offers_data, f) def load_offer(id_or_index): """Load an offer by ID or 1-based index from last search.""" try: idx = int(id_or_index) with open(LAST_SEARCH_FILE) as f: data = json.load(f) offers = data if isinstance(data, list) else data.get("offers", []) if idx < 1 or idx > len(offers): print(f"Error: Index {idx} out of range (1-{len(offers)})") sys.exit(1) return offers[idx - 1] except (ValueError, FileNotFoundError): return {"id": id_or_index} ``` ```python if not args.confirm: # Get cancellation quote payload = {"data": {"order_id": args.order_id}} data = api_post("/air/order_cancellations", payload) cancel = data.get("data", {}) if args.json: print(json.dumps(cancel, indent=2)) return refund = cancel.get("refund_amount", "0") currency = cancel.get("refund_currency", "?") print(f"\n⚠️ Cancellation quote for order {args.order_id}") print(f" Refund: {currency} {refund}") print(f" Cancellation ID: {cancel.get('id', '?' ...[truncated 4118 chars]
Remediation
## Remediation Suggestions 1. Replace global `/tmp` paths with a private per-user state directory, such as an appropriate platform-specific cache directory, created with mode `0700`. 2. Create state files with mode `0600` and secure flags such as `O_CREAT`, `O_EXCL`, and `O_NOFOLLOW` where supported. 3. Validate with `lstat` or descriptor-based checks that each state object is a regular file owned by the current user and is not a symbolic link. 4. Write through a securely created temporary file in the private directory, flush it, and atomically rename it into place. 5. Namespace state by Duffel account, process, workflow, or a cryptographically random session identifier rather than using one global file. 6. Bind cached cancellation state to its order ID. Before confirmation, verify that the stored order ID exactly equals `args.order_id`; reject missing, stale, or mismatched state. 7. Prefer requiring the user to pass the cancellation ID explicitly or create and confirm a cancellation within one controlled invocation. 8. Avoid trusting cached price, currency, passenger, or offer metadata for a financial action. Re-fetch the selected offer by ID and verify its current price and passenger mapping before booking. 9. Add expiration timestamps and reject stale offer and cancellation state. 10. Remove sensitive temporary files after successful use and handle interruption cleanup safely.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (11)

Credential Access

High
Category
Privilege Escalation
Content
## Setup

Set `DUFFEL_TOKEN` env var with your Duffel API access token.
Get one at https://app.duffel.com → Developers → Access Tokens.
Test tokens (prefix `duffel_test_`) use sandbox data with unlimited balance.
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Setup

Set `DUFFEL_TOKEN` env var with your Duffel API access token.
Get one at https://app.duffel.com → Developers → Access Tokens.
Test tokens (prefix `duffel_test_`) use sandbox data with unlimited balance.

## Commands
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Setup

Set `DUFFEL_TOKEN` env var with your Duffel API access token.
Get one at https://app.duffel.com → Developers → Access Tokens.
Test tokens (prefix `duffel_test_`) use sandbox data with unlimited balance.

## Commands
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding
The skill advertises capabilities that involve network access, environment-variable access, and local file writes, but it does not declare any explicit tool scope or permission boundary. This creates an avoidable trust gap: an agent or reviewer cannot easily determine what operations are intended, which increases the chance of over-broad execution and unsafe use of credentials or filesystem access.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The booking flow requires users to provide highly sensitive passenger PII, including full name, date of birth, email, phone number, nationality, and gender, but the skill does not prominently warn that this data will be transmitted to an external airline-booking API. In an agent setting, absent disclosure and consent handling can lead to privacy violations, accidental over-collection, and inappropriate sharing of regulated personal data.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill supports real flight booking in production and notes that the account must be funded, but it does not clearly warn that using production mode can create real financial charges and reservations that may be non-refundable or costly to reverse. In an agent workflow, this omission increases the risk of unintended purchases and irreversible transactions.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This documentation gives direct instructions for booking and cancelling flights, which are real-world, irreversible or financially impactful actions, but it does not include any warning, confirmation guidance, or operator safeguards. In an agent skill context, this increases the risk that an automated system could execute purchases or cancellations without clear user awareness or explicit consent.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The booking flow collects and transmits highly sensitive passenger PII, including full name, date of birth, email, phone number, nationality, and gender, to an external API. While this is functionally required for flight booking, the script does so without an explicit privacy notice, confirmation step, or data-minimization guidance, which increases the risk of users disclosing sensitive data without clear awareness in an agent-driven context.

Missing User Warnings

Low
Confidence
89% confidence
Finding
The skill states that the last search is written to /tmp/duffel-last-search.json, but it does not clearly disclose that travel-search data will persist on local disk. Even if the data is not the most sensitive category, itineraries and travel patterns can still expose personal or business-sensitive information and may be readable by other local processes depending on environment configuration.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests
Confidence
98% confidence
Finding
The dependency file specifies `requests` without a version pin, which makes builds non-reproducible and can cause different environments to install different releases. In a flight-booking skill that may handle API credentials and booking data, this increases supply-chain and reliability risk because a vulnerable or breaking release could be pulled in unintentionally.

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
93% confidence
Finding
Because `requests` is unpinned, it is impossible to verify from this manifest whether the deployed version includes fixes for known advisories. In this skill's context, HTTP requests are central to interacting with the Duffel Flights API, so unresolved client-library vulnerabilities could affect confidentiality of credentials, request integrity, or transport security depending on the installed version.

Static analysis

No suspicious patterns detected.