Back to skill

Security audit

Vitavault

Security checks for vulnerabilities and agentic risk

Overview

This skill has a coherent health-sync purpose, but its setup can expose sensitive health data through an unsafe public webhook and persistent host changes.

Only install after reviewing the setup carefully. Do not let an agent automatically publish this webhook or install the systemd service; require a strong token, localhost binding by default, HTTPS through infrastructure you trust, private file permissions, request limits, date validation, retention/deletion controls, and separate trusted credentials for any cloud API querying.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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 (6)

T06 · System Persistence

Error
Location
SKILL.md:96
Finding
Privileged System-Wide Persistence Through a Systemd Service<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:96-120` **Vulnerability Type**: `T06: System Persistence` **Risk Level**: High ### Vulnerable Code ```bash ### Step 6: Make it persistent (recommended) The webhook should survive reboots. Create a systemd service: cat > /tmp/vitavault-webhook.service << 'EOF' [Unit] Description=VitaVault Webhook Receiver After=network.target [Service] Type=simple User=$USER Environment=VITAVAULT_SYNC_TOKEN=<TOKEN> ExecStart=/usr/bin/python3 /path/to/skills/vitavault/scripts/webhook.py --host 127.0.0.1 --port 8787 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF # Adjust paths and token, then: sudo cp /tmp/vitavault-webhook.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now vitavault-webhook ``` ### Technical Analysis The setup instructions direct the Agent to use `sudo` to copy a service definition into `/etc/systemd/system/` and enable it at boot. This creates cross-session, reboot-persistent execution of the Python script. Continuous webhook operation is relevant to automatic health synchronization, but a root-authorized, system-wide service is not the minimum privilege necessary. An on-demand process or per-user service could provide the same functionality without modifying global startup configuration. The configured executable is also a Python script under a potentially mutable Skill installation path. If that script is replaced after service installation, the replacement code will run automatically under the configured service account. The service definition provides no meaningful systemd sandboxing or write restrictions. ### Attack Path 1. A user asks the Agent to configure VitaVault synchronization. 2. The Agent creates the service definition in `/tmp`. 3. The Agent uses `sudo` to install it into the system-wide systemd directory. 4. The service is enabled and starts automatically after subsequent reboots. 5. If the configured script path ...[truncated 585 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Require explicit, informed user approval before creating any persistent service. - Prefer a per-user systemd unit under `~/.config/systemd/user/` rather than a system-wide service. - Run the receiver on demand where continuous synchronization is unnecessary. - Point `ExecStart` to an immutable, administrator-controlled installation path. - Add systemd hardening directives such as: - `NoNewPrivileges=true` - `PrivateTmp=true` - `ProtectSystem=strict` - `ProtectHome=read-only` - `ReadWritePaths=%h/vitavault/data` - `RestrictAddressFamilies=AF_INET AF_INET6` - Load secrets through systemd credentials or a permission-restricted environment file. - Document commands to stop, disable, and remove the service. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:24
Finding
Setup Failure Can Publish an Unauthenticated Health-Data Webhook<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:24-35`; `scripts/webhook.py:40-44, 96-102` **Vulnerability Type**: `T09: Insecure Skill Coding Practices` **Risk Level**: Critical ### Vulnerable Code ```bash # Generate a secure random token python3 -c "import secrets; print(secrets.token_hex(32))" > ~/.config/vitavault/sync-token mkdir -p ~/.config/vitavault TOKEN=$(cat ~/.config/vitavault/sync-token) echo "Token: $TOKEN" ``` ```bash VITAVAULT_SYNC_TOKEN="$TOKEN" nohup python3 scripts/webhook.py --host 0.0.0.0 --port 8787 > /tmp/vitavault-webhook.log 2>&1 & ``` The receiver explicitly fails open when no token is available: ```python token = getattr(self.server, "sync_token", "") if token: auth = self.headers.get("Authorization", "") if auth != f"Bearer {token}": self._respond(401, {"success": False, "error": "unauthorized"}) return ``` ```python token = os.environ.get("VITAVAULT_SYNC_TOKEN", "").strip() DATA_DIR.mkdir(parents=True, exist_ok=True) srv = ThreadedServer((args.host, args.port), Handler) srv.sync_token = token auth_status = "AUTH ENABLED" if token else "NO AUTH (open)" print(f"VitaVault webhook on http://{args.host}:{args.port} [{auth_status}]") ``` ### Technical Analysis Shell redirection occurs before command execution. On a fresh system where `~/.config/vitavault` does not exist, the first command cannot create `sync-token` because its parent directory has not yet been created. The instructions do not enable shell fail-fast behavior or verify that token generation succeeded. As a result, `TOKEN` may be empty. The webhook treats an empty token as a valid configuration that disables authentication. The setup then binds the receiver to all network interfaces and instructs the Agent to publish it through Tailscale Funnel, Cloudflare Tunnel, nginx/Caddy, or ngrok. This combines a deterministic setup-order defect with an authentication fail-open design. ### Attack Path 1. The setup is run on a host wit ...[truncated 1059 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Create the configuration directory before redirecting output: ```bash set -euo pipefail install -d -m 700 "$HOME/.config/vitavault" umask 077 python3 -c 'import secrets; print(secrets.token_hex(32))' \ > "$HOME/.config/vitavault/sync-token" TOKEN="$(cat "$HOME/.config/vitavault/sync-token")" test -n "$TOKEN" ``` - Make the webhook refuse startup when the token is absent or too short. - Permit unauthenticated operation only behind an explicit development flag and only on loopback. - Bind to `127.0.0.1` by default. - Verify authentication through the public tunnel before reporting setup as complete. - Avoid printing the complete token to logs or terminal history unnecessarily. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/webhook.py:17
Finding
Client-Controlled Date Enables Arbitrary File Path Construction<![CDATA[ ## Vulnerability Details **File Location**: `scripts/webhook.py:17-32` **Vulnerability Type**: `T09: Insecure Skill Coding Practices` **Risk Level**: High ### Vulnerable Code ```python def save_snapshot(payload: dict) -> Path: DATA_DIR.mkdir(parents=True, exist_ok=True) ts = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H-%M-%SZ") date = payload.get("date", datetime.now(timezone.utc).strftime("%Y-%m-%d")) name = f"{date}_{ts}.json" dest = DATA_DIR / name with open(dest, "w") as f: json.dump(payload, f, indent=2) f.write("\n") if LATEST.exists() or LATEST.is_symlink(): LATEST.unlink() try: LATEST.symlink_to(dest.name) except OSError: shutil.copy2(dest, LATEST) return dest ``` ### Technical Analysis The request payload's `date` field is inserted directly into a filesystem path without parsing, normalization, or validation. `pathlib` discards the left operand when the right operand is absolute. Directory separators and traversal components are also not rejected. The `.json` suffix and timestamp limit the exact target filename, but they do not ensure that the write remains inside `~/vitavault/data`. The process writes attacker-controlled JSON content to any reachable constructed path for which the service account has permission. The behavior is remotely reachable through the POST handler and becomes unauthenticated if the token is missing. ### Attack Path 1. An attacker obtains a valid token, or reaches a receiver running without authentication. 2. The attacker submits a JSON object whose `date` contains an absolute path or path components. 3. The server concatenates that value with the timestamp and `.json` suffix. 4. `DATA_DIR / name` resolves to an attacker-influenced location outside the intended directory. 5. The service writes the submitted JSON using the receiver account's filesystem privileges. 6. `latest.json` is then updated to reference or copy the resulting ...[truncated 518 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Parse the supplied date using a strict format and regenerate the filename from the parsed value: ```python raw_date = payload.get("date") try: parsed_date = datetime.strptime(raw_date, "%Y-%m-%d") except (TypeError, ValueError): raise ValueError("date must use YYYY-MM-DD") date = parsed_date.strftime("%Y-%m-%d") ``` - Reject `/`, `\`, NUL characters, and traversal components. - Resolve the destination and verify its parent remains the intended directory: ```python dest = (DATA_DIR / f"{date}_{ts}.json").resolve() if dest.parent != DATA_DIR.resolve(): raise ValueError("invalid destination") ``` - Prefer a server-generated UUID or timestamp as the complete filename. - Write through a securely created temporary file and atomically rename it. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/webhook.py:47
Finding
Unbounded Request Processing and Snapshot Retention Permit Denial of Service<![CDATA[ ## Vulnerability Details **File Location**: `scripts/webhook.py:47-60, 89-90` **Vulnerability Type**: `T09: Insecure Skill Coding Practices` **Risk Level**: High ### Vulnerable Code ```python try: length = int(self.headers.get("Content-Length", "0")) except ValueError: self._respond(400, {"success": False, "error": "bad-length"}) return try: payload = json.loads(self.rfile.read(length).decode()) except Exception: self._respond(400, {"success": False, "error": "invalid-json"}) return if not isinstance(payload, dict): self._respond(400, {"success": False, "error": "must-be-object"}) return ``` ```python class ThreadedServer(ThreadingMixIn, HTTPServer): daemon_threads = True ``` Each accepted request also creates a new permanent file: ```python dest = DATA_DIR / name with open(dest, "w") as f: json.dump(payload, f, indent=2) f.write("\n") ``` ### Technical Analysis The server trusts the client-provided `Content-Length` without enforcing an upper bound. It buffers the complete body in memory and then parses it as JSON. The threaded server has no explicit worker limit, rate limit, read timeout, or connection quota. Every accepted payload is stored in a new timestamped file, and there is no retention period, disk quota, or duplicate suppression. Authentication does not prevent abuse by a token holder, and the setup defect can make the endpoint publicly unauthenticated. ### Attack Path 1. An attacker reaches the webhook endpoint. 2. The attacker opens many concurrent connections or repeatedly sends large JSON bodies. 3. The server creates a thread for each active request. 4. Each thread buffers and parses its request body. 5. Accepted payloads create permanent snapshot files. 6. Memory, CPU, thread capacity, file-system inodes, or disk space is exhausted. 7. The receiver or host becomes unavailable. ### Impact Assessment A remote attacker can deny service to the webhook and potentially degrade other pr ...[truncated 208 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Enforce a conservative maximum request size before reading the body. - Reject absent, negative, nonnumeric, or excessive `Content-Length` values. - Configure socket read and write timeouts. - Limit concurrent workers with a bounded thread pool. - Apply per-source and global rate limits at the reverse proxy. - Validate the expected health-data schema before persisting a payload. - Implement snapshot retention, maximum storage quotas, and duplicate suppression. - Monitor disk usage and reject writes before free space becomes critically low. - Configure equivalent body-size and rate restrictions in nginx, Caddy, Cloudflare, or other public ingress layers. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/query.py:21
Finding
Bearer Token Can Be Sent to an Arbitrary or Plaintext API Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/query.py:21-36` **Vulnerability Type**: `T09: Insecure Skill Coding Practices` **Risk Level**: High ### Vulnerable Code ```python API_URL = os.environ.get("VITAVAULT_API_URL", "") if not API_URL: print("Error: VITAVAULT_API_URL environment variable is required.", file=sys.stderr) print("Set it to your private VitaVault API endpoint.", file=sys.stderr) sys.exit(1) TOKEN = os.environ.get("VITAVAULT_SYNC_TOKEN", "") def api_get(path: str) -> dict: url = f"{API_URL}{path}" req = Request(url) req.add_header("User-Agent", "VitaVault-OpenClaw/1.0") if TOKEN: req.add_header("Authorization", f"Bearer {TOKEN}") try: with urlopen(req, timeout=15) as resp: return json.loads(resp.read()) ``` ### Technical Analysis `VITAVAULT_API_URL` is accepted without validating its scheme or destination. The query function unconditionally adds the bearer token whenever one is configured. Consequently, an `http://` URL transmits the credential without transport encryption, while an attacker-controlled HTTPS URL receives the token directly. The code performs GET requests for health information; it does not itself upload locally stored health snapshots. The confirmed sensitive network flow is disclosure of the bearer credential to the configured endpoint. Because `urllib` follows standard HTTP behavior, redirect handling should also be constrained and tested so credentials cannot cross trust boundaries unexpectedly. ### Attack Path 1. An attacker or configuration error changes `VITAVAULT_API_URL` to an untrusted or plaintext endpoint. 2. The user or Agent executes a documented query command. 3. `api_get()` constructs a request to that endpoint. 4. The script adds `Authorization: Bearer <token>`. 5. The remote endpoint—or a network observer for plaintext HTTP—captures the token. 6. The captured credential is used to submit forged health data or access any API ac ...[truncated 465 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Require `https://` and reject plaintext HTTP. - Parse the URL with `urllib.parse.urlsplit` and validate the scheme, hostname, port, and absence of embedded credentials. - Restrict endpoints to an explicit user-approved allowlist or pinned private hostname. - Do not forward authorization headers across redirects to different origins; preferably disable redirects or validate every redirect target. - Use separate least-privilege credentials for ingestion and querying. - Provide an explicit warning and confirmation when changing the trusted API origin. - Consider certificate or public-key pinning where the deployment model permits it. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:24
Finding
Health Records and Authentication Tokens Are Stored Without Enforced Restrictive Permissions<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:24-29, 101-110`; `scripts/webhook.py:17-26`; `scripts/import.py:16-18, 116-121` **Vulnerability Type**: `T09: Insecure Skill Coding Practices` **Risk Level**: Medium ### Vulnerable Code ```bash python3 -c "import secrets; print(secrets.token_hex(32))" > ~/.config/vitavault/sync-token mkdir -p ~/.config/vitavault TOKEN=$(cat ~/.config/vitavault/sync-token) echo "Token: $TOKEN" ``` The token is embedded directly in the systemd unit: ```ini [Service] Type=simple User=$USER Environment=VITAVAULT_SYNC_TOKEN=<TOKEN> ExecStart=/usr/bin/python3 /path/to/skills/vitavault/scripts/webhook.py --host 127.0.0.1 --port 8787 ``` Health data is created using process-default permissions: ```python DATA_DIR.mkdir(parents=True, exist_ok=True) ts = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H-%M-%SZ") date = payload.get("date", datetime.now(timezone.utc).strftime("%Y-%m-%d")) name = f"{date}_{ts}.json" dest = DATA_DIR / name with open(dest, "w") as f: json.dump(payload, f, indent=2) ``` The importer behaves similarly: ```python def ensure_dirs(): DATA_DIR.mkdir(parents=True, exist_ok=True) ``` ```python dest = DATA_DIR / f"{ts}.json" with open(dest, "w", encoding="utf-8") as f: json.dump(data, f, indent=2) ``` ### Technical Analysis Neither the shell instructions nor the Python scripts explicitly enforce private permissions on the token, health-data directories, or JSON snapshots. Security therefore depends on the invoking process's umask and preexisting directory modes. With a common `022` umask, newly created files are typically mode `0644` and directories mode `0755`, potentially allowing other local accounts to read sensitive medical information. The synchronization token is also placed directly in a service unit under `/etc/systemd/system`, where service definitions are commonly readable by unprivileged local users. The data schema includes highly sensitive information such as heart rat ...[truncated 910 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Set `umask 077` before creating any secret or health-data file. - Create directories with mode `0700` and files with mode `0600`. - Use `os.open()` with explicit modes or create secure temporary files followed by atomic replacement. - Correct permissions on existing installations during startup. - Do not embed the token directly in a systemd unit. - Store it in a dedicated `0600` environment file owned by the service user, or use systemd's credential mechanisms. - Avoid printing the complete token except when strictly necessary for one-time enrollment. - Document local retention, deletion, backup, and encryption expectations for medical data. - Consider encryption at rest where multiple users, backups, or shared storage are involved. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (26)

Tainted flow: 'req' from os.environ.get (line 31, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
if TOKEN:
        req.add_header("Authorization", f"Bearer {TOKEN}")
    try:
        with urlopen(req, timeout=15) as resp:
            return json.loads(resp.read())
    except HTTPError as e:
        body = e.read().decode()
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The description presents this skill as an integration layer for importing Apple Health data from an iPhone into an AI agent, with networking/setup features such as webhooks, token generation, and HTTPS exposure. The supplied code instead only loads a local JSON file from the user's home directory, aggregates previously imported health records, calculates metrics like steps, heart rate, sleep, weight, HRV, SpO2, calories, exercise, and simple weekly trends, then outputs a compact briefing. There is no network communication, no webhook creation, no authentication/token handling, no HTTPS tunneling or exposure, and no code interacting with an iPhone or Apple Health APIs. This is a material mismatch in primary purpose and claimed capabilities.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The code is purely a local filesystem import script. It parses JSON/CSV export files, optionally merges them with previously imported data, writes timestamped JSON files to a local directory, and updates a symlink. There is no network communication, no webhook provisioning, no authentication/token handling, no HTTPS tunneling/exposure, and no iOS-device integration. The declared description therefore materially overstates and misrepresents the skill's actual behavior and primary purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The code does not implement the setup/integration behavior described. It only performs read-only GET requests against a pre-existing VitaVault API using configured environment variables. There is no code for creating webhooks, generating tokens, exposing an HTTPS endpoint, pairing with an iPhone, or syncing Apple Health data directly from the device. The actual purpose is querying already-synced health data from a cloud API, which is materially narrower and different from the declared integration/setup functionality.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description emphasizes infrastructure and integration features: direct Apple Health sync to an AI agent, automatic webhook setup, token generation, and HTTPS exposure. The supplied code does none of these things. It only loads an existing local JSON file, parses health records, computes averages/min/max for metrics, summarizes sleep, and prints results in text or JSON. This is a materially different primary purpose. While it operates on VitaVault health data, it does not implement the advertised integration capabilities or any network/auth/setup behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The description overstates the implementation. The code does implement part of the declared theme—a webhook receiver for health data snapshots—but it does not provide several core advertised capabilities. There is no automatic setup, no token generation, no HTTPS support, no mechanism to expose the service publicly, and no forwarding or integration with an AI agent beyond local file storage. The primary behavior is a basic local HTTP ingestion endpoint that writes JSON files to disk, which is materially narrower than the declared end-to-end iOS integration.

Missing User Warnings

High
Confidence
97% confidence
Finding
The skill tells the agent to expose a health-data webhook publicly over HTTPS but does not prominently warn about the implications of opening inbound access to a service that receives sensitive medical data. Even with a token, public exposure increases the risk of credential leakage, endpoint probing, denial-of-service, and accidental disclosure through logs or misconfiguration.

Intent-Code Divergence

High
Confidence
97% confidence
Finding
The privacy statement says data flows only from the iPhone to the user's agent with no third-party storage, yet the setup recommends Cloudflare Tunnel and ngrok, and even Tailscale Funnel involves third-party infrastructure. This can mislead users about who can observe metadata or transport traffic and causes underestimation of privacy risk for sensitive health information.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill contains instructions to generate tokens, write files, start a network listener, and expose it externally, but it declares no explicit tool or permission scope. That mismatch increases the chance an agent will perform sensitive filesystem and network actions without clear user visibility or policy gating.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
## Agent Setup Guide (DO THIS WHEN USER SAYS "set up VitaVault")

When your user asks to set up VitaVault sync, follow these steps automatically. Don't ask the user to do the technical parts - handle it yourself and hand them the URL + token at the end.

### Step 1: Generate a sync token
Confidence
86% confidence
Finding
The instruction to perform the technical setup automatically and not ask the user removes an important consent checkpoint before privileged actions like file creation, background process launch, network exposure, and persistence. In a security-sensitive context involving health data, reducing user confirmation increases the chance of unsafe or surprising system modifications.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The generated sync token is treated as a simple setup value, but it is effectively a bearer credential authorizing submission of sensitive health data to the webhook. Failing to warn users about its sensitivity increases the chance it will be copied into insecure channels, shell history, logs, screenshots, or shared chats.

Session Persistence

Medium
Category
Rogue Agent
Content
```bash
# Generate a secure random token
python3 -c "import secrets; print(secrets.token_hex(32))" > ~/.config/vitavault/sync-token
mkdir -p ~/.config/vitavault
TOKEN=$(cat ~/.config/vitavault/sync-token)
echo "Token: $TOKEN"
```
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
### Step 2: Start the webhook

```bash
VITAVAULT_SYNC_TOKEN="$TOKEN" nohup python3 scripts/webhook.py --host 0.0.0.0 --port 8787 > /tmp/vitavault-webhook.log 2>&1 &
```

The webhook listens for health data POSTs and saves snapshots to `~/vitavault/data/`.
Confidence
88% confidence
Finding
Using nohup to launch the webhook in the background creates session persistence and leaves a long-running network-reachable process active after the initiating interaction ends. That is particularly risky here because the process handles sensitive health data and may be publicly exposed through a tunnel.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Check if Tailscale is available
tailscale status 2>/dev/null
# If yes, expose via Funnel:
sudo tailscale funnel --bg --set-path /vitavault http://127.0.0.1:8787
# Your URL will be: https://<your-tailscale-hostname>/vitavault
tailscale funnel status  # to see the URL
```
Confidence
90% confidence
Finding
The use of sudo for Tailscale Funnel asks the agent to perform privileged network configuration on the host. Privileged execution is dangerous because mistakes or abuse can modify trusted networking state and expose local services beyond the user's intended scope.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The instructions direct the agent to use sudo and host-level networking features to publish a local service externally, which exceeds the minimum scope needed for simple data import. Broad system administration actions materially increase attack surface and can alter host security posture in ways the user may not expect.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
Installing and enabling a persistent systemd service is a host-administration action that survives the current session and changes system state beyond transient data sync. In a skill context, this is risky because it normalizes persistence and background execution for code that handles sensitive health data and network ingress.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
WantedBy=multi-user.target
EOF
# Adjust paths and token, then:
sudo cp /tmp/vitavault-webhook.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now vitavault-webhook
```
Confidence
92% confidence
Finding
Copying a unit file into /etc/systemd/system with sudo is a privileged host modification that establishes trust for future execution. In a skill ecosystem, asking the agent to make such changes can be abused to plant persistent services or normalize elevated operations users did not explicitly review.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
EOF
# Adjust paths and token, then:
sudo cp /tmp/vitavault-webhook.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now vitavault-webhook
```
Confidence
92% confidence
Finding
Running systemctl daemon-reload with sudo applies privileged service configuration changes system-wide. This is not required for basic health-data analysis and unnecessarily expands the skill from application logic into system administration.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Adjust paths and token, then:
sudo cp /tmp/vitavault-webhook.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now vitavault-webhook
```

## Querying Health Data
Confidence
93% confidence
Finding
Enabling and starting the service with sudo creates persistent privileged execution at boot, which materially raises risk if the script is flawed, replaced, or later compromised. Combined with a public webhook and health-data handling, this enlarges both exposure duration and attack surface.

Session Persistence

Medium
Category
Rogue Agent
Content
# Adjust paths and token, then:
sudo cp /tmp/vitavault-webhook.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now vitavault-webhook
```

## Querying Health Data
Confidence
93% confidence
Finding
systemctl enable establishes reboot persistence, causing the service to continue running and accepting inbound traffic long after the setup interaction ends. Persistence is risky because it can outlive user awareness, preserve insecure configurations, and create a standing target handling sensitive data.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding
Suspicious Unicode normalization or mixed-script content

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The file documents a broad set of highly sensitive health data types, including heart rate, blood glucose, blood pressure, sleep, body metrics, and nutrition, but provides no privacy, consent, retention, or secure-handling guidance. In the context of a skill that syncs Apple Health data to an AI agent and auto-configures webhooks and HTTPS exposure, this omission increases the risk that implementers will collect, transmit, or store regulated health data insecurely or more broadly than intended.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This schema documents export of highly sensitive health, device, and source-application data, including sleep, heart rate, device identifiers, bundle identifiers, and metadata, but provides no privacy warning, consent guidance, data minimization guidance, or handling restrictions. In the context of a skill whose purpose is to sync Apple Health data directly to an AI agent and expose webhooks/HTTPS endpoints, omission of privacy and sharing warnings materially increases the risk of over-collection, inadvertent disclosure, and unsafe downstream processing of regulated or intimate personal data.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The skill metadata and docstring imply secure HTTPS exposure and token generation, but the implementation actually starts a plain HTTP server and only consumes a preexisting environment token. In this health-data context, that mismatch is security-relevant because operators may assume transport security and authentication setup exist when sensitive Apple Health data is in fact exposed over cleartext and potentially unauthenticated.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
Authentication is described as optional and the server binds to 0.0.0.0 by default, making the webhook openly reachable on all interfaces unless the operator manually sets a token. Because the endpoint ingests and stores health snapshots, an unauthenticated default permits arbitrary parties on the reachable network to inject fake medical data and collect information about service availability.

Static analysis

No suspicious patterns detected.