Back to skill

Security audit

dws

Security checks for vulnerabilities and agentic risk

Overview

This is a broad DingTalk management skill, but some workflows can read private communications or change/share sensitive business records without enough guardrails.

Install only in an environment where the dws CLI, account, and DingTalk tenant permissions are trusted. Use a least-privileged DingTalk account, require explicit confirmation before approvals, attendance changes, deletes, permission grants, messages, and file uploads, and avoid cross-source speaker matching or private chat analysis unless the affected data sources are explicitly approved. Preinstall dependencies in a controlled environment rather than allowing runtime pip installation.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/upload_attachment.py:69
Finding

Unvalidated Presigned Upload URL Can Disclose Local Attachment Files

Content
View full analysis
bool: """Upload the file to OSS through HTTP PUT.""" file_data = file_path.read_bytes() req = Request(upload_url, data=file_data, method='PUT') req.add_header('Content-Type', mime_type) try: with urlopen(req, timeout=120) as resp: ``` ### Technical Analysis The function reads the complete contents of a local file and transmits them to `upload_url`. That URL is obtained from the output of the `dws aitable attachment upload` command, but the script does not independently validate: - The URL scheme, such as requiring HTTPS. - Whether the destination hostname belongs to an approved DingTalk or Alibaba OSS domain. - Whether the URL contains embedded credentials or uses an unexpected port. - Whether DNS resolution points to a loopback, private, or link-local address. - Whether the final destination remains approved after redirects. Uploading file bytes to object storage is necessary for the declared attachment functionality. However, trusting an unrestricted destination URL is broader than the minimum network privilege required. A compromised or spoofed `dws` executable, service response, or upstream endpoint could return an attacker-controlled upload URL. The local file is explicitly selected through a command-line argument, so this is not arbitrary filesystem discovery. Nevertheless, the selected file may contain sensitive business or personal information, and the function will disclose its complete contents without confirming the destination. ### Attack Path 1. A user or agent invokes `upload_attachment.py` with a legitimate-looking base ID and a sensitive local file. 2. The script executes `dws aitable attachment upload`. 3. A compromised local `dws` binary o ...[truncated 1037 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/aitable_import_via_task.py:54
Finding

Unvalidated Import Upload URL Can Redirect Spreadsheet Contents

Content
View full analysis
Tuple[bool, str]: payload = file_path.read_bytes() req = Request(upload_url, data=payload, method="PUT") # Important: clear Content-Type to avoid SignatureDoesNotMatch. req.add_header("Content-Type", "") try: with urlopen(req, timeout=180) as resp: if resp.status == 200: return True, "" ``` ### Technical Analysis The AI-table import helper sends the complete contents of a local CSV or spreadsheet to an `uploadUrl` returned by `dws`. Although the extension is restricted to `.csv`, `.xlsx`, and `.xls`, the destination URL is not constrained. No check requires HTTPS or verifies that the hostname belongs to a reviewed DingTalk or Alibaba OSS domain. The code also does not reject internal network destinations, embedded credentials, unusual ports, or an unapproved final destination reached through redirection. The HTTP PUT operation is necessary for the declared import workflow, but unrestricted outbound transmission exceeds the least network privilege needed for that workflow. File-extension validation does not protect the confidentiality of the imported spreadsheet. ### Attack Path 1. A user invokes the import helper with a spreadsheet containing sensitive data. 2. The script calls `dws aitable import upload`. 3. A compromised local binary, service, or upstream response supplies an attacker-controlled `uploadUrl`. 4. The script performs no independent validation of that URL. 5. `file_path.read_bytes()` reads the complete spreadsheet into memory. 6. `urlopen()` transmits the spreadsheet to the supplied destination. 7. The attacker obtains all imported spreadsheet contents. ### Impact Assessment Exploitation can disclose the complete contents of a us ...[truncated 469 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/attendance_report_common.py:1491
Finding

Attendance Image Retrieval Allows Server-Side Request Forgery and Unbounded Response Buffering

