Back to skill

Security audit

Satellite Copilot

Security checks for vulnerabilities and agentic risk

Overview

This satellite pass notifier is not malicious, but it should be reviewed because one included scheduler can run configured shell commands automatically and pass along the process environment.

Review before installing. The alerting and state files are normal for this kind of scheduler, but only enable capture/decode commands if you wrote and trust them, run the cron job as a low-privilege user, and avoid exposing secrets in the environment used by the scheduled process.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (22)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The documented purpose understates important behaviors, especially arbitrary shell-command execution via capture hooks and local state persistence. This mismatch is dangerous because operators may approve or run the skill expecting a simple pass notifier, while it actually has broader execution and persistence capabilities that could be abused for command execution or covert side effects.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
95% confidence
Finding

Copying the full parent environment into an arbitrary shell-executed capture command can leak secrets such as API tokens, credentials, service endpoints, or session data to that command and any child processes. In combination with configurable shell execution, this significantly increases the value of the execution primitive and enables credential exfiltration.

Content

Scanner excerpt · scripts/radio_scheduler.py (reported line 170)May include surrounding context.

python
(run_dir / "pass.json").write_text(json.dumps(p, indent=2), encoding="utf-8")

                    # Run capture command in shell, with timeout
                    env = os.environ.copy()
                    env["RADIO_RUN_DIR"] = str(run_dir)
                    env["SAT_NORAD"] = str(norad)
                    env["SAT_NAME"] = name

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

Passing a configuration-controlled string into subprocess.run with shell=True is a classic arbitrary command execution pattern. In this skill context, it is especially dangerous because the task is expected to run automatically on a schedule, turning a radio pass alert tool into an unattended code-execution mechanism.

Content

Scanner excerpt · scripts/radio_scheduler.py (reported line 178)May include surrounding context.

python
env["PASS_END"] = p["passEnd"]
                    env["PASS_MAX"] = p["passMax"]
                    try:
                        subprocess.run(cmd, shell=True, cwd=str(run_dir), env=env, timeout=timeout)
                    except Exception:
                        pass

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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 · README.md (reported line 46)May include surrounding context.

Copy the example config:

bash
mkdir -p ~/.clawdbot/radio-copilot
cp config.example.json ~/.clawdbot/radio-copilot/config.json
chmod 600 ~/.clawdbot/radio-copilot/config.json

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Lines L67-L72 say the end-to-end Pi/Jetson capture/decode pipeline is 'still in planning and development' and that the repo currently focuses on pass prediction, orchestration, and alerts. However, L85-L87 states the host's job is to 'trigger remote capture/decode via SSH,' which describes implemented operational behavior rather than a merely planned architecture. These statements create an intent-level contradiction in the documentation about whether remote execution/orchestration is present now or only planned.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill advertises operational behavior that implies filesystem, network, and shell access, yet it does not declare any explicit tool scope or permissions boundary. In an agent ecosystem, this weakens reviewability and containment because a user or orchestrator cannot easily tell that the skill may read/write local state, send alerts, or invoke external commands.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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 · SKILL.md (reported line 15)May include surrounding context.

  1. Copy the example config:
bash
mkdir -p ~/.clawdbot/radio-copilot
cp config.example.json ~/.clawdbot/radio-copilot/config.json
chmod 600 ~/.clawdbot/radio-copilot/config.json

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

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

Content

Scanner excerpt · README.md (reported line 48)May include surrounding context.

bash
mkdir -p ~/.clawdbot/radio-copilot
cp config.example.json ~/.clawdbot/radio-copilot/config.json
chmod 600 ~/.clawdbot/radio-copilot/config.json
  1. Run the orchestrator once:

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

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

Content

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

bash
mkdir -p ~/.clawdbot/radio-copilot
cp config.example.json ~/.clawdbot/radio-copilot/config.json
chmod 600 ~/.clawdbot/radio-copilot/config.json
  1. Run the orchestrator once:

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/orchestrator.py (reported line 68)May include surrounding context.

python
def send_whatsapp(channel: str, target: str, message: str) -> None:
    claw = find_clawdbot()
    subprocess.run([claw, "message", "send", "--channel", channel, "--target", target, "--message", message], capture_output=True)


