Back to skill

Security audit

Health Data

Security checks for vulnerabilities and agentic risk

Overview

This skill locally analyzes Apple Health exports and does not show hidden upload, persistence, or unrelated privileged behavior.

Install only if you are comfortable processing sensitive Apple Health data locally. Use exports from your own device, avoid untrusted ZIP files, prefer a new private output path for --out, and do not run the helper with elevated privileges.

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

T09 · Insecure Skill Coding Practices

Warning
Location
health-data.sh:17
Finding
Unsafe Output-File Overwrite Through Symbolic-Link Following<![CDATA[ ## Vulnerability Details **File Location**: `health-data.sh`, lines 17–28 and 211–213 **Vulnerability Type**: Unsafe file creation, destructive overwrite, and symbolic-link following **Risk Level**: Medium ### Vulnerable Code ```bash prepare_output_file() { local target="$1" local dir dir=$(dirname "$target") mkdir -p "$dir" local prev_umask prev_umask=$(umask) umask 0077 : > "$target" umask "$prev_umask" chmod 600 "$target" } ``` The prepared path is subsequently reopened and truncated: ```bash if [[ -n "$output_path" ]]; then prepare_output_file "$output_path" exec 3>"$output_path" sink_fd=3 close_sink=1 fi ``` The output path originates from the user-controlled `--out` argument: ```bash --out) shift [[ $# -gt 0 ]] || die "--out requires a file path" out_path="$1" shift ;; ``` ### Technical Analysis The `--out` destination is opened with shell redirection without checking whether it already exists or is a symbolic link. The first `: > "$target"` operation follows symbolic links and truncates the resolved target. The subsequent `chmod 600 "$target"` also follows the link and changes the target's permissions. Finally, `exec 3>"$output_path"` reopens and truncates the same target. The use of a restrictive `umask` and `chmod 600` protects newly created files from broad read access, but it does not make path resolution safe. There is also a time-of-check/time-of-use concern if separate checks were added without atomic creation. ### Attack Path 1. An attacker identifies an output path that a user or automated process will pass to `export-json --out`. 2. The attacker creates a symbolic link at that path pointing to another file writable by the victim process. 3. The victim runs the command with the attacker-controlled or predictable output path. 4. `prepare_output_file` follows the symbolic link, truncates the target, and changes its permissions to mode `600`. 5. The target is opened and truncated again befor ...[truncated 708 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Reject symbolic links and refuse to overwrite existing destinations by default. - Create the destination atomically with exclusive-creation and no-follow semantics, equivalent to `O_CREAT | O_EXCL | O_NOFOLLOW`. - Prefer a small helper in a language that exposes secure file-opening flags; shell redirection alone cannot reliably provide all required guarantees. - If overwrite support is necessary, require an explicit option and securely validate the destination immediately before opening it. - Avoid the current create–`chmod`–reopen sequence. Open the file once with mode `0600` and retain that descriptor for the entire write. - Validate that the destination directory is trusted and not writable by untrusted users. - Do not run the skill with elevated privileges. For environments where only Bash is available, `set -o noclobber` can reduce accidental overwrites, but it should not be treated as a complete substitute for atomic `O_NOFOLLOW` file creation. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
health-data.sh:86
Finding
Unbounded Decompression of ZIP Archive Member<![CDATA[ ## Vulnerability Details **File Location**: `health-data.sh`, lines 86–94 **Vulnerability Type**: Unbounded archive extraction and local resource exhaustion **Risk Level**: Medium ### Vulnerable Code ```bash elif [[ -f "$source" ]]; then local tmp tmp=$(mktemp) for member in export.xml apple_health_export/export.xml; do if unzip -p "$source" "$member" > "$tmp" 2>/dev/null; then HEALTH_EXPORT_CACHE="$tmp" HEALTH_EXPORT_TEMPFILE=1 return fi done rm -f "$tmp" die "zip '$source' does not contain export.xml" ``` ### Technical Analysis When a ZIP file is supplied, the script streams the selected `export.xml` member into a temporary file without imposing a maximum uncompressed size. ZIP compression can represent very large repetitive content with a comparatively small archive. Consequently, a malicious or unexpectedly large export can consume all available space on the temporary filesystem. The temporary filename itself is securely generated by `mktemp`, and the exit trap removes it after normal process termination. Those controls do not prevent disk exhaustion while extraction is in progress. Cleanup after failure also cannot eliminate disruption already caused to other processes sharing the filesystem. ### Attack Path 1. An attacker creates a ZIP archive containing `export.xml` or `apple_health_export/export.xml`. 2. The member has a very large uncompressed size or an extreme compression ratio. 3. The attacker convinces a user or automated workflow to process the archive with the skill. 4. `unzip -p` expands the member into the `mktemp` file without a size limit. 5. The temporary filesystem fills, causing this command and potentially unrelated local services to fail. The attack does not require path traversal because the script extracts only fixed member names; resource exhaustion occurs through the contents and size of the permitted member. ### Impact Assessment The primary impact is local denial of service t ...[truncated 427 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Inspect archive metadata before extraction and reject members whose declared uncompressed size exceeds a documented, configurable maximum. - Enforce a runtime byte limit while streaming the member so that falsified or unavailable metadata cannot bypass the check. - Check available space on the temporary filesystem before extraction, while retaining a safety margin for other processes. - Reject archives with suspicious compression ratios or malformed metadata. - Apply operating-system resource controls, filesystem quotas, or an isolated temporary directory with a strict size limit when processing untrusted archives. - Emit a clear error when a configured limit is exceeded and ensure the partial temporary file is removed. - Document the accepted maximum export size so users can intentionally adjust it for legitimate large Apple Health exports. ]]>
Vulnerability Patterns
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (3)

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill advertises shell-based functionality but does not declare any tool scope such as allowed-tools or permissions. That creates an authorization gap where an agent may invoke shell access more broadly than intended, which is especially risky here because the skill handles sensitive Apple Health data and performs local file processing.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The manifest description lists several specific triggers, but then adds "or other Apple Health record audits," which leaves the invocation boundary open-ended. That ambiguity can cause unintended activation for loosely related conversations about health records or audits without a clear scope or exclusion criteria.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
umask 0077
  : > "$target"
  umask "$prev_umask"
  chmod 600 "$target"
}

cleanup_export_cache() {
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Static analysis

No suspicious patterns detected.