Back to skill

Security audit

Site Change Alert

Security checks for vulnerabilities and agentic risk

Overview

This skill has a real website-monitoring script, but it also ships mismatched logging code and unsafe persistent cron/config handling that could execute unintended shell commands.

Review carefully before installing. Use only with trusted URLs and notification targets, avoid sensitive query strings or tokens, and do not use the scheduling or notify features until cron construction and shell-sourced configuration are fixed. Be aware that the package stores snapshots/config under the home directory and also contains a separate nested logger that records arbitrary inputs locally.

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

Error
Location
scripts/script.sh:429
Finding

Persistent Command Injection Through Unsafe Cron Job Construction

Content
View full analysis

Vulnerability Details

File Location: scripts/script.sh, lines 429–441
Vulnerability Type: Persistent shell command injection through crontab
Risk Level: High

Vulnerable Code

bash
local cron_cmd="*/${interval} * * * * bash ${script_path} check '${url}' >> ${DATA_DIR}/cron.log 2>&1"

# Check if already scheduled
if crontab -l 2>/dev/null | grep -qF "$url"; then
    echo "⚠️  URL already scheduled. Updating interval..."
    local temp_cron
    temp_cron=$(mktemp)
    crontab -l 2>/dev/null | grep -vF "$url" > "$temp_cron"
    echo "$cron_cmd" >> "$temp_cron"
    crontab "$temp_cron"
    rm -f "$temp_cron"
else
    (crontab -l 2>/dev/null; echo "$cron_cmd") | crontab -
fi

Technical Analysis

The schedule command inserts the user-controlled url and interval values directly into a cron expression. Neither value is validated or safely encoded for the crontab and shell syntaxes.

The URL is surrounded by single quotes, but a URL containing a single quote can terminate that quoted argument. Shell operators and commands following it will then be interpreted when cron executes the entry. Newline characters could also introduce additional crontab entries.

The interval is inserted into the cron timing field without confirming that it is a bounded positive integer. Crafted whitespace or newline content could corrupt the schedule or inject another entry.

This flaw is especially severe because the generated payload is written to the user's crontab. The injected command therefore survives the original process and executes periodically across sessions.

The update logic also identifies existing jobs using a substring search:

bash
crontab -l 2>/dev/null | grep -vF "$url"

This can remove unrelated cron entries that happen to contain the supplied text.

Cron-based scheduling itself is explicitly documented and is reasonably related to periodic website monitoring. However, unsafe construction of the persistent task exceeds a safe i ...[truncated 1233 chars]

Remediation
View remediation

Remediation Suggestions

  1. Validate interval using a strict numeric allowlist and enforce a safe range:

    bash
    [[ "$interval" =~ ^[0-9]+$ ]] || {
        echo "Invalid interval" >&2
        return 1
    }
    (( interval >= 1 && interval <= 59 )) || {
        echo "Interval must be between 1 and 59 minutes" >&2
        return 1
    }
    
  2. Reject URLs containing control characters, especially carriage returns and newlines.

  3. Validate that the URL uses an explicitly supported scheme such as http or https.

  4. Shell-escape every command argument rather than interpolating raw values. For Bash-executed cron commands, construct arguments with printf '%q':

    bash
    printf -v quoted_script '%q' "$script_path"
    printf -v quoted_url '%q' "$url"
    printf -v quoted_log '%q' "${DATA_DIR}/cron.log"
    cron_cmd="*/${interval} * * * * bash ${quoted_script} check ${quoted_url} >> ${quoted_log} 2>&1"
    
  5. Add a stable, generated identifier to each managed cron entry and update or remove entries only by that exact identifier. Do not use the URL as a broad substring selector.

  6. Consider using a scheduler API or a dedicated wrapper that reads validated arguments from a protected data file, reducing the amount of user input embedded in shell command text.

  7. Display the exact proposed schedule and require explicit confirmation before installing persistent tasks in interactive use.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/script.sh:29
Finding

Arbitrary Command Execution Through Sourced Configuration Values

Content
View full analysis

Vulnerability Details

File Location: scripts/script.sh, lines 29 and 517–529
Vulnerability Type: Shell command injection through executable configuration
Risk Level: High

Vulnerable Code

bash
# shellcheck source=/dev/null
source "$CONFIG_FILE"
bash
webhook)
    if [ -z "$target" ]; then
        echo "❌ Webhook URL required"
        echo "Usage: bash scripts/script.sh notify webhook <url>"
        echo "📖 More skills: bytesagain.com"
        return 1
    fi
    sed -i "s|^NOTIFY_METHOD=.*|NOTIFY_METHOD=\"webhook\"|" "$CONFIG_FILE"
    sed -i "s|^WEBHOOK_URL=.*|WEBHOOK_URL=\"${target}\"|" "$CONFIG_FILE"
    echo "✅ Notifications set to webhook: ${target:0:50}..."
    ;;
