Back to skill

Security audit

Personal Finish Notifier

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says, but it installs persistent Claude Code hooks and rewrites global agent settings in a way users should review carefully.

Install only if you are comfortable with this skill modifying your global Claude Code settings and running a shell hook on future completion events. Before use, review ~/.claude/settings.json, back it up, confirm no existing Stop or TaskCompleted hooks would be overwritten, and treat ~/.claude/mac-notify.env as executable code rather than harmless configuration.

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

Warning
Location
scripts/notify.sh:5
Finding

Arbitrary Shell Execution Through Sourced Configuration

Content
View full analysis

Vulnerability Details

File Location: scripts/notify.sh, lines 5–11
Vulnerability Type: Unsafe execution of a configuration file
Risk Level: Medium

Vulnerable Code

bash
CONFIG_FILE="${HOME}/.claude/mac-notify.env"
LOG_FILE="${HOME}/.claude/mac-task-notify.log"

if [[ -f "$CONFIG_FILE" ]]; then
  # shellcheck disable=SC1090
  source "$CONFIG_FILE"
fi

Technical Analysis

The notification hook loads ~/.claude/mac-notify.env with Bash's source command. Although this file is described as configuration, source interprets its entire contents as shell code rather than parsing it as inert key-value data.

Consequently, command substitutions, function calls, redirections, and arbitrary shell commands embedded in the configuration file execute with the privileges and environment of the user running the hook. The hook installer registers this script for both Stop and TaskCompleted events, so malicious content can execute repeatedly whenever either event occurs.

Exploitation requires an attacker or compromised process to modify the user's configuration file. The code shown does not itself provide remote access to that file, so exploitability depends on its ownership, permissions, and surrounding workflows.

Attack Path

  1. An attacker, compromised local process, or unsafe configuration synchronization mechanism gains the ability to alter ~/.claude/mac-notify.env.

  2. The attacker inserts shell code into the file, for example:

    bash
    OPENCLAW_NOTIFY_TARGET=
    malicious_command
    
  3. Claude Code emits a Stop or TaskCompleted event.

  4. The installed hook invokes scripts/notify.sh.

  5. The script executes source "$CONFIG_FILE".

  6. Bash evaluates the attacker's command with the current user's privileges.

Impact Assessment

Successful exploitation provides arbitrary command execution as the user who runs Claude Code. The attacker could access or modify files available to that user, invoke installed applic ...[truncated 275 chars]

Remediation
View remediation

Remediation Suggestions

  • Do not use source or eval to load configuration data.
  • Parse only an explicit allowlist of supported keys:
    • MAC_NOTIFY_MODE
    • OPENCLAW_NOTIFY_CHANNEL
    • OPENCLAW_NOTIFY_TARGET
    • OPENCLAW_NOTIFY_SELF_TARGET
  • Reject malformed lines, unknown keys, command substitutions, and unsupported values.
  • Create the configuration file with mode 0600 and verify that it is owned by the current user before reading it.
  • Reject symbolic links and files writable by group or other users.
  • Validate each value according to its expected syntax before passing it to OpenClaw.
  • Consider using JSON and a non-executing parser such as Python's json module instead of shell-formatted configuration.
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 (9)

Agent Config Directory Access

High
Category
Agent Snooping
Confidence
91% confidence
Finding

Direct access to ~/.claude/settings.json is highly sensitive because that file controls agent behavior and hook execution. In this skill's context, touching the Claude config directory is expected for installation, but it remains dangerous because any write there can create persistence, alter event handling, and affect all future agent runs.

Content

Scanner excerpt · scripts/install-claude-hook.sh (reported line 7)May include surrounding context.

sh
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
HOOK_PATH="${HOME}/.claude/hooks/mac-task-notify.sh"
SETTINGS_PATH="${HOME}/.claude/settings.json"
ENV_PATH="${HOME}/.claude/mac-notify.env"

mkdir -p "$(dirname "$HOOK_PATH")"

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The embedded Python rewrites ~/.claude/settings.json to register command hooks, causing persistent execution of a shell command on future Stop and TaskCompleted events. This is dangerous because it modifies core agent configuration globally, may overwrite existing entries, and establishes an execution mechanism that could later be repurposed for data exfiltration or arbitrary command execution through the installed hook.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill advertises shell, file read, and file write capabilities through its documented scripts and hook installation flow, but it does not declare any explicit tool scope or permission boundaries in the skill manifest. That creates an avoidable trust gap: consumers and runners cannot easily determine the intended execution surface, increasing the chance that the skill is granted broader access than necessary when installing hooks, reading environment files, or invoking transport adapters.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script copies an executable hook into the user's Claude hooks directory and changes permissions without any prompt or disclosure. Silent persistence into an agent's hook path is security-sensitive because it creates ongoing code execution on future agent events, and users may not realize their environment has been modified.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The installer registers the hook for all Stop and TaskCompleted events using a wildcard matcher, which is broader than a narrowly scoped 'finished alert' feature implies. While this may be intended to ensure notifications fire consistently, it modifies agent behavior globally and can create an execution point for every matching event, increasing the blast radius if the hook script is altered or abused later.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The script silently creates a persistent environment file containing notification transport settings, including external messaging-related options, without informing the user. Hidden creation of such config is risky because it can later influence hook behavior and enable outbound notification channels the user did not knowingly authorize.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script creates an environment file preconfiguring OpenClaw/WhatsApp notification parameters, which introduces outbound messaging capability beyond a simple local completion alert. Even with empty target fields by default, silently provisioning messaging-related config expands the trust boundary and could enable unintended data flow once completed or combined with a companion script.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script sends a notification through an external OpenClaw WhatsApp transport without any runtime disclosure, consent prompt, or clear indication in the code path that task-related data is leaving the local environment. Even though the current message is hardcoded to "Claude has finished.", the behavior creates an external data-flow channel and relies on configuration loaded from a user-writable env file, which can surprise users and normalize silent exfiltration patterns in agent hooks.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

The script rejects any channel other than whatsapp with the message that the channel 'must stay whatsapp'. This is a natural-language policy concern because it forces a specific service/channel choice without any visible opt-in alternative or justification in the file.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.