Back to skill

Security audit

Tmall Weekly Report

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent Tmall weekly-report generator, with a local file-output caveat but no evidence of hidden execution, credential access, network exfiltration, or persistence.

Install only if you want a Chinese Tmall weekly-report workflow and are comfortable providing store performance data to the agent. Before running the chart script, check or change the hard-coded output directory so it writes inside your intended project folder and does not overwrite prior reports.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/make_charts.py:21
Finding

Hard-Coded Output Directory Enables Predictable File Overwrites Outside the Project

Content
View full analysis

Vulnerability Details

File Location: scripts/make_charts.py:21, 129, 193, 254, 300, 355, 417, 461, 521, 574, 638, 687, 741
Vulnerability Type: Unvalidated absolute output path and predictable file overwrite
Risk Level: Medium

Vulnerable Code

python
OUT = '/home/ubuntu/weekly_report_v3/charts'

plt.savefig(f'{OUT}/fig01_overview.png', dpi=150, bbox_inches='tight')
plt.savefig(f'{OUT}/fig02_refund.png', dpi=150, bbox_inches='tight')
plt.savefig(f'{OUT}/fig03_traffic.png', dpi=150, bbox_inches='tight')
plt.savefig(f'{OUT}/fig04_customers.png', dpi=150, bbox_inches='tight')
plt.savefig(f'{OUT}/fig05_live.png', dpi=150, bbox_inches='tight')
plt.savefig(f'{OUT}/fig06_cs.png', dpi=150, bbox_inches='tight')
plt.savefig(f'{OUT}/fig07_products.png', dpi=150, bbox_inches='tight')
plt.savefig(f'{OUT}/fig08_ads_scene.png', dpi=150, bbox_inches='tight')
plt.savefig(f'{OUT}/fig09_ads_plan.png', dpi=150, bbox_inches='tight')
plt.savefig(f'{OUT}/fig10_ads_daily.png', dpi=150, bbox_inches='tight')
plt.savefig(f'{OUT}/fig11_content.png', dpi=150, bbox_inches='tight')
plt.savefig(f'{OUT}/fig12_priority.png', dpi=150, bbox_inches='tight')

Technical Analysis

The chart generator writes all generated images to a fixed absolute directory outside the project. The destination cannot be selected by the user, is not constrained to an authorized workspace, and is not validated before writing.

All output filenames are static and predictable. Matplotlib's savefig operation normally replaces an existing destination without requesting confirmation. The script does not check whether the destination already exists, whether it is a symbolic link, or whether the resolved destination remains inside an approved output directory.

Consequently, running the script can overwrite prior reports or other files at those paths. If a local attacker can modify the hard-coded output directory, the attacker may pre-create symboli ...[truncated 1971 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace the absolute path with a project-relative default or a caller-supplied command-line argument.
  2. Create the output directory explicitly with pathlib.Path.mkdir(parents=True, exist_ok=True).
  3. Resolve the requested output directory and verify that it remains beneath an approved workspace.
  4. Before writing each chart, reject symbolic-link destinations and unexpected non-regular files.
  5. Do not overwrite existing files by default. Require an explicit --overwrite option, generate versioned names, or use an atomic safe-write strategy.
  6. Run the chart generator under a minimally privileged account.
  7. Report the final output path clearly so users can verify where artifacts were written.

Example hardened approach:

python
import argparse
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parents[1]
DEFAULT_OUTPUT = PROJECT_ROOT / "charts"

parser = argparse.ArgumentParser()
parser.add_argument("--output-dir", type=Path, default=DEFAULT_OUTPUT)
parser.add_argument("--overwrite", action="store_true")
args = parser.parse_args()

output_dir = args.output_dir.expanduser().resolve()
approved_root = PROJECT_ROOT.resolve()

if output_dir != approved_root and approved_root not in output_dir.parents:
    raise ValueError("Output directory must remain inside the project workspace")

output_dir.mkdir(parents=True, exist_ok=True, mode=0o700)

target = output_dir / "fig01_overview.png"
if target.is_symlink():
    raise ValueError("Symbolic-link output targets are not allowed")
if target.exists() and not args.overwrite:
    raise FileExistsError(f"Refusing to overwrite existing file: {target}")

plt.savefig(target, dpi=150, bbox_inches="tight")
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (5)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- 使用 `scripts/make_charts.py` 生成12张品牌绿色系的专业图表。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- 使用 `scripts/make_charts.py` 生成12张品牌绿色系的专业图表。

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest description and title specify a Chinese-language, Tmall-specific weekly report skill, and the instructions throughout the file assume Chinese output and Chinese font configuration. There is no indication that the user may opt into another language or that the language restriction is explicitly justified as a policy or compliance requirement.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code explicitly sets the matplotlib font family to 'Noto Sans CJK SC', and the entire script's user-facing titles/labels are written in Chinese. This enforces a specific language/locale presentation without offering opt-in or configurability, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The template title is entirely in Chinese, and the whole document is written as a fixed Chinese report format. There is no indication that the user can choose another language or that the Chinese-only locale is a documented, justified regional constraint, which can violate language/locale policy requirements.

Content

No source excerpt is available for this finding.