Back to skill

Security audit

garmin-nutrition

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed Garmin nutrition logger that writes local food records and can sync or delete Garmin food-log entries with user-directed commands.

Install only if you are comfortable letting the skill read cached Garmin tokens, store nutrition data locally, and upload or delete Garmin nutrition entries when you approve write commands. Use --no-garmin for local-only logging and prefer locked dependency installation if your environment supports it.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T08 · Insecure Dependencies

Warning
Location
scripts/garmin_nutrition.py:1
Finding
Runtime Dependency Resolution Without a Reviewed Lockfile or Integrity Enforcement<![CDATA[ ## Vulnerability Details **File Location**: `scripts/garmin_nutrition.py:1-4` **Vulnerability Type**: Supply-chain exposure through runtime dependency retrieval **Risk Level**: Medium ### Vulnerable Code ```python # /// script # requires-python = ">=3.10" # dependencies = ["garminconnect==0.3.11"] # /// ``` The documented commands in `SKILL.md`, including lines 51-55 and 97-117, execute this script through `uv run`: ```bash uv run {baseDir}/scripts/garmin_nutrition.py ... ``` ### Technical Analysis The script declares `garminconnect==0.3.11` as a PEP 723 inline dependency. The direct dependency is pinned to an exact version, which prevents ordinary version drift, but the project does not include a reviewed lockfile, package hashes, vendored dependencies, or another mechanism that authenticates the package artifacts and freezes the complete transitive dependency graph. When the documented `uv run` command is invoked in an environment where the required packages are not already available in a trusted cache, `uv` may resolve and download the package and its transitive dependencies from a configured package registry. Version pinning determines which direct package version is selected, but it does not independently guarantee that the registry, selected artifact, or transitive packages have not been compromised. This is particularly sensitive because the imported Garmin client runs in the same Python process as the skill. Dependency code therefore receives the same operating-system privileges and access to the same files as the skill, including the cached Garmin OAuth token directory at `~/.garminconnect/`. No evidence was found that the currently specified package is malicious. The finding concerns the absence of reproducible, integrity-enforced dependency installation controls. ### Attack Path 1. An attacker compromises the package registry, the selected `garminconnect` artifact, or one of its unresolved transitive dependencies. 2. A user or ag ...[truncated 1391 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Move dependency management into a standard reviewed project configuration such as `pyproject.toml`. 2. Generate and commit a lockfile that freezes the complete transitive dependency graph. 3. Execute installation and runtime commands in locked mode, failing if dependency resolution would modify the reviewed lockfile. For example: ```bash uv sync --locked uv run --locked scripts/garmin_nutrition.py ... ``` 4. Enforce artifact integrity using package hashes or an equivalent trusted artifact-verification mechanism. 5. Use a trusted, explicitly configured package index or an internally controlled package mirror. 6. Review changes to both direct and transitive dependencies before updating the lockfile. 7. Run dependency installation separately from normal skill execution so routine food-logging commands do not unexpectedly retrieve new executable code. 8. Execute the skill with least privilege and restrict access to `~/.garminconnect/` and nutrition data files to the owning user. 9. Consider using a dedicated virtual environment or container with narrowly scoped filesystem and network access. ]]>
Vulnerability Patterns
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (1)

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill clearly performs local file reads/writes and environment-variable reads, but the manifest does not declare corresponding permissions or capabilities. This creates a transparency and consent problem: an agent or user may invoke the skill without realizing it can access and modify local nutrition journals and configuration paths.

Static analysis

No suspicious patterns detected.