Back to skill

Security audit

apple-health-exercise-readiness

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to do what it says: it locally analyzes a user-provided Apple Health export for exercise readiness, with privacy and large-file handling cautions.

Install only if you are comfortable sharing Apple Health export-derived metrics with the agent session. Use exports you created yourself, avoid ZIP files from other people, and use --out only in a directory where you intend to store a health-data JSON report.

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
analyze.py:55
Finding

Unbounded ZIP Decompression and XML Tree Parsing

Content
View full analysis

Vulnerability Details

File Location: analyze.py, lines 55–70
Vulnerability Type: Uncontrolled resource consumption when processing untrusted archives
Risk Level: Medium

Vulnerable Code

python
def load_xml_root(zip_path: str) -> ET.Element:
    with zipfile.ZipFile(zip_path, "r") as zf:
        xml_name = next(
            (n for n in zf.namelist()
             if n.endswith("export.xml") and "export_cda" not in n),
            None,
        )
        if not xml_name:
            raise ValueError(
                "在 ZIP 中找不到 export.xml。"
                "请确认使用的是苹果健康官方导出文件(设置 → 健康数据 → 导出)。"
            )
        print(f"[解析] {xml_name} …", file=sys.stderr)
        with zf.open(xml_name) as f:
            return ET.parse(f).getroot()

Technical Analysis

The application treats a user-supplied ZIP archive as trusted input. It opens the matching export.xml entry and parses the complete decompressed document into an in-memory ElementTree without enforcing limits on:

  • The entry's uncompressed size
  • Its compression ratio
  • Total archive size or number of entries
  • XML nesting depth
  • XML element or health-record count
  • Processing time or memory consumption

A maliciously compressed archive can have a small on-disk size while expanding into an extremely large XML document. Furthermore, ET.parse(f).getroot() constructs the entire XML tree before metric collection begins. This substantially increases peak memory use compared with streaming parsing.

The XML parser does not provide an external-entity expansion path in this code, so this finding specifically concerns resource exhaustion rather than file disclosure.

Attack Path

  1. An attacker creates a ZIP archive containing an entry whose name ends with export.xml.
  2. The entry contains highly compressible or exceptionally large, structurally valid XML with many elements or deeply nested content.
  3. The attacker supplies the archive as an Apple Health export.
  4. The skill in ...[truncated 909 chars]
Remediation
View remediation

Remediation Suggestions

  1. Inspect the selected entry's ZipInfo before opening it and reject files whose uncompressed size exceeds a conservative, documented limit.
  2. Reject suspicious compression ratios by comparing file_size with compress_size, handling zero-byte compressed sizes safely.
  3. Limit the archive's entry count and aggregate declared uncompressed size.
  4. Replace full-tree parsing with xml.etree.ElementTree.iterparse() and clear each processed element immediately after extracting required fields.
  5. Track and cap the number of parsed records and, where feasible, XML nesting depth.
  6. Run parsing under explicit memory and execution-time limits in an isolated worker process.
  7. Catch ET.ParseError, OSError, MemoryError, and relevant decompression errors, then fail closed with a non-sensitive error message.
  8. Validate that the selected document has the expected Apple Health export structure before processing all records.
  9. Add regression tests using oversized entries, extreme compression ratios, excessive record counts, deeply nested XML, malformed XML, and truncated archives.

Example size validation should occur before zf.open(xml_name):

python
info = zf.getinfo(xml_name)

MAX_XML_SIZE = 512 * 1024 * 1024
MAX_COMPRESSION_RATIO = 100

if info.file_size > MAX_XML_SIZE:
    raise ValueError("The export XML exceeds the permitted size.")

compressed_size = max(info.compress_size, 1)
if info.file_size / compressed_size > MAX_COMPRESSION_RATIO:
    raise ValueError("The archive has a suspicious compression ratio.")

These checks should supplement, not replace, streaming XML parsing and operating-system resource limits.

Vulnerability Patterns
  • 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
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill instructs the agent to run a local Python script and also advertises an output mode that writes JSON results to a user-specified directory, but the manifest does not declare any tool scope or allowed-tools restrictions. This creates an undeclared file-write capability boundary: an agent may be induced to execute code and write files without explicit permission controls, reducing reviewability and increasing the chance of unsafe filesystem access.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The natural-language content of the skill, including its description, workflow, constraints, and output guidance, is entirely in Chinese. Under the policy, forcing a specific language without offering the user a language choice or documenting a justified locale constraint is a violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The module docstring specifies the skill’s behavior entirely in Chinese and states fixed Chinese output categories, indicating a language-specific interaction model. The file does not offer user opt-in, fallback language selection, or a documented region-specific justification, which is a natural-language locale policy concern under the stated rules.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The manifest describes reading current Apple Health data and analyzing exercise readiness, which implies local data processing and reporting. The optional --out path adds file-writing behavior by creating directories and saving a JSON report, which goes beyond the read/analyze behavior described in the manifest.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.