Content
View full analysis
bool: """Simply determine whether a value is an HTTP(S) URL.""" if not isinstance(value, str): return False s = value.strip() return s.startswith("http://") or s.startswith("https://") def download_and_convert_image( url: str, *, timeout: int = 10, ) -> str | None: """ Download an image URL, convert it to PNG with PIL, cache it locally, and return the local PNG path. """ if url in _image_url_to_local: return _image_url_to_local[url] if url in _image_failed_urls: return None cache_dir = _ensure_image_cache_dir() url_hash = hashlib.md5(url.encode("utf-8")).hexdigest() local_path = os.path.join(cache_dir, f"{url_hash}.png") if os.path.exists(local_path) and os.path.getsize(local_path) > 0: _image_url_to_local[url] = local_path return local_path try: import requests except ImportError: warn("The requests dependency is missing; image download is unavailable.") _image_failed_urls.add(url) return None try: from PIL import Image as PILImage except ImportError: warn("The Pillow dependency is missing; image conversion is unavailable.") _image_failed_urls.add(url) return None try: resp = requests.get(url, timeout=timeout) resp.raise_for_status() raw_bytes = resp.content if not raw_bytes: raise ValueError("The downloaded response is empty.") ``` ### Technical Analysis The downloader treats every string beginning with `http://` or `https://` as a valid image URL. It then issues a request without validating the hostname or resolved address. Consequently, a URL originating fr ...[truncated 2298 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/attendance_report_common.py:1624
Finding

Report Generation Installs an Unpinned Package at Runtime

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (241)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明描述的是一个覆盖大量钉钉产品场景的通用管理技能,主用途应是操作各类钉钉资源与业务流程。但提供的代码块仅实现了对 URL 路径的解析,通过正则去除尺寸或扩展名后缀并添加 @ 前缀,输出 mediaId。它既没有访问钉钉服务,也没有实现任何声明中的核心业务能力。虽然该脚本与“群聊/机器人发消息”场景中的媒体消息发送工作流存在间接关联,但它只是一个非常狭窄的辅助函数,无法支撑声明中的广泛能力范围,因此描述与实际行为存在明显不匹配。

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 81)May include surrounding context.

md
| `chat` | 群聊与机器人:搜索群/建群/群成员管理/改群名/消息发送(文本/Markdown/图片/文件)/拉取消息/消息收藏/@我/特别关注/机器人群发/单聊/撤回/转发/引用回复/Webhook/机器人搜索 | [chat.md](./references/products/chat.md) |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| `sheet` | 在线电子表格(axls):工作表 CRUD/区域读写/CSV 批量写入/行列增删/合并/查找替换/筛选视图/全局筛选/排序/下拉列表/条件格式/浮动图片/浮动图表/模板/导出 xlsx(单命令一站式) | [sheet.md](./references/products/sheet.md) |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 更多易混淆场景见 [intent-guide.md](./references/intent-guide.md)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
> 更多易混淆场景见 [intent-guide.md](./references/intent-guide.md)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill tells the agent to query recent chat messages for identity inference without any user-facing notice or consent flow. Hidden access to private communications is especially dangerous because users may believe the agent is operating only on the meeting transcript, while it is actually broadening surveillance to unrelated conversations.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill offers to replace speaker labels and says the system will remember voiceprint features for future automatic recognition, but it does not warn about the persistent biometric effect or its privacy implications. Voiceprint persistence is sensitive because it creates long-term identification capability that can affect future meetings and users beyond the immediate task.

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/global-reference.md (reported line 12)May include surrounding context.

md
# 查看状态
dws auth status

# macOS: 将系统 Keychain 登录态迁移为沙箱可读的 file-DEK(先预检)
env -u DWS_DISABLE_KEYCHAIN dws auth migrate-keychain --to file-dek --dry-run --format json
env -u DWS_DISABLE_KEYCHAIN dws auth migrate-keychain --to file-dek --yes --format json

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/global-reference.md (reported line 13)May include surrounding context.

md
dws auth status

# macOS: 将系统 Keychain 登录态迁移为沙箱可读的 file-DEK(先预检)
env -u DWS_DISABLE_KEYCHAIN dws auth migrate-keychain --to file-dek --dry-run --format json
env -u DWS_DISABLE_KEYCHAIN dws auth migrate-keychain --to file-dek --yes --format json

# 退出

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/global-reference.md (reported line 14)May include surrounding context.

md
dws auth status

# macOS: 将系统 Keychain 登录态迁移为沙箱可读的 file-DEK(先预检)
env -u DWS_DISABLE_KEYCHAIN dws auth migrate-keychain --to file-dek --dry-run --format json
env -u DWS_DISABLE_KEYCHAIN dws auth migrate-keychain --to file-dek --yes --format json

# 退出

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/global-reference.md (reported line 13)May include surrounding context.

