Back to skill

Security audit

Apo Cli

Security checks for vulnerabilities and agentic risk

Overview

This looks like a real apohealth.de shopping helper, but it needs Review because it can change a health-related shopping cart and stores session data locally without strong protection.

Review before installing. Use it only for deliberate apohealth.de shopping tasks, avoid invoking it for general medical advice, confirm any cart-clearing or checkout handoff yourself, and prefer installing a pinned reviewed revision rather than the README's mutable git command. Be aware that cart cookies and tokens may be written locally in plaintext.

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

T08 · Insecure Dependencies

Warning
Location
README.md:17
Finding
Unpinned Installation from a Mutable Git Repository<![CDATA[ ## Vulnerability Details **File Location**: `README.md:17` **Vulnerability Type**: Untrusted and unpinned source dependency **Risk Level**: Medium ### Vulnerable Code ```bash uv tool install git+https://github.com/Lars147/apo-cli ``` ### Technical Analysis The documented installation command downloads and builds code from the current default branch of a personal GitHub repository. It does not pin the source to a reviewed commit SHA, signed release, immutable package version, or verified artifact hash. Consequently, the code installed by a user can differ from the code examined during this audit. If the repository, maintainer account, or publishing workflow is compromised, the mutable branch can be changed to contain malicious package source or build configuration. The installation process invokes the package build backend, and the installed CLI will subsequently run with the privileges of the user who invokes it. The audited local `pyproject.toml` uses Hatchling and does not itself contain a malicious build hook. The risk arises because the documented command may retrieve a future, unaudited version of the repository. ### Attack Path 1. An attacker compromises the referenced GitHub repository, its maintainer account, or an authorized publishing credential. 2. The attacker modifies the repository's default branch to include malicious package code or build behavior. 3. A user follows the Quick Start command in `README.md`. 4. `uv` retrieves the current mutable branch rather than the revision audited here. 5. The retrieved package is built and installed. 6. Attacker-controlled code executes during an affected installation phase or when the user invokes the installed `apo` command. ### Impact Assessment Successful exploitation could execute arbitrary code with the privileges of the user installing or invoking the package. Depending on those privileges, this could expose that user's files, credentials, environment variables, network access, and ...[truncated 204 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin VCS installations to a fully reviewed commit SHA: ```bash uv tool install "git+https://github.com/Lars147/apo-cli@REVIEWED_FULL_COMMIT_SHA" ``` 2. Prefer publishing immutable, versioned releases through a trusted package registry. 3. Publish and verify cryptographic hashes for release artifacts. 4. Protect the source repository with multi-factor authentication, branch protection, mandatory review, and signed commits or tags. 5. Use automated dependency and release-pipeline scanning. 6. Update the documentation to explain that installation from an unpinned branch is not reproducible and should not be used in security-sensitive environments. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
apo_cli.py:76
Finding
Session Cookies and Cart Tokens Stored in Plaintext Without Explicit Permission Hardening<![CDATA[ ## Vulnerability Details **File Locations**: `apo_cli.py:31-32`, `apo_cli.py:76-79`, and `apo_cli.py:95-98` **Vulnerability Type**: Insecure storage of session material **Risk Level**: Low ### Vulnerable Code ```python COOKIES_FILE = SCRIPT_DIR / "apo_cookies.json" CART_FILE = SCRIPT_DIR / "apo_cart.json" ``` ```python def save_cookies(cookies: dict[str, str]): """Save cookies to JSON file.""" with open(COOKIES_FILE, "w", encoding="utf-8") as f: json.dump(cookies, f, ensure_ascii=False, indent=2) ``` ```python def save_cart_token(token: str): """Save cart token to file.""" with open(CART_FILE, "w", encoding="utf-8") as f: json.dump({"token": token}, f) ``` ### Technical Analysis The application persists HTTP cookies and a Shopify cart token as plaintext JSON files beside the script. It does not explicitly create these files with owner-only permissions or verify and tighten the permissions of existing files. Their effective access controls therefore depend on the operating system, process umask, installation directory, and any pre-existing file permissions. Cookies and cart tokens are bearer-style session material. A local process or user that can read these files may be able to reproduce the associated session state. The current implementation does not provide customer login or payment processing, so the directly demonstrated exposure is limited to the anonymous shopping-cart session. Saving mutable state beside installed application code also mixes application data with package files and may create unsafe ownership or sharing behavior in multi-user installations. ### Attack Path 1. A user runs the CLI and communicates with `apohealth.de`. 2. The application receives cookies and a cart token associated with the user's anonymous cart session. 3. `save_cookies` and `save_cart_token` write those values to plaintext JSON files. 4. The files are created or retained with permissions that allow another local user or ...[truncated 948 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store state in a per-user application-data directory rather than beside the script, such as an appropriate platform-specific configuration or state directory. 2. Create new state files with owner-only permissions, equivalent to `0600` on POSIX systems. 3. Check existing file permissions before use and tighten or reject files accessible by other users. 4. Use atomic file creation and replacement to reduce race conditions. 5. Avoid following symbolic links when creating sensitive state files where the operating system provides suitable controls. 6. Persist only cookies required for anonymous cart operation and remove obsolete session material promptly. 7. Provide a command to securely clear local session state. 8. If authenticated sessions are added in the future, use an operating-system credential store or keyring rather than plaintext JSON. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (11)

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The file describes add/update/clear cart operations but provides no user-facing warning that these actions modify live session/account state. In an agent skill, this omission is dangerous because an implementer may let natural-language requests trigger unintended cart mutations against a real pharmacy storefront, leading to unauthorized or surprising changes.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
Documenting a cart clear endpoint without any warning or confirmation guidance creates a real safety risk for an agentic CLI, because an implementation may expose a destructive action that wipes user session state with a single call. In this pharmacy context, clearing a cart could remove carefully selected health products and cause user harm or confusion, even if it is not a system-compromise issue.

Intent-Code Divergence

Medium
Confidence
84% confidence
Finding
The documentation frames checkout/purchase flows as unsuitable for the CLI at L258-L260, but later provides concrete session handling notes and a working `addToCart` implementation that performs purchase-adjacent state changes. While cart management is separately discussed, the guidance under 'Nicht empfohlen' conflicts with the inclusion of code that operationalizes shopping actions.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill declares executable behavior with detected file read, file write, and network capabilities but does not declare any tool scope or permission boundaries. That makes the skill harder to sandbox and review, and can allow broader-than-expected access if the runtime grants default capabilities to skills without explicit restrictions.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger conditions are broad and include generic terms like pharmacy, medication, and health products, which can cause the skill to activate in contexts where the user did not intend to shop or disclose product interests. In a health-related domain, unintended invocation increases privacy and safety risk because the agent may steer sensitive conversations into commerce workflows without clear consent.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The skill says purchases must never be completed, but the documented interface includes a checkout command that opens the browser for checkout. This creates a policy/implementation mismatch that can lead an agent or user to invoke a checkout-capable path despite the stated safety rule, especially if downstream code does not hard-block that action.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The HTTP headers hard-code `Accept-Language: de-DE,de;q=0.9`, which imposes a specific language/locale preference on all requests. There is no visible user opt-in, configuration option, or comment explaining why a German locale is required, which fits the language/locale policy violation category.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The manifest describes searching products, browsing categories, viewing details, and managing a cart on apohealth.de. In addition to those web interactions, the code invokes `webbrowser.open(...)`, which crosses from remote storefront operations into controlling a local application on the user's machine.

Missing User Warnings

Low
Confidence
84% confidence
Finding
This markdown file documents operations that can affect user data or privacy: checkout opens a browser with the user's cart, and `apo cart clear` removes cart contents. The README explains how to use these commands but does not include any user warning about opening an external website, transmitting cart data, or clearing cart contents.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The recommended HTTP headers explicitly set `Accept-Language: de-DE`, which forces a specific locale in the skill guidance. This is a natural-language policy issue unless the skill offers user choice or clearly documents and justifies the locale restriction.

Natural-Language Policy Violations

Low
Confidence
75% confidence
Finding
The trigger specification explicitly keys on German-specific terms such as "Apotheke" and "Medikament" alongside site-specific shopping behavior, but does not explain whether the skill is intended only for German-language or Germany-specific pharmacy use. Without a documented opt-in or justified locale restriction, this can create a natural-language locale policy concern.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
RESEARCH.md:175