email)
    if [ -z "$target" ]; then
        echo "❌ Email address required"
        echo "Usage: bash scripts/script.sh notify email <address>"
        echo "📖 More skills: bytesagain.com"
        return 1
    fi
    sed -i "s|^NOTIFY_METHOD=.*|NOTIFY_METHOD=\"email\"|" "$CONFIG_FILE"
    sed -i "s|^EMAIL_TO=.*|EMAIL_TO=\"${target}\"|" "$CONFIG_FILE"

Technical Analysis

The notification target is controlled by the caller and is written directly into config.sh as text inside a double-quoted shell assignment. The script later loads that file using source, which evaluates the file as Bash code rather than reading it as data.

Shell constructs embedded in the target can consequently become executable configuration. For example, command substitutions placed in a stored value are evaluated when the configuration file is sourced. Quotes, backslashes, ampersands, and the | delimiter can also alter or corrupt the dynamically generated sed expression.

This creates a stored or delayed command-injection condition: the malicious value is persisted during the notify operation and executes when a later command calls ensure_dirs, which sources the configuration.

Attack Path

  1. An attacker causes the user or agent to run notify webhook or `notify e ...[truncated 1049 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not source a configuration file containing user-controlled data. Store configuration in a non-executable format such as JSON, or use a fixed-key parser that treats every value strictly as data.

  2. Validate webhook targets against supported http and https URL syntax. Validate email addresses according to a conservative allowlist appropriate for the application.

  3. Reject control characters, shell metacharacters where unnecessary, and embedded line breaks.

  4. Avoid constructing sed programs with raw user input. Rewrite the configuration atomically using safely serialized values.

  5. If shell assignment format must be retained temporarily, serialize every value with printf '%q' before writing it. This is defense in depth and should not replace migration away from source.

  6. Create configuration files with restrictive permissions, such as mode 0600, and ensure the data directory is not writable by other users:

    bash
    umask 077
    mkdir -p "$DATA_DIR"
    
  7. Write updates to a protected temporary file, verify the resulting format, then atomically rename it over the original configuration.

  8. Add regression tests using targets containing command substitutions, quotes, backslashes, &, the sed delimiter, carriage returns, and newlines to ensure they remain inert data.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (22)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

This finding indicates the skill may be fundamentally misrepresented: it is described as a website change monitor, but the underlying behavior reportedly lacks fetching, diffing, scheduling, and notification capabilities. In security and operational contexts, such deceptive functionality can cause users to believe monitoring is active when it is not, leading to missed incidents or compliance failures.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This finding indicates the skill may be fundamentally misrepresented: it is described as a website change monitor, but the underlying behavior reportedly lacks fetching, diffing, scheduling, and notification capabilities. In security and operational contexts, such deceptive functionality can cause users to believe monitoring is active when it is not, leading to missed incidents or compliance failures.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill description explicitly includes 'sending alerts via email and webhook notifications' as part of its purpose. In the code, cmd_notify merely writes configuration values to config.sh, while no function in the script sends an email, performs a webhook POST, or invokes notifications from change-detection paths. The implemented behavior therefore falls materially short of the advertised alerting capability.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script is presented as a website change monitoring and alerting tool, but it contains no website fetching, snapshot comparison, scheduling, or notification logic. Instead, it acts as a generic input collection and local logging utility, which is a deceptive mismatch that can mislead users into supplying operational data under false pretenses and can hide unauthorized data collection behavior.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill advertises shell-based commands and implies file access, but it does not declare any explicit tool scope such as allowed tools or permissions. This creates an authorization ambiguity where an agent may invoke shell or file operations more broadly than a user expects, increasing the risk of unintended local access or command execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The documentation omits warnings about persistent monitoring and outbound notifications, both of which can have privacy, consent, and operational implications. Users may unknowingly configure ongoing checks or send data to external email/webhook endpoints without understanding retention, frequency, or data exposure risks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script sources ~/.site-change-alert/config.sh as shell code, so any content written to that file executes with the user's privileges whenever the tool runs. In this skill's context, the config file is user-writable and later modified by the script, making local code execution via config tampering a realistic risk on shared systems or when another process can alter that path.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The schedule documentation says periodic runs will 'trigger notification' when changes are detected. However, the cron job created at L429 only invokes check, and cmd_check only prints status and diffs to stdout without calling any notification-sending logic. This is an active contradiction between the skill's documented behavior and the implemented code.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% 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/script.sh (reported line 415)May include surrounding context.

sh
*/30 * * * * /path/to/script.sh check "https://example.com"

Remove Schedule:
  crontab -l | grep -v "site-change-alert" | crontab -

View Active Schedules:
  crontab -l | grep "site-change-alert"

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% 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/script.sh (reported line 418)May include surrounding context.

sh
*/30 * * * * /path/to/script.sh check "https://example.com"

Remove Schedule:
  crontab -l | grep -v "site-change-alert" | crontab -

View Active Schedules:
  crontab -l | grep "site-change-alert"

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% 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/script.sh (reported line 456)May include surrounding context.

sh
*/30 * * * * /path/to/script.sh check "https://example.com"

Remove Schedule:
  crontab -l | grep -v "site-change-alert" | crontab -

View Active Schedules:
  crontab -l | grep "site-change-alert"

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% 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/script.sh (reported line 457)May include surrounding context.

sh
*/30 * * * * /path/to/script.sh check "https://example.com"

Remove Schedule:
  crontab -l | grep -v "site-change-alert" | crontab -

View Active Schedules:
  crontab -l | grep "site-change-alert"

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

The schedule command creates a persistent cron entry that will repeatedly execute the script and fetch remote URLs. While persistence is the intended feature of a monitoring tool, it still introduces ongoing execution and network activity that can be abused if invoked without the user's clear understanding or if untrusted URLs are scheduled indefinitely.

Content

Scanner excerpt · scripts/script.sh (reported line 432)May include surrounding context.

sh
local cron_cmd="*/${interval} * * * * bash ${script_path} check '${url}' >> ${DATA_DIR}/cron.log 2>&1"

    # Check if already scheduled
    if crontab -l 2>/dev/null | grep -qF "$url"; then
        echo "⚠️  URL already scheduled. Updating interval..."
        local temp_cron
        temp_cron=$(mktemp)

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

This code modifies the user's crontab to maintain recurring execution. In a security review of agent skills, automatic persistence mechanisms are sensitive because they survive the current session and may continue making network requests or executing altered code later.

Content

Scanner excerpt · scripts/script.sh (reported line 436)May include surrounding context.

sh
echo "⚠️  URL already scheduled. Updating interval..."
        local temp_cron
        temp_cron=$(mktemp)
        crontab -l 2>/dev/null | grep -vF "$url" > "$temp_cron"
        echo "$cron_cmd" >> "$temp_cron"
        crontab "$temp_cron"
        rm -f "$temp_cron"

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

Appending the generated command into crontab establishes lasting scheduled execution. In combination with the separate config sourcing issue, future cron-driven runs could execute attacker-modified config content automatically, increasing the practical risk of persistence.

Content

Scanner excerpt · scripts/script.sh (reported line 441)May include surrounding context.

sh
crontab "$temp_cron"
        rm -f "$temp_cron"
    else
        (crontab -l 2>/dev/null; echo "$cron_cmd") | crontab -
    fi

    cat <<EOF

Ssd 3

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation instructs the system to persist, search, and export all user-supplied inputs across multiple log files, which is risky because users often paste sensitive monitoring targets, internal URLs, credentials-in-URLs, or confidential change results into such tools. The combination of automatic retention plus search/export functionality amplifies exposure by making sensitive data easier to discover, aggregate, and exfiltrate later.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly stores user-provided URLs, targets, and results in persistent local logs and export files, but the description does not prominently warn users that their inputs will be retained on disk. In a natural-language agent workflow, users may provide sensitive URLs, query strings, tokens, internal hostnames, or monitoring results, which then become searchable and exportable artifacts, increasing the chance of unintended disclosure.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The help text exposes a broad set of generic commands that are not specific to website change monitoring, which is inconsistent with the declared skill purpose. In this context, that breadth increases suspicion that the tool is designed as a disguised general-purpose data logger rather than a narrowly scoped monitoring utility.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The help advertises export <fmt> as a data export feature, but the first export) case in the dispatcher only logs arbitrary user input instead of performing an export. This deceptive behavior can cause users to believe they are exporting monitored data while actually recording additional sensitive input, undermining trust and masking data collection.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The help text describes status as a health check, but the first status) branch logs arbitrary input rather than showing status. This discrepancy is dangerous because it disguises storage of user-provided text as an innocuous diagnostic command, especially in an automation context where operators may pass environment or operational details.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The export routine aggregates all logged content into JSON, CSV, or text files on disk without warning the user that previously captured data will be materialized into new files. This increases exposure by duplicating potentially sensitive records into easier-to-share or accidentally exfiltrated formats.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script persistently records all user-supplied command input into log files under the user's home directory with no clear warning, retention policy, or minimization. If operators pass URLs, tokens, incident notes, email addresses, or other sensitive content as arguments, that data will be silently stored and later discoverable by local users or backup systems.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.