md
dws auth status

# macOS: 将系统 Keychain 登录态迁移为沙箱可读的 file-DEK(先预检)
env -u DWS_DISABLE_KEYCHAIN dws auth migrate-keychain --to file-dek --dry-run --format json
env -u DWS_DISABLE_KEYCHAIN dws auth migrate-keychain --to file-dek --yes --format json

# 退出

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/global-reference.md (reported line 14)May include surrounding context.

md
dws auth status

# macOS: 将系统 Keychain 登录态迁移为沙箱可读的 file-DEK(先预检)
env -u DWS_DISABLE_KEYCHAIN dws auth migrate-keychain --to file-dek --dry-run --format json
env -u DWS_DISABLE_KEYCHAIN dws auth migrate-keychain --to file-dek --yes --format json

# 退出

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/global-reference.md (reported line 40)May include surrounding context.

md
| Token | 有效期 | 说明 |
|-------|--------|------|
| Access Token | 2 小时 | 调用 API 的凭证,过期自动刷新 |
| Refresh Token | 30 天 | 换新 Access Token,使用后轮转 |

30 天内使用一次即自动续期。

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/global-reference.md (reported line 41)May include surrounding context.

md
| Token | 有效期 | 说明 |
|-------|--------|------|
| Access Token | 2 小时 | 调用 API 的凭证,过期自动刷新 |
| Refresh Token | 30 天 | 换新 Access Token,使用后轮转 |

30 天内使用一次即自动续期。

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The boss-check workflow instructs the agent to obtain planId by directly calling schedule get, but the same file explicitly forbids direct use of schedule get and requires a separate workflow document instead. This conflict is dangerous because it creates a policy exception around a high-risk write operation that alters attendance records, making it easier for the agent to bypass safeguards or use incomplete/incorrect data when modifying employee time records.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The guidance explicitly tells the agent to correlate transcript data with contacts, chats, calendars, and documents to infer speaker identities, but it does not require user consent or a privacy warning. This creates a strong risk of invasive profiling and secondary use of personal data across systems for a purpose users and meeting participants may not reasonably expect.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The instructions direct the agent to mine private auxiliary sources such as contacts, chats, and calendars to infer identities from meeting content. This is dangerous because it turns a minutes-processing skill into a cross-system surveillance workflow, potentially exposing unrelated private data and enabling deanonymization without clear necessity or consent.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

This section mandates broad cross-source collection from contacts, documents, calendar, and chat to identify a person from transcript data. Such forced aggregation materially increases privacy risk and can reveal sensitive relationships, work patterns, and personal context unrelated to the user's immediate request.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The permission-add workflow enables granting access to transcripts, summaries, and downloadable media, but the documentation lacks a prominent warning about the sensitivity of what may be shared. In practice, an agent following this guidance could grant broad access to highly sensitive meeting artifacts without sufficiently surfacing the consequences to the user.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill encourages harvesting across meetings, chats, private messages, schedules, and document edits to build broad activity summaries. In an enterprise environment this can produce an extensive surveillance-style profile of a user's behavior, greatly exceeding the minimum data needed for many reporting tasks.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The markdown documents approve, reject, and revoke commands as straightforward executable operations but omits any warning that they change workflow state, may be irreversible, or require confirmation. Given the skill's context of handling real enterprise approvals, this omission materially increases the chance that an agent or operator performs destructive business actions without sufficient verification.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Auto-installing Python packages via pip during normal execution is unsafe because it turns a report-export path into code that modifies the host environment and depends on external package resolution. This is especially risky in agent contexts, where a simple user request could trigger unexpected software installation, supply-chain exposure, or policy violations on enterprise systems.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill exposes broad operational capabilities over DingTalk data and messaging but does not declare any explicit tool scope such as permissions or allowed-tools. In a powerful skill that can read, write, delete, message, upload, and monitor events across many products, missing scope boundaries increases the blast radius of prompt injection, misuse, or accidental invocation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The file consistently mandates and presents all user-facing guidance in Chinese, from the manifest description through the operational instructions. This can violate a language/locale policy when the skill forces a specific language without explicitly allowing the user to choose another language or opt in to Chinese-only operation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The document recommends exporting and summarizing group and private chat histories, including pagination and file export, but gives no privacy warning, authorization check, or data-minimization guidance. Because this skill manages enterprise communications, such exports can expose sensitive personal, business, or confidential information at scale.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.