T09 · Insecure Skill Coding Practices
- Location
scripts/camera_stream.py:377- Finding
Unauthenticated Camera Streaming on All Network Interfaces
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This camera skill is mostly purpose-aligned, but its streaming server can expose live camera feeds and local files to anyone who can reach the port.
Review carefully before installing. Use this only on trusted machines and networks, avoid starting the streaming server unless you intend to expose the camera feed, do not enable HLS until the path traversal is fixed, and prefer localhost binding plus authentication before any remote viewing.
scripts/camera_stream.py:377Unauthenticated Camera Streaming on All Network Interfaces
scripts/camera_stream.py:259Arbitrary Local File Disclosure Through HLS Path Traversal
scripts/camera_stream.py:175Execution of an Unpinned Mutable Third-Party HLS Script
The code chunk's behavior is narrower than the declared description. It supports recording video clips from V4L2 webcams and RTSP cameras, which aligns with part of the description, but there is no functionality here for taking still photos, enumerating/listing available cameras, or live streaming. The reference to 'Run camera_list.py' is only an error message and does not implement camera listing in this chunk. Therefore the declared description does not accurately represent what this supplied code chunk actually does.
The code chunk is narrowly focused on taking a still image from a local /dev/video* device via ffmpeg with the v4l2 input format. While it does detect whether local video device nodes exist and prints available devices on error, that is only a limited helper behavior rather than a full camera-listing feature. There is no implementation for video recording, streaming, or accessing RTSP/IP camera sources. Therefore, the declared description materially overstates the implemented capabilities in this code chunk.
The description is partially accurate: the code does support Linux cameras, V4L2, ffmpeg, USB webcams, RTSP/IP cameras, snapshots, and live streaming. However, two declared capabilities are not implemented in this code chunk: listing cameras and recording video clips. Instead, the code’s actual primary function is to run a network-accessible live streaming server with snapshot and status endpoints, plus optional HLS and RTSP re-stream output. Because the declared purpose includes significant capabilities absent from the code and understates the server/re-streaming behavior, this is a material description-behavior mismatch.
The trigger list contains broad everyday words like 'photo', 'picture', 'video', 'record', and 'stream', which can cause accidental activation in unrelated conversations or tasks. In a camera skill, unintended activation is especially sensitive because it can capture images, record video, or start network streaming without sufficiently deliberate user intent.
The skill describes live streaming endpoints but does not prominently warn users that starting the stream exposes live camera output over HTTP and optionally RTSP to other hosts on the network. This omission is dangerous because users may believe they are only viewing locally while actually publishing camera feeds, potentially leaking private spaces, people, screens, or credentials visible in the frame.
Potential security issue detected. Manual review is recommended.
uv run python scripts/camera_snap.py
# Snapshot from a specific camera
uv run python scripts/camera_snap.py --device /dev/video2 --output /tmp/photo.jpg
# Snapshot from an IP camera
uv run python scripts/camera_snap.py --rtsp rtsp://user:pass@192.168.1.100:554/stream1
Potential security issue detected. Manual review is recommended.
uv run python scripts/camera_snap.py
# Snapshot from a specific camera
uv run python scripts/camera_snap.py --device /dev/video2 --output /tmp/photo.jpg
# Snapshot from an IP camera
uv run python scripts/camera_snap.py --rtsp rtsp://user:pass@192.168.1.100:554/stream1
Potential security issue detected. Manual review is recommended.
uv run python scripts/camera_snap.py
# Snapshot from a specific camera
uv run python scripts/camera_snap.py --device /dev/video2 --output /tmp/photo.jpg
# Snapshot from an IP camera
uv run python scripts/camera_snap.py --rtsp rtsp://user:pass@192.168.1.100:554/stream1
Potential security issue detected. Manual review is recommended.
uv run python scripts/camera_snap.py --device /dev/video2 --output /tmp/cam2.jpg
uv run python scripts/camera_stream.py --device /dev/video0 --port 8090 uv run python scripts/camera_stream.py --device /dev/video2 --port 8091
Potential security issue detected. Manual review is recommended.
uv run python scripts/camera_snap.py --device /dev/video2 --output /tmp/cam2.jpg
uv run python scripts/camera_stream.py --device /dev/video0 --port 8090 uv run python scripts/camera_stream.py --device /dev/video2 --port 8091
Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.
source = args.rtsp or args.device
threads = []
# MJPEG capture thread (always on)
t = threading.Thread(
target=capture_mjpeg,
args=(args.device, args.rtsp, args.width, args.height, args.fps),
The skill declares use of the exec tool but does not define a restrictive tool scope such as allowed-tools or permissions. Because the skill can invoke shell commands that access cameras, files, and network services, the missing scope increases the chance of unintended or overbroad command execution.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
sudo apt-get install -y ffmpeg v4l-utils
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
]
print(f"Recording {duration}s from {device} ({width}x{height} @ {fps}fps)...")
result = subprocess.run(cmd, capture_output=True, text=True, timeout=duration + 30)
if result.returncode != 0:
print(f"ffmpeg error:\n{result.stderr}", file=sys.stderr)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
]
print(f"Recording {duration}s from {device} ({width}x{height} @ {fps}fps)...")
result = subprocess.run(cmd, capture_output=True, text=True, timeout=duration + 30)
if result.returncode != 0:
print(f"ffmpeg error:\n{result.stderr}", file=sys.stderr)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
info = {"path": str(dev), "name": "", "driver": "", "formats": []}
try:
result = subprocess.run(
["v4l2-ctl", "--device", str(dev), "--info"],
capture_output=True, text=True, timeout=5,
)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
pass
try:
result = subprocess.run(
["v4l2-ctl", "--device", str(dev), "--list-formats-ext"],
capture_output=True, text=True, timeout=5,
)
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
if not devices:
print("No video capture devices found.", file=sys.stderr)
print("Make sure a camera is connected and v4l-utils is installed:")
print(" sudo apt-get install -y v4l-utils")
sys.exit(1)
if args.json:
This skill captures images from a camera and writes them to disk, but the user-facing description and usage text do not provide any privacy warning, consent cue, or prominent notice that local image files will be created. In a camera skill, this increases the risk of unnoticed collection or retention of sensitive visual data, especially if triggered by broad phrases like 'photo', 'snapshot', or 'webcam'.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
]
print(f"Taking photo from {device}...")
result = subprocess.run(cmd, capture_output=True, text=True, timeout=15)
if result.returncode != 0:
print(f"Error: {result.stderr.strip()}", file=sys.stderr)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
]
print(f"Capturing from {device} ({width}x{height}, warmup={warmup_frames} frames)...")
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
if result.returncode != 0:
print(f"ffmpeg error:\n{result.stderr}", file=sys.stderr)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
]
print(f"Capturing from {device} ({width}x{height}, warmup={warmup_frames} frames)...")
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
if result.returncode != 0:
print(f"ffmpeg error:\n{result.stderr}", file=sys.stderr)
When an RTSP URL is supplied, the script causes ffmpeg to connect to a network camera without any explicit warning about outbound network access, possible credential exposure in URLs, or privacy implications of capturing from remote streams. In a camera-capture skill, this behavior is functionally expected, but the lack of disclosure can still surprise users and lead to accidental transmission of sensitive camera endpoint information or use of embedded credentials.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
"pipe:1",
]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
buf = b""
try:
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
playlist,
]
proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
try:
while server_running:
No suspicious patterns detected.