Back to skill

Security audit

私人旅游管家

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent travel-database helper, but it can save private travel content and send travel queries or records to external services without sufficiently clear user consent.

Review and limit where the travel database lives before installing. Treat screenshots, OCR text, preferences, trip dates, and saved places as private data that may be written to disk and optionally synced to Notion. Use dry-runs first, require explicit approval before --apply, external searches, image/OCR retention, or Notion export, and keep Notion/API tokens in a local secret store rather than chat or travel-db files.

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

T09 · Insecure Skill Coding Practices

Note
Location
scripts/notion_sync.py:324
Finding

Dry-Run Synchronization Persists Local State

Content
View full analysis
None: entry = {"timestamp": now_iso(), **entry} path = sync_dir / "_sync_log.jsonl" path.parent.mkdir(parents=True, exist_ok=True) with path.open("a", encoding="utf-8") as handle: handle.write(json.dumps(entry, ensure_ascii=False, sort_keys=True) + "\n") ``` The documented behavior in `references/notion-integration.md:32` is: ```markdown - Default sync commands to dry-run and require `--apply` for writes. ``` ### Technical Analysis The synchronization command represents execution without `--apply` as a dry run and explicitly states that the user must rerun it with `--apply` to write changes. However, `append_sync_log()` is called after both the apply and dry-run branches. It creates the parent directory when necessary and appends an entry to `notion-sync/_sync_log.jsonl`. Several earlier validation and credential-error paths also invoke the same logging function. Therefore, planning and failed validation operations can mutate the filesystem even though no write authorization was provided. This violates expected dry-run semantics and the documented requirement that writes require `--apply`. Although the written data is operational metadata rather than arbitrary attacker-selected file content, the discrepancy can affect automation that treats dry runs as side- ...[truncated 1299 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
scripts/SEARCH_README.md:63
Finding

Unpinned Third-Party Package Installation Instruction

Content
View full analysis
Remediation
View remediation
``` 2. Generate and enforce cryptographic hashes for the package and all transitive dependencies: ```bash python3 -m pip install --require-hashes -r requirements.txt ``` 3. Commit a lock file produced by an appropriate dependency-management tool and review lock-file changes as code changes. 4. Prefer installation inside an isolated virtual environment rather than the user's global Python environment. 5. Document the expected package index and warn users that custom or untrusted pip indexes can introduce dependency-confusion risks. 6. Add automated dependency scanning and scheduled review of pinned releases before updating the lock file. ]]>
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
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (46)

Tainted flow: 'request' from os.environ.get (line 435, 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/notion_common.py (reported line 447)May include surrounding context.

python
)
    for attempt in range(4):
        try:
            with urllib.request.urlopen(request, timeout=60) as response:
                raw = response.read().decode("utf-8")
                return json.loads(raw) if raw else {}
        except urllib.error.HTTPError as exc:

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Undeclared live web search combined with missing implementation of the advertised database, Notion, image, and planning features is a trust-boundary problem. Users may provide sensitive travel plans, screenshots, or preferences expecting local handling, while the skill's real behavior may transmit data externally or operate outside expected constraints.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Undeclared live web search combined with missing implementation of the advertised database, Notion, image, and planning features is a trust-boundary problem. Users may provide sensitive travel plans, screenshots, or preferences expecting local handling, while the skill's real behavior may transmit data externally or operate outside expected constraints.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Undeclared live web search combined with missing implementation of the advertised database, Notion, image, and planning features is a trust-boundary problem. Users may provide sensitive travel plans, screenshots, or preferences expecting local handling, while the skill's real behavior may transmit data externally or operate outside expected constraints.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Undeclared live web search combined with missing implementation of the advertised database, Notion, image, and planning features is a trust-boundary problem. Users may provide sensitive travel plans, screenshots, or preferences expecting local handling, while the skill's real behavior may transmit data externally or operate outside expected constraints.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Undeclared live web search combined with missing implementation of the advertised database, Notion, image, and planning features is a trust-boundary problem. Users may provide sensitive travel plans, screenshots, or preferences expecting local handling, while the skill's real behavior may transmit data externally or operate outside expected constraints.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/notion-integration.md (reported line 20)May include surrounding context.

md
## Notion Setup

1. Create a Notion integration or personal access token in the Notion developer portal.
2. Create or choose a parent page and enable the connection under that page's integration/connection menu.
3. Copy the parent page link or page ID into `NOTION_PARENT_PAGE_ID`.
4. Run `scripts/notion_setup.py --parent-page-id "$NOTION_PARENT_PAGE_ID"` first to preview the database and properties.

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 · scripts/notion_common.py (reported line 113)May include surrounding context.

python
def load_local_env() -> None:
    """Load simple KEY=VALUE lines from the project .env without overriding real env vars."""
    env_path = project_root() / ".env"
    if not env_path.exists():
        return
    for line in env_path.read_text(encoding="utf-8").splitlines():

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 · scripts/notion_common.py (reported line 129)May include surrounding context.

