Back to skill

Security audit

Visa Itinerary Gen

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly aligned with visa itinerary generation, but it should be reviewed because it installs mutable third-party tooling and renders unvalidated travel data into active HTML/PDF outputs.

Install only if you are comfortable with flyai/Fliggy data being queried online, third-party npm and Python packages being installed, and generated HTML/PDF files being opened locally. Treat booking links as untrusted until you verify the destination, and avoid rendering Markdown or JSON supplied by someone else unless the renderer has been fixed to escape all fields and validate URLs.

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
scripts/render_booking.py:257
Finding

HTML and JavaScript Injection Through Unvalidated Booking URLs

Content
View full analysis
' f'{COPY_SVG}' f'{u}' f'' ) ``` ### Technical Analysis The renderer processes URL values from `data.json` using `html.escape()` and then inserts the result into two different security-sensitive contexts: 1. An inline JavaScript string inside the `onclick` attribute. 2. An HTML `href` attribute. HTML escaping alone is not sufficient for a JavaScript-string context. Character references such as `'` are decoded by the browser before the inline event handler is compiled as JavaScript. Consequently, an attacker-controlled apostrophe can terminate the string argument passed to `copyLink()` and inject additional JavaScript. The `href` value is also accepted without URL parsing or scheme validation. A value using a dangerous scheme such as `javascript:` can therefore be emitted as an active link. No Content Security Policy is generated to prevent inline script execution. Although the normal workflow expects URLs from FlyAI, the renderer accepts an arbitrary local JSON file through `--data`. Exploitation is possible if the JSON file is supplied by an untrusted party, modified before rendering, or populated from a compromised upstream response. ### Attack Path 1. An attacker controls or influences a URL field in `data.json`, including a flight, hotel, or attraction URL. 2. The attacker supplies a value that either: - breaks out of the JavaScript string in the inline `onclick` handler, or - uses a dangerous scheme such as `javascript:`. 3. The user runs `render_booking.py` against the malicious data. 4. The script writes the value into ...[truncated 920 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/render_pdf.py:106
Finding

Unescaped Markdown Title and Headers Are Rendered as Active HTML

Content
View full analysis
{h}" for h in headers) return f""" {CSS}

{title}

``` The table body uses manual escaping, but the title and header values do not receive equivalent protection. ### Technical Analysis `parse_md_table()` derives the document title and table headers directly from the supplied Markdown file. `build_html()` then places those values into an HTML document without escaping them. The generated document is opened by Playwright Chromium: ```python page.goto(f"file://{os.path.abspath(html_path)}") ``` As a result, HTML supplied through the Markdown title or header cells is interpreted by a real browser rather than displayed as text. Active elements, including scripts, event handlers, external resources, or crafted markup, can execute or load while Chromium renders the PDF. This issue is reachable through the public `--md` argument. It does not require modification of the Python source. ### Attack Path 1. An attacker supplies or modifies the Markdown input file. 2. The attacker places active HTML in the first heading or a table header. 3. A user invokes `render_pdf.py --md --output `. 4. The title or header is inserted into the temporary HTML without escaping. 5. Playwright opens the temporary file in Chromium. 6. The injected markup executes or loads external content during rendering. 7. The attacker can manipulate the generated PDF or cause browser-originated network activity. ### Impact Assessment The flaw permits attacker-controlled HTML and JavaScript to run inside the transient Chromium page. Potential consequences include: - Manipulation or falsification of the generated itinerary PDF. - Loading attac ...[truncated 515 chars]
Remediation
View remediation
{escape(h, quote=True)}" for h in headers) safe_title = escape(title, quote=True) ``` 2. Use `safe_title` in the generated heading rather than the raw title. 3. Replace manual cell escaping with `html.escape(cell, quote=True)` for consistent behavior. 4. Disable JavaScript for the rendering page if it is not required: ```python context = browser.new_context(java_script_enabled=False) page = context.new_page() ``` 5. Intercept requests and reject all non-local network traffic during PDF generation. 6. Validate Markdown structure, table dimensions, and maximum input size before invoking Chromium. 7. Add regression tests containing HTML tags, event handlers, quotation marks, and script elements in titles, headers, and cells. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:15
Finding

Mutable Third-Party Dependencies Are Installed Without Version or Integrity Pinning

