Back to skill

Security audit

DingTalk Sheets

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real DingTalk spreadsheet helper, but it needs Review because it can modify remote spreadsheets and export local CSV/TSV files with insufficient safety controls.

Install only if you trust the publisher, the npm source for mcporter, and the DingTalk MCP endpoint you configure. Review target spreadsheet, sheet, range, and output path before any write/import/export operation, and treat exported CSV/TSV files as untrusted if other people can edit the source spreadsheet.

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/export_sheet.py:59
Finding
CSV/TSV Formula Injection in Spreadsheet Exports## Vulnerability Details **File Location**: `scripts/export_sheet.py:59-68, 90-96` **Vulnerability Type**: CSV/TSV formula injection **Risk Level**: Medium ### Vulnerable Code ```python def select_table(payload: dict) -> list[list[str]]: """Prefer displayValues, then values.""" table = payload.get("displayValues") or payload.get("values") or [] if not isinstance(table, list): return [] normalized: list[list[str]] = [] for row in table: if isinstance(row, list): normalized.append(["" if cell is None else str(cell) for cell in row]) return normalized ``` ```python def save_table(rows: list[list[str]], output_path: Path) -> bool: """Save as a CSV or TSV file.""" try: with open(output_path, "w", encoding="utf-8-sig", newline="") as handle: writer = csv.writer(handle, delimiter=detect_delimiter(output_path)) writer.writerows(rows) return True except Exception as error: print(f"Failed to save file: {error}") return False ``` ### Technical Analysis Data obtained from remote spreadsheet cells is converted to strings and written directly to CSV or TSV without neutralizing formula-triggering prefixes. Quoting performed by `csv.writer` does not reliably prevent spreadsheet software from interpreting fields beginning with characters such as `=`, `+`, `-`, or `@` as formulas. An attacker who can modify the source DingTalk spreadsheet can therefore place a malicious formula into a cell and wait for another user to export and open the resulting file. Depending on the spreadsheet application and its security settings, formulas may initiate external network requests, disclose contextual data, present deceptive links, or invoke dangerous application-specific functionality. ### Attack Path 1. An attacker obtains legitimate or compromised write access to a DingTalk spreadsheet that the vict ...[truncated 1206 chars]
Remediation
## Remediation Suggestions - Add a dedicated CSV/TSV sanitization function that detects formula-triggering prefixes. - Neutralize cells beginning with `=`, `+`, `-`, or `@` by prefixing an apostrophe or another format-safe character. - Detect dangerous prefixes after leading spaces, tabs, carriage returns, and other characters that spreadsheet applications may ignore before formula evaluation. - Apply sanitization immediately before serialization so every export path receives the same protection. - If raw formula export is required, make it an explicit opt-in option and display a clear warning before writing the file. - Add tests covering direct prefixes, whitespace-obfuscated prefixes, ordinary text, numeric values, and both CSV and TSV output.

T08 · Insecure Dependencies

Note
Location
README.md:47
Finding
Unpinned Global Installation of an Executable Dependency## Vulnerability Details **File Location**: `README.md:47-51` **Additional Location**: `package.json:26-28` **Vulnerability Type**: Unpinned third-party executable dependency **Risk Level**: Low ### Vulnerable Code ```bash npm install -g mcporter ``` ```json "peerDependencies": { "mcporter": ">=0.7.0" } ``` ### Technical Analysis The installation instructions retrieve the mutable latest version of `mcporter` from the configured npm registry and install it globally. The package metadata only specifies a lower bound, allowing all future versions. There is no lockfile, exact reviewed version, or integrity constraint in the audited project. Because `mcporter` is both an executable dependency and the process used for all MCP operations, a compromised package release could execute npm lifecycle code during installation and later control spreadsheet requests and responses. This finding concerns reproducibility and supply-chain exposure; the audit found no evidence that the current `mcporter` package is malicious. ### Attack Path 1. The npm package, a future package release, a maintainer account, or the user's configured package registry is compromised. 2. An attacker publishes a malicious version that still satisfies `>=0.7.0`. 3. A user follows the documented `npm install -g mcporter` command. 4. npm retrieves the malicious mutable version and may execute its lifecycle scripts with the installing user's privileges. 5. The installed executable is subsequently invoked by `scripts/mcporter_utils.py`. 6. The malicious executable can observe or alter MCP operations and any spreadsheet content passed through those operations. ### Impact Assessment A malicious dependency could execute with the privileges of the user performing the global installation. It could access resources available to that account, interfere with local files, and compromise the confidentiality or integrity of spreadsheet operations. Sinc ...[truncated 369 chars]
Remediation
## Remediation Suggestions - Pin `mcporter` to a reviewed exact version in both installation documentation and package metadata. - Replace the global mutable installation command with an exact-version command, such as `npm install -g mcporter@<reviewed-version>`. - Use a lockfile and a reproducible local installation mechanism where operationally possible. - Verify package integrity or provenance during installation and document the expected package source. - Review dependency updates before changing the pinned version. - Consider disabling npm lifecycle scripts during installation when they are not required, while confirming that doing so does not break legitimate installation behavior.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (16)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The manifest describes a broad spreadsheet-management skill, while the body also introduces local export behavior and script-based file handling that are not clearly and consistently declared at the top-level description. This mismatch can cause users and orchestrators to authorize the skill under incomplete assumptions, increasing the risk of unintended local file creation or data exfiltration from remote spreadsheets into the workspace.

