Back to skill

Security audit

opentable-fpx

Security checks for vulnerabilities and agentic risk

Overview

The skill is openly about controlling OpenTable through a signed-in browser session, but it gives raw commands that can book, modify, or cancel reservations without an enforced confirmation step.

Review this carefully before installing. Use it only if you are comfortable letting fpx act through your signed-in OpenTable session, and do not run the write examples unless you have manually checked the exact reservation details and cancellation/payment policy. Prefer a pinned/local install, restrict browser-extension site access, revoke pairing when finished, and avoid storing or printing reservation tokens in shared shells or logs.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:99
Finding
Authenticated destructive operations lack an enforced confirmation gate<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:99-104`; `references/opentable-fpx-requests.md:11-16, 259-301, 335-361` **Vulnerability Type**: Missing confirmation and authorization safety control **Risk Level**: High ### Vulnerable Code From `SKILL.md:99-104`: ```markdown - **Booking, modifying, and cancelling are real actions with no confirm-gate here.** The MCP's `opentable_book`/`opentable_modify`/ `opentable_cancel` tools require `confirm: true` and a mandatory preview step; raw `fpx` calls have none of that — a `make-reservation` POST commits immediately. Fetch `/booking/details` and read the cancellation policy first (§5 of the reference) before calling it. ``` From `references/opentable-fpx-requests.md:259-301`: ```sh cat > /tmp/ot-book.json <<'JSON' { "restaurantId": 54232, "reservationDateTime": "2026-08-01T19:00", "partySize": 2, "slotHash": "<slot_hash>", "slotAvailabilityToken": "<reservation_token>", "slotLockId": 999999, "diningAreaId": 12345, "firstName": "Jane", "lastName": "Doe", "email": "jane@example.com", "phoneNumber": "5551234567", "phoneNumberCountryId": "US", "country": "US", "reservationAttribute": "default", "pointsType": "Standard", "points": 100, "tipAmount": 0, "tipPercent": 0, "confirmPoints": true, "optInEmailRestaurant": false, "additionalServiceFees": [], "nonBookableExperiences": [], "katakanaFirstName": "", "katakanaLastName": "", "correlationId": "<uuid>", "isModify": false, "reservationType": "Standard" } JSON fpx post-json 'https://www.opentable.com/dapi/booking/make-reservation' \ @/tmp/ot-book.json -p opentable \ | jq '{confirmationNumber, reservationId, securityToken, points, errorCode, partnerScaRequired}' ``` From `references/opentable-fpx-requests.md:335-361`: ```sh cat > /tmp/ot-cancel.json <<'JSON' { "operationName": "CancelReservation", "variables": { "input": { "restaurantId": 54232, "confirmationNumber" ...[truncated 2543 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Default the Skill to read-only behavior. 2. Implement a wrapper around every state-changing request rather than exposing raw mutation commands as the primary workflow. 3. Require a mandatory preview that displays: - Restaurant name and identifier. - Reservation date and time. - Party size and seating area. - Experience or deposit charges. - Credit-card requirements. - Cancellation policy and potential fees. - Existing reservation affected by a modification or cancellation. 4. Generate a short-lived confirmation token bound cryptographically or structurally to the exact previewed parameters. 5. Require a separate explicit user confirmation immediately before the mutation. 6. Reject a write if parameters differ from those previewed or if the confirmation token has expired. 7. Require independent confirmations for booking, modification, cancellation, and favorites mutations. 8. Preserve the MCP-style `confirm: true` control rather than relying solely on documentation. 9. Log only a redacted action summary and never include payment tokens or reservation security tokens. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/opentable-fpx-requests.md:141
Finding
Sensitive profile and reservation data is stored in predictable shared temporary files<![CDATA[ ## Vulnerability Details **File Location**: `references/opentable-fpx-requests.md:141-146, 170-180, 259-290, 338-351` **Vulnerability Type**: Unsafe temporary-file handling and plaintext sensitive-data exposure **Risk Level**: Medium ### Vulnerable Code From `references/opentable-fpx-requests.md:141-146`: ```sh fpx get 'https://www.opentable.com/user/dining-dashboard' -p opentable \ | node extract-initial-state.mjs > /tmp/ot-dash.json # Reservations — state.diningDashboard.{upcomingReservations,pastReservations}[] jq -r '.diningDashboard.upcomingReservations[] | "\(.confirmationNumber)\t\(.dateTime)\t\(.restaurantName)\tparty \(.partySize)\tsecurityToken=\(.securityToken)"' /tmp/ot-dash.json # Profile — state.header.userProfile jq '.header.userProfile | {name: "\(.firstName) \(.lastName)", email, mobile: .mobilePhoneNumber, points, metro: .metro.displayName}' /tmp/ot-dash.json ``` From `references/opentable-fpx-requests.md:170-180`: ```sh fpx get 'https://www.opentable.com/booking/details?rid=54232&datetime=2026-08-01T19:00&covers=2&partySize=2&seating=default&slotHash=<slot_hash>&slotAvailabilityToken=<reservation_token>' \ -p opentable | node extract-initial-state.mjs > /tmp/ot-details.json # CC-required? cancellation policy? saved card? dining areas? jq '{ ccRequired: .timeSlot.creditCardRequired, policy: .messages.cancellationPolicyMessage.cancellationMessage.message, defaultCard: (.wallet.savedCards[] | select(.default == true)), diningAreas: .timeSlot.diningAreasBySeating, conflicts: .upcomingReservationConflicts }' /tmp/ot-details.json ``` The documentation also creates predictable request files: ```sh cat > /tmp/ot-book.json <<'JSON' ``` ```sh cat > /tmp/ot-cancel.json <<'JSON' ``` ### Technical Analysis The examples use fixed names in the shared `/tmp` namespace for account state and authenticated request bodies. These files can contain: - Full names. - Email addresses and telephone numbers. - Reservation dates, ven ...[truncated 2224 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create a private temporary directory with a securely generated name: ```sh umask 077 tmpdir="$(mktemp -d)" trap 'rm -rf -- "$tmpdir"' EXIT HUP INT TERM ``` 2. Store all transient data only inside that directory. 3. Avoid predictable file names in the shared `/tmp` namespace. 4. Prefer in-memory pipelines where reuse of the response is unnecessary. 5. Ensure temporary files are created atomically and are not symbolic links. 6. Delete sensitive files immediately after use rather than waiting for normal process termination. 7. Redact or omit: - Reservation security tokens. - Slot availability tokens. - Slot lock identifiers. - Saved-card identifiers and expiration metadata. - Email addresses and phone numbers. 8. Do not print secrets to stdout unless the user explicitly requests them. 9. Add documentation warning against running these examples in shared shells, CI environments, or logging-enabled automation. 10. Consider a dedicated helper that extracts only the minimum fields required for each operation instead of retaining the full SSR account state. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:23
Finding
Unpinned global dependency is entrusted with a persistent authenticated browser bridge<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:23-34` **Vulnerability Type**: Unpinned third-party dependency with persistent session authority **Risk Level**: Medium ### Vulnerable Code ```markdown ## One-time setup ```sh npm install -g @fetchproxy/cli # provides `fpx` fpx profile add opentable --domain opentable.com fpx pair -p opentable # prints a pair code → approve in Transporter ``` Requirements: the **Transporter** browser extension installed, an open `www.opentable.com` tab **signed in**, and its Chrome **Site access** allowing `opentable.com`. Pairing persists — after the first approval every later `fpx` call reuses it. ``` ### Technical Analysis The setup installs `@fetchproxy/cli` globally without specifying an exact version, lockfile, or integrity hash. The resolved package can therefore change over time even though the audited Skill files remain unchanged. The installed executable is then paired with a browser extension that can issue requests through a signed-in OpenTable tab. Persistent pairing is functionally relevant to the declared Skill, but it significantly raises the trust placed in the unpinned package. A compromised registry release, maintainer account, transitive dependency, or unexpectedly changed future version could execute with the user's local privileges and use the authenticated browser bridge. No evidence was found that the current package is malicious. This finding concerns the unsafe dependency acquisition and trust model. ### Attack Path 1. The user runs `npm install -g @fetchproxy/cli` without an exact reviewed version. 2. npm installs the package version and dependency graph currently selected by the registry. 3. The user pairs the executable with the Transporter browser extension. 4. Pairing persists and is reused for later requests through the signed-in OpenTable tab. 5. If the package or a transitive dependency is compromised, its install-time or runtime code execute ...[truncated 826 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `@fetchproxy/cli` to an exact, reviewed version. 2. Record and verify package integrity and provenance before installation. 3. Use a project-local installation and lockfile instead of a global install. 4. Review the resolved transitive dependency graph and enable automated dependency vulnerability monitoring. 5. Avoid lifecycle scripts where feasible, or inspect them before installation. 6. Document how to revoke and remove the persistent pairing. 7. Prefer short-lived pairing or require reauthorization before sensitive mutation operations. 8. Keep browser extension site access restricted to the exact required OpenTable origins. 9. Separate read-only and write-capable profiles if supported. 10. Re-review the package before updating the pinned version. ]]>
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
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep

Static analysis

No suspicious patterns detected.