def run(cmd: List[str], timeout: int = 30) -> subprocess.CompletedProcess:

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/radio_scheduler.py (reported line 94)May include surrounding context.

python
def send_whatsapp(channel: str, target: str, message: str) -> None:
    claw = find_clawdbot()
    subprocess.run([claw, "message", "send", "--channel", channel, "--target", target, "--message", message], capture_output=True)


def run(cmd: List[str], timeout: int = 30) -> subprocess.CompletedProcess:

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/orchestrator.py (reported line 72)May include surrounding context.

python
def run(cmd: List[str], timeout: int = 30) -> subprocess.CompletedProcess:
    return subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)


def ssh(host: str, remote_cmd: str, timeout: int = 60, user: Optional[str] = None) -> subprocess.CompletedProcess:

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The docstring reassures readers that the scheduler is 'conservative and safe,' yet the code later executes arbitrary shell commands from configuration. This misleading safety claim can reduce scrutiny and cause operators to deploy the tool with more trust and privilege than they otherwise would.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
80% confidence
Finding

The code attempts to resolve Node with subprocess.check_output(["command", "-v", "node"]), but 'command' is a shell builtin and not a standalone executable on many systems, causing unreliable behavior. More importantly, falling back to 'node' or trusting PATH can execute an attacker-controlled binary if the environment PATH is compromised in the scheduler context.

Content

Scanner excerpt · scripts/radio_scheduler.py (reported line 62)May include surrounding context.

python
def run_pass_predictor(norad: int, lat: float, lon: float, height_m: float, min_el: float, lookahead_min: float) -> List[dict]:
    node = subprocess.check_output(["command", "-v", "node"], text=True).strip() or "node"
    script = Path(__file__).with_name("pass_predictor.mjs")
    cmd = [
        node,

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/radio_scheduler.py (reported line 80)May include surrounding context.

python
"--look-ahead-min",
        str(lookahead_min),
    ]
    p = subprocess.run(cmd, capture_output=True, text=True)
    if p.returncode != 0:
        raise RuntimeError(p.stderr.strip() or "pass predictor failed")
    out = []

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill is presented primarily as a pass scheduler/alerter, but it includes hidden general-purpose command execution during pass windows. That mismatch is dangerous because users may enable the skill expecting notifications while unintentionally granting unattended remote-execution capability to whoever controls its configuration or updates.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Invoking a shell to run configured commands is substantially broader than what a pass-alerting copilot needs. In this context, the extra capability materially increases risk because the scheduler runs unattended and can execute arbitrary payloads whenever a matching event occurs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The scheduler automatically executes shell commands during pass windows without any runtime confirmation or prominent warning. In an unattended cron-style context, that means dangerous actions can occur silently after initial setup, magnifying the blast radius of misconfiguration or malicious config changes.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
99% confidence
Finding

This runs a configuration-supplied command through the shell with shell=True, which allows arbitrary command execution in the scheduler's security context. Because the command is triggered automatically during pass windows, any party able to modify configuration can achieve unattended code execution and potentially pivot further using inherited environment and filesystem access.

Content

Scanner excerpt · scripts/radio_scheduler.py (reported line 178)May include surrounding context.

python
env["PASS_END"] = p["passEnd"]
                    env["PASS_MAX"] = p["passMax"]
                    try:
                        subprocess.run(cmd, shell=True, cwd=str(run_dir), env=env, timeout=timeout)
                    except Exception:
                        pass

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This manifest file sets the time zone to "Europe/London" directly, which imposes a specific locale-related setting in natural language/config form. There is no indication in the file that the user is expected to choose or confirm this locale, so it may violate the policy against forcing a language/locale without opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This code sends message content and a target identifier to an external CLI without any runtime log, confirmation, or local comment at the call site explaining that user/system data is being transmitted. Although the module docstring mentions WhatsApp alerts generally, this function performs the actual outbound transmission silently.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The send_notify function transmits satellite pass details to an external messaging channel using clawdbot message send, but there is no log/print/comment at the call site indicating that data is being sent out. The top-level docstring mentions alerts are optional, yet the actual transmission lacks a visible runtime disclosure for users or operators.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.