Back to skill

Security audit

Family Grocery List

Security checks for vulnerabilities and agentic risk

Overview

This grocery-list skill appears purpose-aligned, but it needs review because setup can write to a user-chosen local path and its shared-file access controls are weak.

Review before installing. Use only a dedicated, non-sensitive shared folder, avoid paths containing shell metacharacters, and do not rely on this skill for strong access control. Family members with filesystem access may be able to read or modify the underlying files directly, including membership and history data.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:46
Finding
Shell Command Injection Through an Unquoted User-Controlled Path<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 46-52 **Vulnerability Type**: OS command injection **Risk Level**: Critical ### Vulnerable Code Snippet ```markdown 1. Ask: "What shared path should I use for the family grocery data? (e.g. /Users/Shared/grocery)" 2. Create directory: `mkdir -p [path]` 3. Initialize files from `memory-template.md`: `config.json`, `users.md`, `list.md`, `history.md` 4. Write the current user to `users.md` as `admin` 5. Save path to OpenClaw memory as `family_grocery_path` 6. Confirm: "Setup complete. You are admin. Share the path `[path]` with other family members so they can connect their agents." ``` ### Technical Analysis The initialization procedure instructs the agent to substitute a user-provided path into the shell command `mkdir -p [path]`. It does not require shell avoidance, argument separation, quoting, escaping, path canonicalization, or rejection of shell metacharacters. If the agent follows the instruction by constructing a shell command, shell syntax embedded in the supplied path can be interpreted as an additional command rather than as part of a directory name. Quoting alone would remain fragile if implemented incorrectly; the safe approach is to avoid invoking a shell entirely. ### Attack Path 1. An attacker initiates the first-time setup flow. 2. The skill asks the attacker to provide a shared path. 3. The attacker supplies a path containing shell control syntax, such as a command separator followed by an attacker-selected command. 4. The agent substitutes that value into `mkdir -p [path]`. 5. A shell interprets the injected syntax and executes the additional command with the agent process's privileges. ### Impact Assessment Successful exploitation can provide arbitrary command execution under the account running the agent. Depending on that account's permissions, an attacker could read or modify local files, access credentials available to the process, alter application state, i ...[truncated 103 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not construct or execute a shell command for directory creation. - Use a filesystem API that receives the destination path as one indivisible argument. - Canonicalize the requested path before use and display the resolved path for confirmation. - Restrict storage to a dedicated, application-owned base directory. - Reject paths containing null bytes, control characters, or invalid platform-specific components. - Verify that the resolved path remains beneath the approved base directory. - Add tests covering command separators, substitutions, quoting characters, newlines, and traversal sequences. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
SKILL.md:46
Finding
Unrestricted Filesystem Destination Enables Arbitrary File Creation or Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 46-52; `memory-template.md`, lines 1-35 **Vulnerability Type**: Unrestricted filesystem write and unsafe initialization **Risk Level**: High ### Vulnerable Code Snippet ```markdown ## Admin Init Flow Only runs when no shared path is in OpenClaw memory. 1. Ask: "What shared path should I use for the family grocery data? (e.g. /Users/Shared/grocery)" 2. Create directory: `mkdir -p [path]` 3. Initialize files from `memory-template.md`: `config.json`, `users.md`, `list.md`, `history.md` 4. Write the current user to `users.md` as `admin` 5. Save path to OpenClaw memory as `family_grocery_path` 6. Confirm: "Setup complete. You are admin. Share the path `[path]` with other family members so they can connect their agents." ``` The files initialized at that destination include: ```markdown ## config.json ```json { "primary_store": "", "stores": [], "fallback_order": [], "category_store_map": {} } ``` ## users.md ```markdown # Family Members | Name | Role | Added | |------|------|-------| ``` ``` ### Technical Analysis The setup flow permits the user to select an arbitrary filesystem path and then creates or initializes predictable filenames at that location. The instructions define no approved root, canonical-path containment check, symlink defense, ownership verification, existing-file check, or exclusive creation requirement. Consequently, the stated rule that the skill does not write outside `[shared-path]` is not an effective security boundary: the requesting user controls what `[shared-path]` means. Existing files named `config.json`, `users.md`, `list.md`, or `history.md` may be replaced or corrupted if initialization is implemented as an ordinary write. Symbolic links or path redirections may also cause writes to reach targets outside the apparent directory. ### Attack Path 1. An attacker reaches first-time initialization. 2. The attacker chooses a sensitive writable d ...[truncated 728 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Store all skill data beneath a fixed, application-owned directory rather than an unrestricted user-selected path. - Resolve the canonical destination and verify that it is a descendant of the approved storage root. - Reject symbolic links in every path component and verify the final target immediately before writing. - Create files atomically with exclusive-create semantics so existing files are never silently replaced. - Refuse initialization in a nonempty directory unless a validated migration process is explicitly selected. - Set restrictive directory and file permissions appropriate to the intended users. - Verify ownership before every write and use file handles resistant to time-of-check/time-of-use races. - Back up validated existing data before any migration or format conversion. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
SKILL.md:29
Finding
Mutable Name-Based Identity Allows User Impersonation and Unsafe Administrator Bootstrap<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 29-43 and 46-51; `user-management.md`, lines 3-21; `memory-template.md`, lines 39-51 **Vulnerability Type**: Authentication bypass and administrator impersonation **Risk Level**: High ### Vulnerable Code Snippet ```markdown ### Step 1 — Resolve user identity 1. Ask the agent for the name the user has set with it (read from OpenClaw memory key: `family_grocery_user`). 2. If no name is stored → deny: "No name found on this agent. Ask your admin to configure your agent with your name." Stop. ### Step 2 — Resolve shared path 1. Read shared path from OpenClaw memory (key: `family_grocery_path`). 2. If not found → this is a **first-time setup**. Go to **Admin Init Flow** below. ### Step 3 — Load config and verify access 1. Read `[shared-path]/config.json` and `[shared-path]/users.md`. 2. Look up the username (from Step 1) in `users.md`. 3. If not found → deny: "`[name]` is not on the family list. Ask your admin to add you." 4. If found → proceed. Note whether user is `admin` or `member`. ``` The bootstrap procedure further states: ```markdown 1. Ask: "What shared path should I use for the family grocery data? (e.g. /Users/Shared/grocery)" 2. Create directory: `mkdir -p [path]` 3. Initialize files from `memory-template.md`: `config.json`, `users.md`, `list.md`, `history.md` 4. Write the current user to `users.md` as `admin` 5. Save path to OpenClaw memory as `family_grocery_path` ``` The identity model is explicitly described as: ```markdown The first user who runs setup becomes the admin. There is one admin. ``` ### Technical Analysis Authentication is reduced to comparing a mutable name string from per-agent memory against a Markdown table. A name is not a security credential and does not prove control of an authenticated account. The design specifies no immutable principal identifier, password, cryptographic token, signed invitation, administrator approval, or binding between an Open ...[truncated 1893 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Bind authorization to an authenticated, immutable user identifier supplied by a trusted identity provider. - Do not use display names or mutable memory values as authentication credentials. - Require signed, single-use, expiring invitations when enrolling a new member agent. - Bind each invitation to a specific user identity and intended family group. - Require explicit approval by an existing administrator before activating a new member. - Protect administrator enrollment with a separate setup secret or verified ownership process. - Record enrollment and role changes in an integrity-protected audit log. - Support revocation of device or agent credentials without relying solely on deleting a display name. - Treat missing local memory as an unconfigured client, not as proof that the caller may become an administrator. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
SKILL.md:17
Finding
Authorization Database Resides in the Shared Data Directory Without Integrity Protection<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 17-22 and 38-43; `user-management.md`, lines 24-58 **Vulnerability Type**: Authorization-state tampering and role escalation **Risk Level**: High ### Vulnerable Code Snippet ```markdown Shared data lives in a user-configured local path accessible to all family members. See `memory-template.md` for file templates. ```text [shared-path]/ ├── config.json # Stores, primary store, fallback order, category→store map ├── users.md # Family members and roles (admin/member) ├── list.md # Current grocery list, grouped by store └── history.md # Log of all adds, removes, and merges ``` ``` Authorization is then derived directly from that shared file: ```markdown ### Step 3 — Load config and verify access 1. Read `[shared-path]/config.json` and `[shared-path]/users.md`. 2. Look up the username (from Step 1) in `users.md`. 3. If not found → deny: "`[name]` is not on the family list. Ask your admin to add you." 4. If found → proceed. Note whether user is `admin` or `member`. ``` The role-bearing format is: ```markdown | Name | Role | Added | |------|------|-------| | Abhishek | admin | 2026-03-01 | | Nita | member | 2026-03-02 | | Arjun | member | 2026-03-10 | ``` ### Technical Analysis The design places `users.md`, which acts as the authorization database, in the same shared directory used by family members for collaborative data. No operating-system access-control requirements, trusted ownership model, integrity signature, authenticated update mechanism, file locking, or tamper detection are specified. If a member has direct write access to the shared directory—as is commonly required for collaboratively modifying `list.md`, `history.md`, and `config.json`—that member may also be able to edit `users.md`. Because the skill reloads this file and trusts its role field, changing `member` to `admin` can directly elevate privileges. The documented user-removal process only delet ...[truncated 1501 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Move authorization data out of the member-writable shared directory. - Store roles in an administrator-owned database or service with authenticated access-control enforcement. - If local storage is required, apply operating-system ACLs so ordinary members can modify grocery data but cannot modify identity or role records. - Authenticate every role-management update and protect authorization records with integrity verification. - Use atomic updates and file locking to prevent races and partial writes. - Separate authorization, configuration, grocery-list, and audit-log permissions according to least privilege. - On user removal, revoke the person's underlying filesystem, device, token, or service-level credentials. - Protect audit history from modification by ordinary members so unauthorized role changes remain detectable. - Validate that exactly one authorized administrator exists and reject malformed or duplicate role entries. ]]>
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 Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill instructs the agent to create directories and initialize files on the local filesystem during first-time setup, but it provides no explicit user-confirmation or safety checks around path selection, overwrite behavior, or existing content. Because the path is user-provided and then persisted for later use, this creates a real risk of unintended filesystem modification, especially if the path is mistyped, points to a sensitive location, or already contains unrelated files.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
Never cache across sessions. Always re-read `config.json` and `users.md` at startup to pick up changes made by other family members.