Content
View full analysis
Remediation
View remediation
` - `playwright==` 2. Commit lockfiles or equivalent reproducible dependency metadata. 3. Verify package integrity using registry integrity hashes, signed provenance, or separately published checksums. 4. Pin and verify the Playwright Chromium revision rather than implicitly downloading a mutable artifact. 5. Avoid global npm installation where possible. Install dependencies into a project-local, isolated environment. 6. Install Python dependencies in a dedicated virtual environment with hash checking, such as `pip --require-hashes`. 7. Document the approved registries and reject unexpected registry overrides. 8. Introduce dependency scanning and a controlled update process in which new versions are reviewed before pins and hashes are changed. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code chunk is a presentation-layer renderer, not an itinerary generator. Its sole function is to load structured JSON input and output booking_links_cn.html and booking_links_en.html. While this partially aligns with the declared mention of booking links with Fliggy, it does not implement the core declared purpose of one-click natural-language visa itinerary generation, nor does it create a PDF. It also does not access fly.ai or any external source, so the claim about real-time/zero-hallucination data is not supported by this code. Therefore the description materially overstates and misrepresents what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code chunk is a document rendering utility, not an itinerary generation system. It takes an existing Markdown file, parses a table, builds HTML, and outputs a PDF. There is no natural-language understanding, no external data retrieval, no airline or Fliggy integration, and no booking-link generation. While PDF creation aligns with one small part of the description, the primary declared purpose is materially broader and different from the actual behavior.

Content

No source excerpt is available for this finding.

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · templates/booking_links_cn.html (reported line 229)May include surrounding context.

html
<div class="header-sub">fly.ai 实时搜索 · 2026年3月31日 · 所有链接指向飞猪</div>
</div>

<!-- Flights 航班 -->
<section>
  <div class="section-label">FLIGHTS</div>
  <h2>航班</h2>

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · templates/booking_links_cn.html (reported line 229)May include surrounding context.

html
<div class="header-sub">fly.ai 实时搜索 · 2026年3月31日 · 所有链接指向飞猪</div>
</div>

<!-- Flights 航班 -->
<section>
  <div class="section-label">FLIGHTS</div>
  <h2>航班</h2>

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · templates/booking_links_en.html (reported line 229)May include surrounding context.

html
<div class="header-sub">fly.ai real-time search &middot; March 31, 2026 &middot; All links point to Fliggy</div>
</div>

<!-- Flights 航班 -->
<section>
  <div class="section-label">FLIGHTS</div>
  <h2>Flights</h2>

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill performs file reads and writes (travel_plan.md, data.json, PDF/HTML outputs) but declares no explicit tool scope or permissions boundary. That creates an authorization gap where an agent runtime may grant broader filesystem access than users expect, increasing the chance of unintended file modification or data exposure.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The top-level documentation promises 'Real data from flyai, zero hallucination.' Later, the review instructions say that if a touring spot was not returned by flyai, it may be replaced with 'Local exploration / neighborhood walk', which is not traceable to FlyAI data and contradicts the absolute zero-hallucination claim.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill instructs the agent to install global Node and Python packages and then execute them, which expands the trust boundary from a simple itinerary generator to arbitrary third-party code execution. Installing packages at runtime exposes the environment to supply-chain risk and persistent system modification, especially because the commands are framed as mandatory operational steps.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill mandates shell command execution (which, python3 -c, flyai ...) as part of routine use, making command execution a built-in behavior rather than an exceptional admin action. In an agent context, normalizing shell execution increases the blast radius of prompt misuse, environmental tampering, and unsafe command composition if any user-controlled values later reach those commands.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The instructions require the generated travel plan to be 'full English' and further make 'ALL text in English' a hard rule. This forces a specific language output without offering the user any language choice or opt-in, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 233)May include surrounding context.

md
**Critical rules:**
- ALL text in English
- Every day must have specific touring spots — never write "Free day" or "Rest"
- Touring Spots: just list attraction names, no descriptions (e.g. "Duomo di Milano, Galleria V.E. II, The Last Supper")
- Accommodation: first time a hotel appears → full name + address; subsequent nights at same hotel → name only
- Transportation: flight rows → "Flight {airline} {flight_no}: {route} {time}"; train rows → "Train {city_a}→{city_b}"; sightseeing days → "Public transport and walking"

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

Earlier dependency-check steps instruct the agent to ask permission to install missing flyai-cli and proceed once dependencies are present. The error-handling table later states 'flyai not installed | Print installation instructions and stop', which contradicts the documented setup flow rather than merely omitting detail.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The module docstring and usage instructions are written only in Chinese, and the CLI description/help strings are also Chinese-only. This creates a locale policy concern because the skill presents a fixed language experience without any documented user opt-in or language-selection mechanism.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code file contains natural-language strings exclusively in Chinese, including the module docstring, comments, CLI description, help text, and an error message. Under the policy rule, forcing a specific language without user opt-in is a locale/language policy issue because the script does not offer an alternative language or document that it is intentionally region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The HTML declares lang="zh-CN", and the visible content throughout the page is presented in Simplified Chinese. Under the policy, forcing a specific language without user opt-in can be a natural-language locale violation unless the regional limitation is explicitly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file is explicitly marked as English-only with lang="en" and an '(EN)' title, but there is no visible opt-in or explanation that this template is intentionally language-specific. Under the stated policy, forcing a specific language without user choice can be a natural-language locale policy issue.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This HTML file loads a Google Fonts stylesheet from an external domain, which causes the user's browser to make a network request to a third party. The page also promotes outbound booking links, but it does not explicitly warn users that opening the page or clicking links will contact external services and may expose browsing metadata.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.