Back to skill

Security audit

Window Truth

Security checks for vulnerabilities and agentic risk

Overview

This skill has a coherent weather-checking purpose, but it uses sensitive RTSP camera and microphone access with hardcoded default credentials and limited privacy controls.

Review before installing. Use only with a camera you own or are authorized to monitor, replace the default RTSP URL with a dedicated least-privilege account, understand that the script captures microphone audio to compute RMS, and be aware it sends configured coordinates to Open-Meteo and stores local JSONL observation history.

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/twilight_test.py:13
Finding

Hard-Coded Default RTSP Camera Credentials

Content
View full analysis

Vulnerability Details

File Location: scripts/twilight_test.py, line 13
Vulnerability Type: Hard-coded credentials and insecure default configuration
Risk Level: Medium

Complete Code Snippet:

python
RTSP_URL = os.getenv("RTSP_URL", "rtsp://admin:pass@192.168.1.247:554/stream2")

Technical Analysis

The default RTSP URL contains the plaintext credential pair admin:pass. When the RTSP_URL environment variable is absent, the script automatically supplies these credentials to ffmpeg and attempts to authenticate to a camera at the fixed private address 192.168.1.247.

Although environment-variable override support exists, the fallback does not fail securely. Embedding credentials in distributed source code exposes them to anyone who can read the package and encourages deployment with weak or shared camera credentials. Credentials embedded in a URL may also appear in process inspection, diagnostics, exception output, or logs produced by surrounding tooling.

Attack Path

  1. A user installs or obtains the Skill and runs scripts/twilight_test.py without defining RTSP_URL.
  2. capture_photo() and capture_audio() pass the hard-coded URL to ffmpeg as the input source.
  3. ffmpeg connects to 192.168.1.247:554 and attempts authentication with username admin and password pass.
  4. If a reachable camera accepts those credentials, the process obtains its video frame and microphone audio stream.
  5. Anyone who learns that a deployed camera retained the same credentials may independently attempt RTSP authentication and access the exposed media streams.

Exploitation requires network access to a camera configured with the disclosed credential pair. The audited code does not bypass authentication, escalate operating-system privileges, or transmit captured raw media to an unrelated remote service.

Impact Assessment

Successful use of the disclosed credentials can grant the level of acce ...[truncated 588 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove the credential-bearing fallback and require RTSP_URL to be explicitly configured.
  • Fail closed with a clear configuration error when the URL is absent.
  • Obtain credentials from a protected secret store, restricted configuration file, or runtime secret injection mechanism rather than source code.
  • Use a dedicated, least-privileged camera account that can access only the required RTSP stream instead of an administrative account.
  • Require users to replace factory or example passwords with unique, strong credentials.
  • Redact URL user information from application errors, diagnostics, and logs.
  • Consider separating the endpoint from its credentials so secret values are less likely to be exposed as part of a complete URL.
  • Rotate the disclosed credential on any camera where it has been used.

A safer configuration pattern is:

python
RTSP_URL = os.getenv("RTSP_URL")
if not RTSP_URL:
    raise RuntimeError("RTSP_URL must be configured securely")
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (13)

Tainted flow: 'url' from os.getenv (line 61, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

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

python
def get_weather():
    """Get weather forecast from Open-Meteo."""
    url = f"https://api.open-meteo.com/v1/forecast?latitude={LAT}&longitude={LON}&current=temperature_2m,cloud_cover,precipitation_probability,weather_code"
    resp = requests.get(url, timeout=10)
    return resp.json()

def detect_conflicts(brightness, rms, weather):

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill advertises operational behavior that depends on network access, shell execution via ffmpeg, and likely local file/output handling, but it does not declare any explicit tool scope or permissions. This creates an authorization gap where an agent or host may permit broader capabilities than users expect, increasing the risk of unintended network access, command execution, or filesystem side effects when the skill is invoked.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger list contains broad, natural-language phrases such as 'local weather observation' and 'trust the window' that can overlap with ordinary conversation unrelated to this specific skill. Overbroad activation increases the chance of unintended invocation, which is more concerning here because the skill's described behavior involves networked camera/RTSP access and shell-capable processing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The document explicitly describes collecting and using RTSP microphone audio ('RMS' from the RTSP mic) as a key signal, but it provides no notice, consent guidance, retention limits, or privacy safeguards. Audio capture from an IP camera can unintentionally collect conversations or other sensitive ambient data, creating privacy and legal risk even if only RMS is intended for analysis.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script embeds default RTSP credentials and captures camera photo/audio without any explicit privacy notice, consent flow, or confirmation. In a home or office setting, access to live camera and microphone data is highly sensitive, and the combination of hardcoded credentials plus silent capture materially increases surveillance and unauthorized-access risk.

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

python
"-i", RTSP_URL,
        "-frames:v", "1", "-f", "image2", "-"
    ]
    result = subprocess.run(cmd, capture_output=True)
    return result.stdout

def capture_audio(duration=3):

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

python
"-i", RTSP_URL,
        "-frames:v", "1", "-f", "image2", "-"
    ]
    result = subprocess.run(cmd, capture_output=True)
    return result.stdout

