Back to skill

Security audit

toolguard-daemon-control

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed macOS service manager, but its installer can persist arbitrary user commands and contains concrete injection flaws that need review before use.

Use only for services you intentionally want to survive beyond the current session. Review the exact command, arguments, workdir, and environment variables before installation; do not pass secrets via --env; and avoid untrusted input until the eval and plist-escaping issues are fixed.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/install.sh:55
Finding

Arbitrary Command Execution Through Unsafe Work Directory Expansion

Content
View full analysis
Remediation
View remediation
&2 exit 1 fi WORKDIR="$(cd "$WORKDIR" && pwd -P)" ``` Additional hardening should include: - Rejecting control characters in paths. - Avoiding every use of `eval` for user-controlled input. - Using `realpath` or a safe directory canonicalization method where available. - Adding regression tests containing command substitutions, semicolons, quotes, spaces, and XML metacharacters. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/install.sh:67
Finding

LaunchAgent Plist Injection Through Unescaped User-Controlled Values

Content
View full analysis
${COMMAND}" for arg in "${ARGS[@]}"; do PROGRAM_ARGS+=" ${arg}" done PROGRAM_ARGS+=" " # Build EnvironmentVariables section ENV_SECTION="" if [[ ${#ENV_VARS[@]} -gt 0 ]]; then ENV_SECTION=" EnvironmentVariables " for env_pair in "${ENV_VARS[@]}"; do KEY="${env_pair%%=*}" VALUE="${env_pair#*=}" ENV_SECTION+=" ${KEY} ${VALUE}" done ENV_SECTION+=" " fi # Write plist cat > "$PLIST_PATH" < Label ${LABEL} ProgramArguments ${PROGRAM_ARGS} WorkingDirectory ${WORKDIR} StandardOutPath ${LOG_DIR}/stdout.log StandardErrorPath ${LOG_DIR}/stderr.log KeepAlive RunAtLoad ${ENV_SECTION} EOF ``` ### Technical Analysis The script constructs XML through string concatenation and directly embeds caller-controlled values into `` and `` elements. It does not XML-escape characters such as `&`, `<`, or `>` and does not validate environment variable keys or service names. Affected data includes: - Service names and the derived launchd label - Executable paths - Program arguments - Working directories - Environment variable names and values - Derived log paths An attacker can supply XML closing tags and additional plist elements. Depending on the resulting ...[truncated 1611 chars]
Remediation
View remediation
&2 exit 1 fi ``` 3. Validate environment variable names: ```bash if [[ ! "$KEY" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then echo "Error: Invalid environment variable name: $KEY" >&2 exit 1 fi ``` 4. Preserve command arguments as distinct plist array values. 5. Validate the completed file before loading it: ```bash plutil -lint "$PLIST_PATH" ``` 6. Abort and remove the generated file if validation fails. 7. Add tests for ampersands, angle brackets, quotes, newlines, and attempted closing-tag injection in every input field. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/install.sh:77
Finding

Sensitive Environment Values Stored in Plaintext LaunchAgent Files

Content
View full analysis
EnvironmentVariables " for env_pair in "${ENV_VARS[@]}"; do KEY="${env_pair%%=*}" VALUE="${env_pair#*=}" ENV_SECTION+=" ${KEY} ${VALUE}" done ENV_SECTION+=" " fi # Write plist cat > "$PLIST_PATH" <
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (43)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a broad launchd service management skill whose core purpose is managing long-running macOS services, including plist creation and lifecycle control. The actual code chunk only implements log access for an existing service by tailing stdout/stderr files in a user log directory. While log access is mentioned in the description, this chunk does not perform the primary declared capabilities of starting, stopping, restarting, checking status, or configuring launchd services. That makes the code materially narrower than the declared purpose.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script expands the user-supplied working directory with eval echo, which causes the shell to interpret command substitutions and other shell syntax inside attacker-controlled input. A caller supplying --workdir '$(malicious_command)' can achieve arbitrary command execution during installation, before the plist is even written or loaded.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
95% confidence
Finding

The skill is explicitly designed to create persistent launchd services that continue beyond the current session. Persistence is inherently security-relevant because it can keep processes running, auto-restart them after failure, and make removal less obvious if invoked unintentionally or with unsafe commands.

Content

Scanner excerpt · SKILL.md (reported line 3)May include surrounding context.

md
---
name: toolguard-daemon-control
description: Manage long-running processes as macOS launchd services. Use when asked to start, stop, restart, check status of, or manage background services/daemons. Handles launchd plist creation, service lifecycle, and log access. Use this instead of background exec for any process that should persist beyond the current session.
---

# toolguard-daemon-control

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The activation text is broad enough that an agent may invoke this skill for general process-management requests, even when persistence was not explicitly requested. Because the skill creates launchd agents and persistent background behavior, accidental invocation can cause unintended system changes and long-lived processes beyond the user's intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill describes installing LaunchAgents and auto-restarting services but does not prominently warn that this makes persistent system changes and may survive the current session. In an agent setting, that omission increases the chance that users or upstream orchestrators trigger durable background execution without informed consent.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
96% confidence
Finding

This section states that services are installed into ~/Library/LaunchAgents and auto-restart on failure, which establishes durable user-level persistence. In context, that is the core capability of the skill, so it is not malicious by itself, but it is dangerous if used without strict consent and command validation.

Content

Scanner excerpt · SKILL.md (reported line 12)May include surrounding context.

md
## Overview

Services are installed as `~/Library/LaunchAgents/ai.toolguard.<name>.plist` and run as user-level launch agents. They auto-restart on failure and log to `~/Library/Logs/toolguard/`.

## Scripts

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The install interface allows arbitrary executable paths and arguments to be persisted as a launchd service. That creates a durable execution mechanism for any command supplied to the skill, raising the risk of persistence abuse or accidental installation of unsafe commands.

Content

Scanner excerpt · SKILL.md (reported line 24)May include surrounding context.

bash scripts/install.sh [args...] [--workdir

] [--env KEY=VALUE ...]

text

- `service-name`: Short identifier (e.g., `toolguard-proxy`). Used in plist filename and log paths.
- `command`: Absolute path to the executable.
- `args`: Arguments passed to the command.
- `--workdir <dir>`: Working directory for the process (default: `$HOME`).

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 69)May include surrounding context.

md
## Notes

- Services run as the current user (no sudo required).
- Services auto-restart on crash (`KeepAlive = true`).
- To run a Go project, use the compiled binary path or wrap in a shell script — launchd does not support `go run` directly. Use `go build` first, then point to the binary.
- Log directory: `~/Library/Logs/toolguard/<service-name>/`

Session Persistence

Medium
Category
Rogue Agent
Confidence
96% confidence
Finding

This duplicate finding points to the same persistence behavior: a user LaunchAgent plist plus KeepAlive-based restart. The danger is contextual rather than hidden—the skill is intended for persistence—but that still warrants safeguards because persistent execution can be abused or triggered accidentally.

Content

Scanner excerpt · SKILL.md (reported line 73)May include surrounding context.

md
- Services auto-restart on crash (`KeepAlive = true`).
- To run a Go project, use the compiled binary path or wrap in a shell script — launchd does not support `go run` directly. Use `go build` first, then point to the binary.
- Log directory: `~/Library/Logs/toolguard/<service-name>/`
- Plist location: `~/Library/LaunchAgents/ai.toolguard.<service-name>.plist`

Session Persistence

Medium
Category
Rogue Agent
Confidence
96% confidence
Finding

This duplicate finding points to the same persistence behavior: a user LaunchAgent plist plus KeepAlive-based restart. The danger is contextual rather than hidden—the skill is intended for persistence—but that still warrants safeguards because persistent execution can be abused or triggered accidentally.

Content

Scanner excerpt · SKILL.md (reported line 73)May include surrounding context.

md
- Services auto-restart on crash (`KeepAlive = true`).
- To run a Go project, use the compiled binary path or wrap in a shell script — launchd does not support `go run` directly. Use `go build` first, then point to the binary.
- Log directory: `~/Library/Logs/toolguard/<service-name>/`
- Plist location: `~/Library/LaunchAgents/ai.toolguard.<service-name>.plist`

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/install.sh (reported line 119)May include surrounding context.

sh
EOF

# Load and start service
launchctl load "$PLIST_PATH"

echo "Service '${SERVICE_NAME}' installed and started."
echo "  Label:  ${LABEL}"

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/install.sh (reported line 16)May include surrounding context.

sh
# list.sh — List all managed toolguard services
# Usage: list.sh

PLIST_DIR="$HOME/Library/LaunchAgents"
FOUND=false

for plist in "$PLIST_DIR"/ai.toolguard.*.plist; do

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/install.sh (reported line 17)May include surrounding context.

sh
# list.sh — List all managed toolguard services
# Usage: list.sh

PLIST_DIR="$HOME/Library/LaunchAgents"
FOUND=false

for plist in "$PLIST_DIR"/ai.toolguard.*.plist; do

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/install.sh (reported line 59)May include surrounding context.

sh
# list.sh — List all managed toolguard services
# Usage: list.sh

PLIST_DIR="$HOME/Library/LaunchAgents"
FOUND=false

for plist in "$PLIST_DIR"/ai.toolguard.*.plist; do

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/install.sh (reported line 64)May include surrounding context.

sh
# list.sh — List all managed toolguard services
# Usage: list.sh

PLIST_DIR="$HOME/Library/LaunchAgents"
FOUND=false

for plist in "$PLIST_DIR"/ai.toolguard.*.plist; do

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/install.sh (reported line 94)May include surrounding context.

sh
# list.sh — List all managed toolguard services
# Usage: list.sh

PLIST_DIR="$HOME/Library/LaunchAgents"
FOUND=false

for plist in "$PLIST_DIR"/ai.toolguard.*.plist; do

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/install.sh (reported line 96)May include surrounding context.

sh
# list.sh — List all managed toolguard services
# Usage: list.sh

PLIST_DIR="$HOME/Library/LaunchAgents"
FOUND=false

for plist in "$PLIST_DIR"/ai.toolguard.*.plist; do

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/install.sh (reported line 119)May include surrounding context.

sh
# list.sh — List all managed toolguard services
# Usage: list.sh

PLIST_DIR="$HOME/Library/LaunchAgents"
FOUND=false

for plist in "$PLIST_DIR"/ai.toolguard.*.plist; do

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/install.sh (reported line 123)May include surrounding context.

sh
# list.sh — List all managed toolguard services
# Usage: list.sh

PLIST_DIR="$HOME/Library/LaunchAgents"
FOUND=false

for plist in "$PLIST_DIR"/ai.toolguard.*.plist; do

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/list.sh (reported line 7)May include surrounding context.

sh
# list.sh — List all managed toolguard services
# Usage: list.sh

PLIST_DIR="$HOME/Library/LaunchAgents"
FOUND=false

for plist in "$PLIST_DIR"/ai.toolguard.*.plist; do

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/list.sh (reported line 10)May include surrounding context.

sh
# list.sh — List all managed toolguard services
# Usage: list.sh

PLIST_DIR="$HOME/Library/LaunchAgents"
FOUND=false

for plist in "$PLIST_DIR"/ai.toolguard.*.plist; do

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/status.sh (reported line 9)May include surrounding context.

sh
# list.sh — List all managed toolguard services
# Usage: list.sh

PLIST_DIR="$HOME/Library/LaunchAgents"
FOUND=false

for plist in "$PLIST_DIR"/ai.toolguard.*.plist; do

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/status.sh (reported line 11)May include surrounding context.

sh
# list.sh — List all managed toolguard services
# Usage: list.sh

PLIST_DIR="$HOME/Library/LaunchAgents"
FOUND=false

for plist in "$PLIST_DIR"/ai.toolguard.*.plist; do

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/status.sh (reported line 18)May include surrounding context.

sh
# list.sh — List all managed toolguard services
# Usage: list.sh

PLIST_DIR="$HOME/Library/LaunchAgents"
FOUND=false

for plist in "$PLIST_DIR"/ai.toolguard.*.plist; do

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/uninstall.sh (reported line 11)May include surrounding context.

sh
# list.sh — List all managed toolguard services
# Usage: list.sh

PLIST_DIR="$HOME/Library/LaunchAgents"
FOUND=false

for plist in "$PLIST_DIR"/ai.toolguard.*.plist; do

Static analysis

No suspicious patterns detected.