python
def load_local_env() -> None:
    """Load simple KEY=VALUE lines from the project .env without overriding real env vars."""
    env_path = project_root() / ".env"
    if not env_path.exists():
        return
    for line in env_path.read_text(encoding="utf-8").splitlines():

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · scripts/create_entry.py (reported line 141)May include surrounding context.

python
return 0

    if target_path.exists() and not target.get("detail_file"):
        print(f"Refusing to overwrite existing file: {target_path}")
        return 1

    target["record_weight"] = "detailed"

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · scripts/notion_promote.py (reported line 34)May include surrounding context.

python
return 0

    if target_path.exists() and not target.get("detail_file"):
        print(f"Refusing to overwrite existing file: {target_path}")
        return 1

    target["record_weight"] = "detailed"

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 · scripts/location_api.py (reported line 21)May include surrounding context.

python
# Travel Search Configuration
# Do not put real API keys in this file. Set them in your local shell or project
# .env instead; this file is a publishable feature toggle template.

# Environment variable names used by scripts
AMAP_API_KEY_ENV=AMAP_API_KEY

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 · scripts/notion_common.py (reported line 112)May include surrounding context.

python
# Travel Search Configuration
# Do not put real API keys in this file. Set them in your local shell or project
# .env instead; this file is a publishable feature toggle template.

# Environment variable names used by scripts
AMAP_API_KEY_ENV=AMAP_API_KEY

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 · scripts/notion_common.py (reported line 128)May include surrounding context.

python
# Travel Search Configuration
# Do not put real API keys in this file. Set them in your local shell or project
# .env instead; this file is a publishable feature toggle template.

# Environment variable names used by scripts
AMAP_API_KEY_ENV=AMAP_API_KEY

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 · scripts/search_config.ini (reported line 3)May include surrounding context.

text
# Travel Search Configuration
# Do not put real API keys in this file. Set them in your local shell or project
# .env instead; this file is a publishable feature toggle template.

# Environment variable names used by scripts
AMAP_API_KEY_ENV=AMAP_API_KEY

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
97% confidence
Finding

The skill requests or implies powerful capabilities including environment access, file read/write, network, and shell execution, but does not declare an explicit tool scope or permission boundary. That makes it harder for a host system or reviewer to enforce least privilege and increases the chance the skill can access credentials, modify local data, or perform network actions beyond what users expect.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The activation text is broad enough to trigger on ordinary travel conversation, increasing the chance the skill runs when the user did not intend to store data, modify files, or initiate sync-related actions. In a skill with file, shell, network, and possible credential access, over-broad activation materially raises the risk of unintended side effects.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
## Hermes Usage

When invoked from Hermes, do not ask the user to paste Notion tokens or credentials into chat. Read local Notion settings from the project root `.env` through the provided scripts.

If the user asks whether Notion is connected:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The workflow states that text and images/screenshots may be stored in local files, but the skill description does not clearly warn users about this persistence. That is dangerous because users may share sensitive travel details, screenshots, reservations, or personal preferences without realizing they will be written to disk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The workflow instructs the agent to store images and OCR-extracted text, which can easily capture sensitive personal data such as names, addresses, booking details, IDs, or contact information from screenshots. Because this is a personal travel knowledge base, users are especially likely to submit private travel confirmations and location evidence, so retaining raw images and OCR text without a privacy warning, minimization rule, or consent check creates a real privacy and data-retention risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The workflow encourages use of network, OCR, map, and search tools to enrich user-submitted travel data, but it does not warn that these actions may transmit user content, places of interest, trip details, or images to external services. In a travel assistant context, that can expose highly sensitive behavioral and location information, making the omission materially risky rather than merely theoretical.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The Notion sync instruction tells the operator to push or sync local records to an external platform without any warning that private travel notes, preferences, and source data may leave the local database. Given the skill explicitly manages personal travel history and planning, this creates a meaningful risk of unintended third-party disclosure and over-sharing.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/butler.py (reported line 21)May include surrounding context.

python
def run(command: list[str], check: bool = False) -> int:
    print("+ " + " ".join(str(part) for part in command), flush=True)
    result = subprocess.run(command)
    if check and result.returncode != 0:
        raise SystemExit(result.returncode)
    return result.returncode

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/ingest_text.py (reported line 63)May include surrounding context.

python
def run(command: list[str], check: bool = False) -> int:
    print("+ " + " ".join(str(part) for part in command), flush=True)
    result = subprocess.run(command)
    if check and result.returncode != 0:
        raise SystemExit(result.returncode)
    return result.returncode

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill performs external web searches and verification against third-party services even though its stated role centers on managing a local travel database and related organization/sync tasks. This expands the trust boundary: user prompts and travel interests may be transmitted externally without clear necessity, creating an undisclosed data-exposure channel and capability drift beyond the declared purpose.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.