Back to skill

Security audit

pricewin-hotel-deal-finder

Security checks for vulnerabilities and agentic risk

Overview

This hotel-price skill appears purpose-built, but it runs a powerful local browser daemon with several safety gaps users should review before installing.

Review this before installing if you run agents as root, in shared environments, or with broad filesystem access. Prefer running it as an unprivileged user, verify booking-link destinations before clicking, avoid custom `OPENTRAVEL_API_BASE_URL` values unless trusted, and be prepared to manually stop the PriceWin daemon if a search fails.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
bin/daemon.js:164
Finding

Chromium Sandbox Is Automatically Disabled When Running as Root

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
bin/search.js:103
Finding

Untrusted Booking Links Are Not Restricted to Approved OTA Domains

Content
View full analysis
Remediation
View remediation

T06 · System Persistence

Warning
Location
bin/search.js:346
Finding

Fatal Search Errors Can Leave the Detached Browser Daemon Running

Content
View full analysis
setTimeout(r, 500)); } bail('Daemon failed to come up within 30s — check stderr or ~/.cache/pricewin-hotel-deal-finder/'); } ``` Cleanup occurs only at the successful end of `main()`: ```js console.log(lines.join('\n')); // ── Cleanup ──────────────────────────────────────────────────────────────── await run(['close'], 5000).catch(() => {}); } ``` Fatal errors exit without invoking cleanup: ```js main().catch(e => { console.error('[search] fatal:', e.message); process.exit(1); }); ``` An early daemon-validation failure also exits directly: ```js const launchRaw = await run(['launch'], 30000); const launchR = parse(launchRaw); if (!launchR || (launchR.status !== 'launched' && launchR.status !== 'already-running')) { process.stderr.write(`[search] daemon error: ${launchRaw}\n`); process.exit(1); } ``` ### Technical Analysis The daemon owns a real Chromium instance and exposes privileged br ...[truncated 2672 chars]
Remediation
View remediation
{}); } } ``` 2. Avoid calling `process.exit()` inside the workflow. Set `process.exitCode` only after cleanup has completed. 3. Track whether the current invocation created the daemon or reused an existing daemon, so cleanup follows an explicit ownership policy. 4. Add an inactivity timeout to `daemon.js`; automatically close Chromium and exit after a short period without authenticated requests. 5. Monitor parent-process liveness where practical, or use a non-detached child when the architecture permits. 6. If state-file removal is intended to trigger shutdown, implement an actual watcher or periodic existence check. Otherwise, remove that unsupported lifecycle claim. 7. On startup, detect stale state files safely and terminate only a positively identified PriceWin daemon rather than relying solely on PID existence. 8. Add integration tests that inject failures after every major workflow stage and verify that no daemon or Chromium process remains. ]]>
Vulnerability Patterns
  • 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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (33)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

If the implementation lacks the claimed hotel-comparison logic and instead provides generic DOM extraction/mapping, the skill description is materially deceptive. That can cause inappropriate invocation, overbroad trust, and execution of tooling that harvests arbitrary page content rather than performing the narrow user-facing task described.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

If the implementation lacks the claimed hotel-comparison logic and instead provides generic DOM extraction/mapping, the skill description is materially deceptive. That can cause inappropriate invocation, overbroad trust, and execution of tooling that harvests arbitrary page content rather than performing the narrow user-facing task described.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

If the implementation lacks the claimed hotel-comparison logic and instead provides generic DOM extraction/mapping, the skill description is materially deceptive. That can cause inappropriate invocation, overbroad trust, and execution of tooling that harvests arbitrary page content rather than performing the narrow user-facing task described.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
f your runtime does not substitute it, `cd` into the folder that contains this `SKILL.md` (the one with `bin/search.js`). Avoid hardcoding a `~/.hermes/...` or

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
Let `search.js` do the scraping; don't scrape an OTA yourself.** Avoid calling `browse.js` directly, doing `goto`/`click`/`type` in the browser, building Agoda/

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 · bin/daemon.js (reported line 168)May include surrounding context.

js
const args = [
    '--disable-dev-shm-usage',
    '--password-store=basic',
    '--use-mock-keychain',
    '--disable-blink-features=AutomationControlled',
  ];
  const isLinuxRoot = process.platform === 'linux'

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill explicitly instructs the agent to run shell commands, access environment variables, and make network requests, yet it declares no tool/permission scope. That creates an unnecessary trust gap where a runtime or reviewer cannot easily constrain execution to the minimum required capabilities, increasing the blast radius if the skill is modified or behaves unexpectedly.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The description uses broad trigger language like 'use whenever someone asks for hotel prices' and related travel queries, which encourages frequent automatic activation. Over-broad invocation increases the chance that a skill with shell, network, and browser automation capabilities runs in situations where a simpler or safer response would suffice.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The markdown instructs the agent to infer parameters and run the workflow with minimal clarification, which biases toward automatic execution. In the context of a skill that performs shell execution and external browsing, this reduces opportunities to validate user intent and increases the likelihood of unnecessary or mistaken network activity.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
82% confidence
Finding

The installation command uses npx skills without a pinned version, so execution depends on whatever package version resolves at install time. This creates a supply-chain risk: a compromised or breaking upstream release could change behavior, execute unintended code, or silently widen capabilities.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
72% confidence
Finding

The natural-language usage text mandates passing a locale code and gives specific examples, but does not indicate that locale selection should come from user preference or explain any policy-based reason for enforcing locale handling this way. Under the language/locale policy rule, hard requirements around locale should either be user-chosen or clearly justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code sends user-supplied hotel search parameters (city, check-in/check-out dates, adults) to an external OpenTravel API endpoint, including a configurable base URL via an environment variable. Even though this is core functionality rather than overtly malicious behavior, there is no consent, disclosure, or trust-boundary validation in this file, so user travel data can be transmitted off-platform without clear user awareness and could be redirected to an untrusted endpoint if the environment is compromised.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.