T08 · Insecure Dependencies
- Location
install.sh:39- Finding
Unpinned Third-Party Package Installed from a Mutable Package Index
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This camera-control skill appears purpose-aligned, but it handles camera passwords and surveillance media in ways users should review carefully before installing.
Install only if you are comfortable giving this skill access to camera credentials, live feeds, PTZ controls, local network discovery, and local storage of snapshots or recordings. Use a dedicated low-privilege camera account, avoid passing passwords with --pass, do not share stream-url output, restrict permissions on the config file, and review the unpinned dependency before running install.sh.
install.sh:39Unpinned Third-Party Package Installed from a Mutable Package Index
install.sh:47Camera Credentials Stored Without Enforced Restrictive File Permissions
scripts/ptz.py:757Camera Password Accepted Through Process Command-Line Arguments
scripts/camera.sh:82Credential-Bearing RTSP URLs Exposed Through Output and FFmpeg Arguments
scripts/ptz.py:545ONVIF Stream URI Printed Without Redacting Embedded Credentials
The code supports part of the description: RTSP capture/recording and basic camera info/connectivity checks. However, there is no ONVIF interaction, no PTZ commands, and no discovery mechanism such as network scanning or WS-Discovery. 'list-cameras' only lists cameras already present in a local config file, which is not camera discovery. The script primarily manages configured RTSP streams with ffmpeg, so the declared description materially overstates the implemented capabilities.
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
VENV_PYTHON = VENV_DIR / "bin" / "python"
if VENV_PYTHON.exists() and not sys.prefix.startswith(str(VENV_DIR)):
os.execv(str(VENV_PYTHON), [str(VENV_PYTHON)] + sys.argv)
# ── Config Loading ───────────────────────────────────────────────────────────
The skill advertises installation and usage of shell scripts and Python tools that interact with the network, environment variables, and local config files, but it declares no explicit tool scope or permissions. That omission weakens user consent and sandboxing because the skill can scan the local network, access credentials from env/config, and write files without transparent capability declaration.
The documented discover --add workflow implies active network scanning and automatic modification of the user's camera config, yet the skill provides no warning or consent prompt. In this context, silent LAN scanning and persistent config changes are sensitive operations because they can expose device inventory, alter local state, and surprise users in managed or monitored environments.
The skill advertises snapshot and recording features without warning that it may capture, store, or expose surveillance footage. In the context of IP cameras, this is especially sensitive because recordings may contain private spaces, people, or security-relevant information, and users need clear notice about storage location, retention, and access implications.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
if command -v brew &>/dev/null; then
brew install ffmpeg
elif command -v apt-get &>/dev/null; then
sudo apt-get install -y ffmpeg
else
echo " ✗ Please install ffmpeg manually." >&2; exit 1
fi
The stream-url command prints a full RTSP URL that embeds the camera username and password directly in stdout. This is dangerous because credentials can be exposed through terminal history, logs, screenshots, shell piping, or other tooling that captures command output; in the context of an IP camera skill, those credentials grant access to live video streams and potentially other camera functions.
The discover --add path stores supplied camera usernames and passwords in plaintext JSON on disk, and the code does not set restrictive permissions or clearly warn the user about local secret storage. In the context of an IP camera control skill, these credentials grant access to surveillance devices, so local disclosure can directly compromise camera feeds and control functions.
The script allows IPCAM_CONFIG from the environment to fully control the path written during discover --add, then writes camera configuration and credentials to that location. If this script is launched by another tool, agent, or privileged context, an attacker who can influence the environment could redirect writes to arbitrary files the process can access, causing unauthorized file overwrite or credential leakage.
# Write config
config_path.parent.mkdir(parents=True, exist_ok=True)
with open(config_path, "w") as f:
json.dump(config, f, indent=2)
print(f"\n✓ Config saved: {config_path}")
This is the same issue in the stream-uri --save flow: config_path is derived from an environment variable and then opened for writing without validation. An attacker able to control the process environment could redirect the write to an unintended file, leading to file clobbering or exposure of camera-related configuration in sensitive locations.
if len(uris) >= 2:
cam_cfg["rtsp_sub_path"] = uris[1]["path"]
with open(config_path, "w") as f:
json.dump(config, f, indent=2)
print(f"✓ Saved to config [{cam_name}]:")
No suspicious patterns detected.