Back to skill

Security audit

home-inventory

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent local home-inventory tool, but it includes an unsafe generated shell command and weak warnings around sensitive plaintext inventory exports.

Review before installing. The tool appears local and purpose-aligned, with no network behavior or hidden persistence found, but protect inventory.json and exported CSVs because they may reveal valuables, room locations, and serial numbers. Avoid copying the QR-generation shell command from box-manifest when item names or box IDs may contain punctuation or untrusted text.

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
scripts/inventory.py:396
Finding

Shell Command Injection in Generated QR Code Command

Content
View full analysis

Vulnerability Details

File Location: scripts/inventory.py, lines 396–400
Vulnerability Type: Shell command injection through unsafe command generation
Risk Level: Medium

Vulnerable Code

python
# QR-friendly compact summary (single line, pipe-delimited)
names = "|".join(i["name"] for i in box_items)
qr_data = f"BOX:{box_id}|N:{len(box_items)}|V:{total:.0f}|{names}"
print(f"\nQR data (compact):")
print(f"  {qr_data}")
print(f"\n  Tip: pipe this string into any QR code generator:")
print(f"  echo '{qr_data}' | qrencode -o {box_id}.png")

Technical Analysis

The generated shell command incorporates box_id and inventory item names without shell-safe escaping:

  • box_id originates from the positional box-manifest argument.
  • names contains item names previously supplied through the add command.
  • qr_data combines both values and is enclosed only in literal single quotes.
  • box_id is also inserted unquoted into the output filename.

A single quote in an item name can terminate the intended quoted string. Shell metacharacters or command substitutions in either value can then introduce additional commands when the displayed recommendation is copied into a shell. The Python application does not execute the command directly, but it explicitly presents the command as a usage recommendation, making copied execution a credible attack path.

Attack Path

  1. An attacker causes a crafted item name or box identifier containing shell syntax to be added to the inventory.

  2. The crafted item is assigned to the maliciously named box.

  3. A victim runs box-manifest for that box.

  4. The application generates a command resembling:

    bash
    echo 'ATTACKER_CONTROLLED_DATA' | qrencode -o ATTACKER_CONTROLLED_BOX.png
    
  5. The victim follows the displayed tip and copies the command into a shell.

  6. The shell interprets the injected syntax, executi ...[truncated 595 chars]

Remediation
View remediation

Remediation Suggestions

  • Avoid presenting executable shell commands assembled from untrusted inventory data.

  • Prefer generating the QR image directly through a Python library or a subprocess call that uses an argument list with shell=False.

  • If a shell command must be displayed, escape every dynamic shell argument with shlex.quote():

    python
    import shlex
    
    safe_data = shlex.quote(qr_data)
    safe_output = shlex.quote(f"{box_id}.png")
    print(f"  printf '%s' {safe_data} | qrencode -o {safe_output}")
    
  • Apply strict validation to box identifiers, such as ^[A-Za-z0-9_-]+$, and reject invalid identifiers.

  • Do not rely exclusively on validation for QR content because item names may legitimately contain punctuation; use context-appropriate shell escaping.

  • Add tests containing single quotes, command substitutions, semicolons, pipes, newlines, leading hyphens, and other shell-significant input.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/inventory.py:227
Finding

CSV Formula Injection in Inventory Export

Content
View full analysis

Vulnerability Details

File Location: scripts/inventory.py, lines 227–240
Vulnerability Type: CSV formula injection
Risk Level: Low

Vulnerable Code

python
def cmd_export_csv(args, data, db_path):
    output = args.output or "inventory_export.csv"
    fields = [
        "id", "name", "category", "room", "purchase_date",
        "estimated_value", "brand_model", "serial_number",
        "photo_path", "qr_label_id", "box_id", "notes",
    ]
    with open(output, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fields, extrasaction="ignore")
        writer.writeheader()
        for item in data["items"]:
            writer.writerow(item)
    print(f"Exported {len(data['items'])} item(s) to {output}")

Technical Analysis

Inventory fields controlled by users are written directly to CSV cells. The csv module correctly handles CSV delimiters and quoting, but CSV quoting does not prevent spreadsheet applications from interpreting cell contents as formulas.

Text fields beginning with characters such as =, +, -, or @ may be evaluated as formulas when the exported file is opened in spreadsheet software. Depending on the application and its security configuration, a malicious formula may create deceptive content, reference external resources, leak data through outbound requests, or invoke dangerous application-specific functionality.

Attack Path

  1. An attacker supplies a crafted value in an inventory text field such as the item name, notes, serial number, room, or brand/model.
  2. The value begins with a spreadsheet formula marker and is stored in inventory.json.
  3. A user runs export-csv.
  4. The application writes the malicious value to the CSV without neutralizing formula syntax.
  5. The user or an insurance recipient opens the exported file in formula-capable spreadsheet software.
  6. The spreadsheet interpret ...[truncated 767 chars]
Remediation
View remediation

Remediation Suggestions

  • Sanitize all textual values before writing them to CSV.

  • Treat cells beginning with =, +, -, or @ as potentially dangerous. Consider leading whitespace, tabs, carriage returns, and line feeds that could conceal a formula marker.

  • Prefix dangerous cells with an apostrophe or another spreadsheet-compatible neutralization character according to the intended spreadsheet ecosystem.

  • Apply the protection centrally to every exported string field:

    python
    def safe_csv_cell(value):
        if not isinstance(value, str):
            return value
        normalized = value.lstrip("\t\r\n ")
        if normalized.startswith(("=", "+", "-", "@")):
            return "'" + value
        return value
    
    for item in data["items"]:
        writer.writerow({
            key: safe_csv_cell(value)
            for key, value in item.items()
        })
    
  • Document that the export is designed to preserve text rather than executable spreadsheet formulas.

  • Add tests for formula-prefixed values, values with leading control characters, Unicode text, embedded delimiters, and multiline notes.

  • Where feasible, use a spreadsheet format or import workflow that explicitly marks untrusted inventory fields as text.

Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill advertises file read/write behavior through its documented commands and local JSON storage, but it does not declare any explicit tool scope such as permissions or allowed-tools. This weakens least-privilege boundaries and makes it harder for a host system or reviewer to understand and constrain filesystem access, increasing the chance of unintended file access or modification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill stores highly sensitive household inventory data locally, including item descriptions, serial numbers, locations, values, and notes, but provides no warning about the privacy and theft risk of keeping this data in plaintext JSON. If the file is exposed, it could aid burglary, identity misuse, fraudulent insurance claims, or leakage of personal financial information.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script persists a JSON database containing potentially sensitive information such as item names, room locations, serial numbers, notes, and values. Although the code performs the write directly, there is no user-facing warning or disclosure near the save operation that this personal household inventory data will be stored on disk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The export operation writes the full inventory, including serial numbers, room assignments, and notes, to a CSV file that may be easier to share or expose accidentally. The code prints only a success message after writing and does not warn users beforehand about the sensitivity of the exported data.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.