def capture_audio(duration=3):

Tainted flow: 'cmd' from os.getenv (line 32, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
84% confidence
Finding

The command arguments include values derived from environment variables, especially FFMPEG and RTSP_URL, which are treated as trusted without validation before being passed to subprocess.run. Although shell injection is mitigated by list-based invocation, an attacker who can influence the environment can redirect execution to a malicious binary or force ffmpeg to connect to an attacker-controlled stream, increasing code-execution and parser-exploitation risk.

Content

Scanner excerpt · scripts/twilight_test.py (reported line 27)May include surrounding context.

python
"-i", RTSP_URL,
        "-frames:v", "1", "-f", "image2", "-"
    ]
    result = subprocess.run(cmd, capture_output=True)
    return result.stdout

def capture_audio(duration=3):

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill captures audio from the RTSP stream even though its stated purpose centers on visual window observation for weather verification. In context, ambient audio may collect conversations or other sensitive nearby sounds, making this significantly more dangerous than ordinary telemetry because it introduces covert surveillance capability unrelated to the declared function.

Content

No source excerpt is available for this finding.

Tainted flow: 'cmd' from os.getenv (line 32, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
84% confidence
Finding

This subprocess invocation reuses unvalidated environment-derived values for the executable path and RTSP input while capturing audio from the camera stream. In the context of a skill that processes untrusted network media, this increases exposure to malicious binaries, hostile streams, and privacy-invasive behavior beyond a simple helper command.

Content

Scanner excerpt · scripts/twilight_test.py (reported line 38)May include surrounding context.

python
"-t", str(duration), "-f", "wav", "-acodec", "pcm_s16le",
        "-ar", "8000", "-ac", "1", "-"
    ]
    result = subprocess.run(cmd, capture_output=True)
    return result.stdout

def calculate_brightness(jpeg_bytes):

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/twilight_test.py (reported line 61)May include surrounding context.

python
def get_weather():
    """Get weather forecast from Open-Meteo."""
    url = f"https://api.open-meteo.com/v1/forecast?latitude={LAT}&longitude={LON}&current=temperature_2m,cloud_cover,precipitation_probability,weather_code"
    resp = requests.get(url, timeout=10)
    return resp.json()

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The weather request transmits precise latitude and longitude to an external service without clear notice to the user. While this is not a code-execution issue, location data can reveal a user's residence or routine, so the privacy impact is real in the context of a window-mounted home observation skill.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The manifest describes determining whether the weather app is wrong based on current local observation, but this script also builds a historical log of perceptions, app data, conflicts, and predictions. Maintaining a local dataset is a meaningful behavioral extension beyond one-shot observation/comparison, and it is not surfaced in the skill description.

Content

No source excerpt is available for this finding.