Back to skill

Security audit

HR Workforce Dashboard 人力看板

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but it has a real file-deletion risk and uses remote JavaScript in sensitive HR dashboards.

Review before installing. Use only a newly created, dedicated output folder inside the workspace, avoid pointing --output-dir at any existing project or personal directory, and treat generated dashboards as sensitive HR material. Open dashboard.html only in an environment where loading jsDelivr is acceptable, and verify recipients before using the email/clipboard feature.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/build_dashboard_bundle.py:2683
Finding
Arbitrary Output Directory Cleanup Can Delete Unrelated Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/build_dashboard_bundle.py`, lines 2683-2690; invoked at lines 2875-2879 and 2949 **Vulnerability Type**: Unsafe recursive deletion using a user-controlled output path **Risk Level**: High ### Vulnerable Code ```python def cleanup_output_dir(output_dir: Path) -> None: for folder_name in ["png", "excel", "ppt"]: folder = output_dir / folder_name if folder.exists(): shutil.rmtree(folder) for file_path in output_dir.iterdir() if output_dir.exists() else []: if file_path.is_file() and file_path.name != "dashboard.html": file_path.unlink() ``` The cleanup function is invoked against the resolved command-line path before workbook validation: ```python def main() -> None: args = parse_args() output_dir = Path(args.output_dir).resolve() output_dir.mkdir(parents=True, exist_ok=True) cleanup_output_dir(output_dir) ``` It is invoked again after generating the HTML: ```python build_html(meta, html_path, dashboard1_image, dashboard2_image, d3_df, d4_df, d3_meta, d4_meta, d5_df=d5_df, executive_summary=executive_summary, d1_df=d1_df, d1_meta=d1_meta, d2_df=d2_df, d2_meta=d2_meta) cleanup_output_dir(output_dir) print(html_path) ``` ### Technical Analysis The `--output-dir` argument is fully user-controlled. Although the path is normalized with `resolve()`, the script does not verify that it is a newly created, Skill-owned directory or that it resides within the current workspace. The cleanup operation: - Recursively deletes any `png`, `excel`, or `ppt` directory beneath the selected path. - Deletes every top-level regular file except one named `dashboard.html`. - Runs before validating whether the input workbooks are usable. - Runs again after dashboard generation. - Does not require an ownership marker or explicit confirmation. Path normalization does not provide a security boundary. An absolute path, workspace root, or e ...[truncated 1542 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require a dedicated output directory rather than accepting an arbitrary existing directory. 2. Reject dangerous destinations, including filesystem roots, user home directories, and the current workspace root. 3. Create a Skill-specific ownership marker, such as `.hr-workforce-dashboard-output`, and refuse cleanup unless the marker is present. 4. Validate all input workbooks before performing any destructive output operation. 5. Delete only an explicit allowlist of files generated by this Skill, rather than all top-level files. 6. Avoid recursive deletion of generic directory names. Remove only known artifact files inside Skill-owned directories. 7. Prefer a fresh temporary staging directory and atomically move completed artifacts to the requested destination. 8. If an existing non-empty output directory is supplied, fail safely or require explicit user confirmation. 9. Resolve each deletion target and verify that it remains beneath the approved output root before deletion. 10. Add automated tests covering dangerous values such as `/`, a home directory, the workspace root, and an existing unrelated project directory. ]]>

T03 · Remote Payload Retrieval and Execution

Warning
Location
scripts/build_dashboard_bundle.py:2265
Finding
Generated Dashboard Executes Mutable Third-Party JavaScript from a CDN<![CDATA[ ## Vulnerability Details **File Location**: `scripts/build_dashboard_bundle.py`, line 2265 **Vulnerability Type**: Remote executable dependency without an exact version or integrity verification **Risk Level**: Medium ### Vulnerable Code ```html <script src='https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js'></script> ``` ### Technical Analysis The generated dashboard retrieves and executes JavaScript from a third-party CDN whenever the HTML is opened with network access. The dependency uses the floating major-version selector `echarts@5` instead of an exact reviewed release and does not provide a Subresource Integrity hash. As a result, the effective executable code is not fully contained in the audited Skill package and can change after the audit. A CDN compromise, package-account compromise, malicious upstream release, or unexpected major-line update could cause arbitrary JavaScript to execute in the dashboard's browser context. This is especially relevant because the page contains aggregated HR workforce information and offers clipboard and email-generation functionality. Remote code running in the page can read the rendered DOM and initiate outbound browser requests. The remote dependency also contradicts the declared expectation that `dashboard.html` is self-contained. ### Attack Path 1. The Skill generates `dashboard.html` containing the external script reference. 2. A user opens the dashboard while connected to a network. 3. The browser requests `echarts.min.js` from jsDelivr using the mutable `echarts@5` selector. 4. If the CDN response or upstream package has been compromised or unexpectedly changed, the returned code executes automatically. 5. The remote code can inspect dashboard content, alter metrics, manipulate the interface, or attempt to transmit displayed information through browser network APIs. Successful exploitation depends on compromise or malicious alteration of the remote dependency delivery chain; no local co ...[truncated 730 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Bundle a reviewed ECharts distribution within the Skill and embed or reference that local asset. 2. Pin ECharts to an exact version rather than using the mutable `@5` major-version selector. 3. Generate a genuinely self-contained and offline-capable HTML file where feasible. 4. If remote loading is unavoidable, use a version-specific immutable URL. 5. Add a verified Subresource Integrity hash and `crossorigin="anonymous"` to the script element. 6. Establish a documented dependency-update process that includes review, integrity-hash regeneration, and regression testing. 7. Add a restrictive Content Security Policy that permits scripts only from explicitly approved sources and limits outbound connections. 8. Consider using the already generated static chart images as an offline fallback when the reviewed local chart library is unavailable. ]]>
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 (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The top-level description emphasizes interactive HTML output, but the body also instructs generating Excel, PowerPoint, markdown summaries, and ZIP bundles. This mismatch weakens user consent and review because the skill performs broader data transformation and packaging than the summary suggests, which is significant for sensitive HR data.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The top-level description emphasizes interactive HTML output, but the body also instructs generating Excel, PowerPoint, markdown summaries, and ZIP bundles. This mismatch weakens user consent and review because the skill performs broader data transformation and packaging than the summary suggests, which is significant for sensitive HR data.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README documents a feature that copies a full HR dashboard to the system clipboard and opens an email client, but it provides no privacy warning, consent language, recipient verification guidance, or data-handling safeguards. Because the skill processes sensitive workforce data, this increases the risk of accidental disclosure through clipboard leakage, pasting into the wrong destination, or sending prefilled content to unintended recipients.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill explicitly instructs creating output directories, reading uploaded Excel files, and writing generated artifacts, but it does not declare any tool scope or permissions boundaries. In an agent environment, missing scope declarations can let the skill run with broader-than-expected file read/write access, increasing the chance of unintended access to unrelated workspace data or overwriting files.

Vague Triggers

Medium
Confidence
95% confidence
Finding
Broad trigger phrases such as '看板' and 'workforce report' can cause the skill to activate for loosely related HR requests, leading it to process attachments or generate outputs when the user did not intend to invoke this fixed workflow. In the HR context, accidental activation matters because the inputs contain employee and termination data, making unnecessary processing a privacy and data-minimization concern.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill directs one-click email generation and clipboard copying of full dashboards derived from HR datasets without an explicit warning, confirmation, or recipient review step. Because the dashboards may contain sensitive headcount, attrition, and country-level workforce details, this creates a concrete risk of unintended disclosure through email drafts, clipboard leakage, or pasting into the wrong destination.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This markdown file presents all installation, invocation, and usage guidance exclusively in Chinese. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly documented and justified.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
These lines require titles, notes, and footnotes to be in Chinese and the overall output style to be mixed Chinese-English. Under the policy, forcing a specific language or locale without user opt-in is a natural-language policy violation unless clearly justified as region-specific, which is not stated here.

Intent-Code Divergence

Medium
Confidence
99% confidence
Finding
The table header text explicitly says the percentage columns are '% of Involuntary', but the underlying rows are filled from 'Overall Attrition %', 'Voluntary Attrition %', 'Involuntary Attrition %', 'Others Attrition %', and 'Statutory Attrition %'. This is an active contradiction in rendered documentation that can mislead users about the meaning of the numbers.

Natural-Language Policy Violations

Medium
Confidence
84% confidence
Finding
SQP-3 applies to all file types. The generated document sets lang='zh-CN', and the script also defaults titles and UI text to Chinese throughout, which forces a specific language/locale rather than offering a choice or documenting a justified region-specific constraint.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The manifest says the skill outputs a self-contained interactive HTML, which implies the result should work standalone. However, the generated document loads ECharts from jsDelivr at runtime, so chart interactivity depends on external network access and a third-party CDN rather than being fully bundled into the output.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The script recursively deletes output subdirectories and unlinks nearly all files in the user-supplied output directory before generating results. In an agent or automation context, a mistaken or attacker-influenced --output-dir could cause destructive data loss outside the intended workspace, making this more dangerous than a normal local utility cleanup routine.

Description-Behavior Mismatch

Medium
Confidence
88% confidence
Finding
The manifest describes standardized dashboard outputs and mentions only a self-contained HTML, while this builder script includes substantial code for Excel, PowerPoint, summary, and ZIP bundle generation but the main path ultimately writes only dashboard.html and immediately cleans output directories. This creates a mismatch between the script's implemented bundle-building behavior and its actual final output behavior.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
A language or locale policy issue exists when a skill forces a specific language without user opt-in. This README presents all instructions, usage examples, and operational guidance exclusively in Chinese, with no indication that users may choose another language or that the locale restriction is deliberate and justified.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The document states a presentation preference with Chinese titles and English country/region/BG names as the default output format. This imposes a locale/language choice rather than offering the user a selectable language option or documenting a required regional compliance reason.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
Line L150 instructs the system to mark incomplete data using the Chinese phrase `数据不完整`, which imposes a specific language choice in the skill behavior. The document does not indicate user opt-in, locale selection, or a region-specific justification for forcing that output language.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
This markdown file contains all operational instructions in Chinese and does not mention any language selection, alternative locale, or user opt-in. Under the policy rule for language or locale constraints, forcing a specific language without offering choice can be a natural-language policy violation.

Missing User Warnings

Low
Confidence
80% confidence
Finding
The script generates dashboard.html and has functions to write summary markdown, Excel, PowerPoint, PNGs, and ZIP bundles, but the code does not provide visible runtime disclosure to the user about these write operations. For code-file SQP-2, file writes should have some form of notice unless clearly disclosed elsewhere in the skill description, which is not visible in this file.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
This Python file embeds user-facing Chinese strings for dropdown prompts and validation errors, and similar fixed-language labels appear throughout the generated workbook. Under the policy rule for language or locale constraints, forcing a specific language without user opt-in is a natural-language policy issue.

Static analysis

No suspicious patterns detected.