Back to skill

Security audit

water-shutoff-map

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent local water-shutoff registry, but it needs review because some real-world water-heater guidance omits important safety prerequisites and the local registry may store sensitive household details without hardened permissions.

Install only if you are comfortable storing household shutoff locations and optional contact details in a local JSON file. Treat the plumbing guidance as a checklist, not a substitute for manufacturer instructions or a plumber; for water-heater draining or gas-adjacent work, shut down the heater safely, let it cool, avoid scalding water, and stop if the procedure is unclear.

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 (1)

T09 · Insecure Skill Coding Practices

Note
Location
scripts/shutoff_registry.py:74
Finding

Registry File May Expose Household and Contact Information Through Permissive File Permissions

Content
View full analysis
{path}") ``` ### Technical Analysis The application stores the registry as plaintext JSON. Its contents may include exact valve locations, household tool locations, plumber contact details, insurance contact details, notes, and photo paths. The `save()` function uses the process's default file-creation behavior and does not explicitly apply restrictive permissions. Consequently, the permissions assigned to a newly created registry depend on the user's current umask. Under a permissive umask, other local users may be able to read the file. If the registry already exists with unsafe permissions, rewriting it does not correct those permissions. The default location under the user's home directory reduces exposure when the home directory itself is inaccessible to other users, but that protection is environment-dependent. The `--file` option can also place the registry in a shared or broadly accessible directory. No network transmission or automatic exfiltration was identified. Exploitation requires local filesystem access and sufficient directory traversal permissions. ### Attack Path 1. A user invokes `add`, `update`, `remove`, or `meta`, causing `save()` to write a registry. 2. The registry is created under a permissive umask, already has broad permissions, or is placed in a shared directory through `--file`. 3. Another local account identifies the default file or the custom registry path. 4. The local account reads the JSON file using its inherited filesystem permissions. 5. The account obtains household inf ...[truncated 788 chars]
Remediation
View remediation
{path}") ``` Tests should verify that a newly created registry has mode `0600` and that saving an existing broadly readable registry changes it to `0600`. ]]>
Vulnerability Patterns
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • 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
Findings (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill advertises and instructs use of shell execution and file-writing behavior, but it does not declare any explicit tool scope or permissions boundaries. That creates an authorization gap: an agent or runtime may grant broader capabilities than users expect, allowing filesystem writes or command execution without clear least-privilege constraints.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The guide tells users to close the water heater cold inlet, open a hot tap, and attach a hose to the drain spigot, and also references the nearby gas valve, but it does not clearly warn users to first shut off electrical power or gas burner operation and allow the tank to cool. A user following these steps during an emergency could release scalding water/steam, damage an electric element by operating a partially drained heater, or mishandle gas-adjacent equipment in a stressful situation.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/test_shutoff_registry.py (reported line 14)May include surrounding context.

python
def run_cli(args, env_file):
    return subprocess.run([sys.executable, ENGINE] + args + ["--file", env_file],
                          capture_output=True, text=True)

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/shutoff_registry.py (reported line 136)May include surrounding context.

python
changed = False
    for k in ("label", "location", "type", "direction", "tool", "notes",
              "photo", "tested"):
        v = getattr(a, k, None)
        if v:
            e[k] = v
            changed = True

Static analysis

No suspicious patterns detected.