Back to skill

Security audit

Share to GetNote

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its advertised import workflow, but weak URL validation can make its browser open unintended or internal URLs, and it installs mutable browser dependencies at runtime.

Review before installing. Only use this skill in a constrained environment, avoid running it on links from untrusted people, and treat imported shared conversations as potentially sensitive. Prefer a version that strictly validates HTTPS hostnames and paths, pins Playwright, and requires explicit consent before downloading browser artifacts.

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

Error
Location
scripts/parse_share.py:28
Finding

Unanchored URL Validation Allows Arbitrary Browser Navigation and SSRF

Content
View full analysis
str: for pat in CHATGPT_PATTERNS: if pat.search(url): return "chatgpt" for pat in GEMINI_PATTERNS: if pat.search(url): return "gemini" return "" ``` The accepted string is subsequently used as the browser navigation destination: ```python await page.goto(url, wait_until="domcontentloaded", timeout=timeout * 1000) ``` Redirect validation is incomplete: ```python current_url = page.url if "share_not_found" in current_url or "not_found" in current_url: await browser.close() print("分享链接已过期或不存在。", file=sys.stderr) sys.exit(2) if platform == "chatgpt" and "/share/" not in current_url and "/s/t_" not in current_url: await browser.close() print( f"页面被重定向到 {current_url},分享链接可能已过期或需要登录。", file=sys.stderr, ) sys.exit(2) ``` ### Technical Analysis The validation expressions are used with `re.Pattern.search()`, so an approved URL only needs to occur somewhere inside the input. The code does not parse the URL or verify that its actual hostname is an approved ChatGPT or Gemini host. For example, the following input is classified as ChatGPT even though its real destination is a loopback service: ```text http://127.0.0.1:8080/?source=https://chatgpt.com/share/example ``` Because the full, attacker-controlled string is passed to `page.goto()`, Chromium navigates to `127.0.0.1`, not `chatgpt.com`. The post-navigation controls do not eliminate this issue. ...[truncated 1969 chars]
Remediation
View remediation
str: parsed = urlsplit(url) if parsed.scheme != "https" or parsed.username or parsed.password: return "" host = (parsed.hostname or "").rstrip(".").lower() prefixes = ALLOWED_PATHS.get(host) if not prefixes or not any(parsed.path.startswith(p) for p in prefixes): return "" if host in {"chatgpt.com", "chat.openai.com"}: return "chatgpt" return "gemini" ``` The same hostname, address-range, and path validation must be applied to the final URL and all intermediate redirects before their content is trusted. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/parse_share.py:3
Finding

Unpinned Runtime Dependencies and Browser Artifacts Create Supply-Chain Exposure

Content
View full analysis
=3.9" # dependencies = ["playwright"] # /// ``` The alternative dependency manifest permits any future Playwright version at or above 1.40.0: ```text playwright>=1.40.0 ``` The script also downloads and installs Chromium dynamically during execution: ```python # Check if chromium binary already exists in Playwright's cache pw_browsers = Path.home() / "Library" / "Caches" / "ms-playwright" chromium_exists = any(pw_browsers.glob("chromium-*")) if pw_browsers.exists() else False if not chromium_exists: print("正在安装 Chromium 浏览器(首次运行需要下载)...", file=sys.stderr) result = subprocess.run( [sys.executable, "-m", "playwright", "install", "chromium"], capture_output=True, text=True, timeout=600, ) if result.returncode != 0: print( f"Chromium 浏览器安装失败:\n{result.stderr}", file=sys.stderr, ) sys.exit(4) ``` ### Technical Analysis The package has no exact dependency pin, committed lockfile, or recorded artifact hash. Consequently, two installations of the same Skill version can resolve to different Playwright versions. First execution may also install a browser artifact selected by the version resolved at that time. This prevents reproducible review: the executable package and browser components used in production can differ from those assessed during the audit. Although the project uses the legitimate `playwright` package name and there is no evidence that the currently available package is malicious, open-ended resolution increases exposure to future upstream compromise, malicious package-index substitution, incom ...[truncated 1871 chars]
Remediation
View remediation
"] ``` ```text playwright== ``` 2. Generate and commit a lockfile containing exact versions and cryptographic hashes. 3. Use a controlled package index or organization-managed mirror, and require hash verification during installation. 4. Pin the corresponding Chromium revision and obtain it through a trusted, integrity-verified artifact channel. 5. Prefer provisioning Playwright and Chromium during a controlled build or installation phase rather than downloading executable artifacts when processing a user request. 6. Run the browser in a constrained container or sandbox with minimal filesystem access, no unnecessary credentials, and restricted network egress. 7. Use Playwright APIs or documented environment variables to locate browser installations instead of checking only the macOS cache path. 8. Establish an update process in which dependency and browser upgrades are explicitly reviewed, tested, and reflected in a new Skill release. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared behavior says the skill saves shared conversations to GetNote, but the documented workflow also fetches external pages with Playwright, outputs extracted content to stdout, and relies on a separate skill for actual persistence. This mismatch reduces transparency about network access and data handling, which can mislead operators into approving a skill that performs broader collection and processing of external content than its description suggests.

Content

No source excerpt is available for this finding.

Context Leakage

High
Category
Data Exfiltration
Confidence
91% confidence
Finding

The core purpose of this skill is to fetch shared ChatGPT/Gemini conversations and extract their contents into note objects, which can propagate sensitive prompts, responses, links, or embedded secrets into another system. In this skill context, that makes context leakage materially more dangerous because it automates cross-system transfer of potentially sensitive conversation data without any content minimization, redaction, or trust checks.

Content

Scanner excerpt · scripts/parse_share.py (reported line 253)May include surrounding context.

python
async def fetch_and_extract(url: str, platform: str, timeout: int = 60) -> tuple[list[dict], str]:
    """Use Playwright to fetch page and extract conversation data.

    Returns (raw_messages, page_title).
    """

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill instructs the agent to execute shell commands (uv run ...) and install dependencies, but it declares no explicit tool scope or allowed-tools boundary. That creates an authorization gap where a runtime capable of shell execution may run external code and package installation without a clearly declared permission model, increasing the chance of unintended command execution or overly broad agent behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script appends Chinese text ("来源" and "第 ... 轮") into every output item, and many user-facing stderr messages elsewhere in the file are also Chinese-only. This imposes a specific locale on all users without opt-in or any documented language selection, which matches the policy category for forced language/locale behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill performs package-management-like behavior and modifies the local environment by auto-installing Chromium when it is missing. In an agent-skill context, this is riskier than a normal parser because a user asking to parse a link may not expect network downloads, disk writes, or execution of installer logic, which broadens the attack surface and can violate least surprise or policy boundaries.

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/parse_share.py (reported line 388)May include surrounding context.

python
if not chromium_exists:
        print("正在安装 Chromium 浏览器(首次运行需要下载)...", file=sys.stderr)
        result = subprocess.run(
            [sys.executable, "-m", "playwright", "install", "chromium"],
            capture_output=True,
            text=True,

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency is specified with a lower-bound version only, which allows future unreviewed Playwright releases to be installed. This creates supply-chain risk because a breaking, compromised, or vulnerable upstream version could be pulled into the skill without explicit testing or approval.

Content

Scanner excerpt · scripts/requirements.txt (reported line 1)May include surrounding context.

text
playwright>=1.40.0

Static analysis

No suspicious patterns detected.