Back to skill

Security audit

Tencent Meeting Export

Security checks for vulnerabilities and agentic risk

Overview

The skill appears intended to export Tencent Meeting transcripts, but it needs review because it can launch a browser against arbitrary URLs while saving potentially sensitive meeting content locally.

Install only if you are comfortable running a local Chromium browser and saving meeting transcripts on disk. Use only Tencent Meeting share links you are authorized to access, avoid passing arbitrary URLs, and treat exported Markdown or JSON as sensitive meeting records. Prefer running it in an isolated environment and pinning reviewed Playwright dependencies.

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

Warning
Location
scripts/tencent_meeting_export.py:428
Finding
Destination Validation Does Not Prevent Navigation to Arbitrary URLs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/tencent_meeting_export.py:428-435`, with the navigation sink at `scripts/tencent_meeting_export.py:231-234` **Vulnerability Type**: Non-enforcing URL validation and unrestricted browser navigation **Risk Level**: Medium ### Vulnerable Code ```python if not re.match(r"https?://meeting\.tencent\.com/", args.url): print(f"警告: URL 不像是腾讯会议链接: {args.url}") print(" 预期格式: https://meeting.tencent.com/cw/xxxxx") # 抓取数据 capture = TranscriptCapture( url=args.url, timeout=args.timeout, verbose=not args.quiet, ) ``` The untrusted URL is later passed directly to the browser: ```python await page.goto( self.url, wait_until="networkidle", timeout=self.timeout * 1000, ) ``` ### Technical Analysis The regular-expression check only produces a warning. It does not reject the URL, terminate execution, or replace it with an approved destination. Therefore, any URL accepted by Playwright can reach `page.goto()`. This violates the Skill's documented trust boundary, which states that it processes Tencent Meeting public share links. The launched browser uses the host's network connectivity and executes JavaScript supplied by the destination. An attacker-controlled page can consequently cause browser requests to external services or to network resources reachable from the host. The response listener also processes responses by matching endpoint substrings such as `minutes/detail` and `get-full-summary`, without first requiring the response origin to be Tencent Meeting. An attacker-controlled page could therefore return crafted JSON from similarly named endpoints, although the captured data is only formatted and written to output files in the audited implementation. ### Attack Path 1. An attacker supplies a URL that is not hosted at `meeting.tencent.com`, such as an attacker-controlled HTTP(S) page or a reachable internal web application. 2. The user or agent invokes the export script wit ...[truncated 1319 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the supplied value using `urllib.parse.urlparse` rather than relying only on a regular expression. 2. Require all of the following conditions: - The scheme is exactly `https`. - The normalized hostname is exactly `meeting.tencent.com`. - No username or password is embedded in the URL. - The port is absent or explicitly approved. - The path begins with an approved Tencent Meeting share-link prefix, such as `/cw/`. 3. Raise an error and terminate before launching Chromium when any validation check fails. 4. Validate the final URL after redirects and reject redirects to unapproved origins. 5. Restrict intercepted API responses to the exact approved Tencent Meeting origin, not merely URLs containing expected endpoint substrings. 6. Consider adding request interception that blocks loopback, link-local, private-network, and non-HTTPS destinations. 7. Add tests covering malformed hosts, embedded credentials, alternate ports, redirects, loopback addresses, private IP addresses, and attacker-controlled domains. A hardened validation pattern should follow this structure: ```python from urllib.parse import urlparse parsed = urlparse(args.url) if ( parsed.scheme != "https" or parsed.hostname != "meeting.tencent.com" or parsed.username is not None or parsed.password is not None or parsed.port not in (None, 443) or not parsed.path.startswith("/cw/") ): raise ValueError("Only approved Tencent Meeting HTTPS share URLs are allowed") ``` ]]>

T08 · Insecure Dependencies

Note
Location
SKILL.md:20
Finding
Playwright and Chromium Are Installed Without Version or Integrity Pinning<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:20-23`; repeated in `scripts/tencent_meeting_export.py:17-18` and `scripts/tencent_meeting_export.py:42-43` **Vulnerability Type**: Unpinned executable third-party dependency **Risk Level**: Low ### Vulnerable Code ```bash pip install playwright playwright install chromium ``` ### Technical Analysis The installation instructions resolve the current Playwright release and its associated Chromium artifact at installation time. No reviewed version, lock file, package hash, browser revision, or integrity-verification procedure is provided. This makes installation non-reproducible and allows upstream changes to alter the code and browser binary executed by the Skill after the Skill itself has been audited. A future compromised package release, compromised distribution channel, or unexpectedly incompatible update could introduce code execution during installation or change browser behavior. No suspicious package name, dependency-confusion setup, custom package index, or known malicious source was identified. The risk arises from mutable and unverified supply-chain inputs rather than evidence that the current Playwright package is malicious. ### Attack Path 1. A user follows the documented prerequisite instructions. 2. `pip` resolves whichever Playwright version is current on the configured package index. 3. `playwright install chromium` retrieves the browser artifact associated with that mutable version. 4. If the selected package, artifact, account, index, or delivery path has been compromised, malicious code can execute during installation or when the browser is launched. 5. The resulting code runs with the privileges of the user installing or invoking the Skill. ### Impact Assessment A compromised Python dependency or browser artifact could execute code with the permissions of the installing user. Depending on those permissions, this could expose files, environment variables, meeting transcr ...[truncated 322 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin Playwright to a reviewed exact version, for example through a version-controlled requirements file. 2. Generate and enforce package hashes using a lock-file or hash-checking workflow. 3. Install only from an explicitly trusted Python package index. 4. Pin and verify the corresponding Chromium revision or use Playwright's documented reproducible browser-management process. 5. Review dependency updates before changing the pinned version. 6. Run installation and browser execution as an unprivileged user in an isolated virtual environment or container. 7. Add automated vulnerability and provenance checks for both Python packages and downloaded browser artifacts. An improved Python dependency installation pattern is: ```bash python -m pip install --require-hashes -r requirements.txt python -m playwright install chromium ``` The committed `requirements.txt` should contain an exact reviewed version and its approved hashes. ]]>
Vulnerability Patterns
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill documents and encourages writing exported transcript data to local files, but it does not declare any explicit tool scope or permissions boundary for file-writing behavior. This matters because meeting transcripts, summaries, speaker names, and event timelines can contain sensitive personal or business information, so undeclared write capability weakens user awareness and sandboxing expectations.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill promotes exporting full meeting transcripts from public share links but omits a warning that the resulting data may include sensitive personal, corporate, or regulated information even when the link is public. Users may incorrectly assume that 'public share' means low-risk data handling, leading to unintended disclosure, redistribution, or insecure storage of names, speech content, summaries, and participation events.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The script captures and writes potentially sensitive meeting artifacts—full transcripts, speaker identities, summaries, chapters, and event nodes—to local Markdown/JSON files without any privacy warning, consent check, or safer default handling. In the context of meeting recordings, this increases the risk of unauthorized retention, accidental sharing, and exposure of confidential business or personal information.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Content
# 分发到对应的处理器
            for pattern, handler_name in self.API_PATTERNS.items():
                if pattern in url:
                    getattr(self, handler_name)(data)
                    break
        except Exception:
            pass
Confidence
50% confidence
Finding
Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
The Playwright browser context is configured with locale="zh-CN", which imposes a specific locale behavior. Under the policy, locale constraints should be optional or clearly justified; this file does not provide a user opt-in or explanation that the tool is limited to Chinese locale operation.