### 2. Identity is resolved from OpenClaw memory
- Never ask the user for their name — always read it from the agent's OpenClaw memory. If absent, deny access.
- Never ask for the shared path if it's in memory.
- Save both on first encounter so they're never asked again.
- Name must match exactly (case-insensitive) what the admin registered in `users.md`.
Confidence
80% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The trigger set includes very broad everyday phrases such as "Show the list," which can easily match ordinary conversation outside a clear grocery-management intent. In an always-on or loosely scoped agent environment, this can cause unintended disclosure of the family grocery list and store/address details or trigger actions in the wrong context.

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The skill documentation introduces persistent store-configuration administration features such as setting a primary store, fallback order, and category-to-store mappings, which go beyond the stated grocery-list scope. Expanding capabilities beyond the manifest increases the attack surface and can enable unauthorized or unexpected configuration changes if the surrounding authorization and review mechanisms are weaker than users expect.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The setup flow performs persistent side effects by creating directories/files and automatically assigning the first user as admin, but it does not require an explicit confirmation step or clearly warn the user that these changes are durable and security-relevant. In a shared-path, multi-user skill, accidental initialization could let the wrong person permanently claim admin control or modify a shared data location without informed consent.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The removal workflow immediately deletes a user's entry after a trigger phrase, without an explicit confirmation or warning that access will be revoked. This increases the chance of accidental or socially engineered user removal in a shared family system, causing unintended denial of access and administrative mistakes.

Intent-Code Divergence

Low
Confidence
95% confidence
Finding
L61 states the skill 'will not ask' for the user name and that the key must already be set before first use. But L68 says that when connecting as a member, the skill saves the path, 'asks for username if not already stored,' and then verifies it against users.md. These instructions describe conflicting runtime behavior.

Static analysis

No suspicious patterns detected.