Credential Access

High
Category
Privilege Escalation
Content
try:
            os.environ["OPENCLAW_WORKSPACE"] = str(self.test_dir)
            with self.assertRaises(ValueError):
                import_sheet.resolve_safe_path("../etc/passwd")
        finally:
            if old_env:
                os.environ["OPENCLAW_WORKSPACE"] = old_env
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
try:
            os.environ["OPENCLAW_WORKSPACE"] = str(self.test_dir)
            with self.assertRaises(ValueError):
                import_sheet.resolve_safe_path("../etc/passwd")
        finally:
            if old_env:
                os.environ["OPENCLAW_WORKSPACE"] = old_env
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill declares capabilities that include environment-variable access, local file read/write, and shell execution via helper scripts and `mcporter`, but it does not constrain tool scope with explicit `permissions` or `allowed-tools`. This creates unnecessary ambient authority: if the agent is induced to use local scripts or shell paths unexpectedly, it could read/write workspace files or invoke tooling beyond the minimum needed for spreadsheet operations.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill supports creating spreadsheets, modifying remote cell ranges, and exporting spreadsheet contents to local files, but it does not prominently warn users that these actions can change remote data or write data into the local workspace. Without a clear warning/confirmation pattern, users may trigger destructive or privacy-impacting actions unintentionally.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The description contains a wide set of natural-language trigger phrases such as 表格, 电子表格, 在线表格, 工作表, 单元格, 报表, and CSV 导入导出, which can cause the skill to be invoked in loosely related requests. Because this skill performs read/write operations against DingTalk sheets using a credentialed service URL, unintended invocation could expose or modify spreadsheet data when the user intended a different document or workflow operation.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This markdown documents `update_range` as updating specified spreadsheet ranges and provides direct write examples, but it does not warn users that the operation will overwrite existing cell contents. Because the file is a markdown API reference and the behavior can affect user data integrity, a user-facing warning or caution is expected.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The `append_rows` section and its recommended replacement workflow describe adding rows to a sheet, which persistently modifies user data. The documentation does not include any caution about unintended duplication, placement errors, or the need to verify the destination before appending/writing.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The module docstring and CLI usage/help text are presented only in Chinese, and the script's runtime status/error messages are also hard-coded in Chinese. This imposes a specific language on users without opt-in or alternative locale support, which matches the stated language/locale policy violation category.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
command.extend(["--args", json.dumps(args, ensure_ascii=False)])

    try:
        result = subprocess.run(
            command,
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
This code performs a data-modifying operation by computing a target range and calling `update_range` to append rows to a DingTalk sheet. Although the docstring explains the implementation detail, there is no user-facing confirmation, warning, or disclosure that rows will be written/modified, which matches the code-file criteria for missing user warnings.

Missing User Warnings

Low
Confidence
90% confidence
Finding
The README explicitly advertises importing from and exporting to local CSV/TSV files but does not warn that these actions read from and write to the local filesystem. In an agent skill context, insufficient disclosure can lead users or higher-level agents to trigger file operations without appreciating their side effects, increasing the risk of unintended local data exposure or overwriting files.

Natural-Language Policy Violations

Low
Confidence
98% confidence
Finding
This file contains natural-language documentation and command-line output exclusively in Chinese, including the module docstring and help text. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless clearly justified, and no such justification or language-selection mechanism is present.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The module docstring and all user-visible explanatory text in this file are written exclusively in Chinese, indicating a fixed language/locale choice. There is no indication that users can opt into this locale or that the restriction is justified as region-specific, which fits the language-policy violation category.

Natural-Language Policy Violations

Low
Confidence
90% confidence
Finding
This Python test file contains natural-language text in Chinese in the module docstring, indicating a fixed language choice. Under the policy, locale or language constraints should either offer user choice or be clearly documented as region-specific; that context is not present in this file.

Natural-Language Policy Violations

Low
Confidence
83% confidence
Finding
The assertion message at this line is written only in Chinese, which hard-codes a specific language in user-visible test output. The file does not provide any indication that this locale restriction is intentional or configurable.

Static analysis

No suspicious patterns detected.