T09 · Insecure Skill Coding Practices
- Location
src/config.py:22- Finding
Camera credential file is created without enforced restrictive permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
SmartEye discloses that it views and controls cameras, but its handling of camera credentials, saved snapshots, and broad activation phrases needs review before installation.
Install only if you intend to let the agent access private camera feeds and PTZ controls. Use dedicated low-privilege camera accounts, restrict the camera config file permissions, avoid shared machines for VLC live viewing, review or disable broad triggers for multi-camera capture, and periodically delete saved snapshots.
src/config.py:22Camera credential file is created without enforced restrictive permissions
src/protocol/brands/tplink.py:104Camera credentials are exposed through VLC process arguments
The view and control triggers include short, generic actions like '看看', '分析', '截图', and PTZ commands that may be matched without strong scoping. This increases the chance that ordinary conversation or ambiguous commands will cause camera snapshots, stream access, or physical PTZ movement, which affects both privacy and safety in the monitored environment.
The multi-camera search triggers such as '帮我找', '在哪里', and '有没有' are very broad and overlap with normal conversation. In a voice- or chat-driven agent, this can cause unintended activation that captures images from all configured cameras and sends them for analysis, creating privacy exposure and potentially opening live surveillance actions without clear user intent.
The configuration marks pan, tilt, and zoom as "supported": true, but the inline notes explicitly say the fixed-lens camera cannot physically rotate or change zoom. This is an active contradiction between the documented intent in the notes and the declared operational capability in the same config.
This code file contains user-facing natural-language guidance entirely in Chinese, including safety instructions, but does not indicate that the skill is region-specific or provide any opt-in/alternative language. Per the policy, forcing a specific language without user choice is a natural-language policy violation.
The code launches an external executable using a path taken directly from configuration, which can cause arbitrary local program execution if that configuration is tampered with. Although subprocess.Popen is invoked without shell=True, reducing shell injection risk, the danger remains because an attacker who can modify vlc_path can make the application execute any binary under the agent's privileges.
return False
rtsp = self.get_rtsp_url()
try:
subprocess.Popen([vlc_path, rtsp], start_new_session=True)
return True
except Exception:
return False
The dispatcher and default stop implementation route to ONVIF device-control operations such as continuous movement, absolute movement, and stop, including a direct self.onvif.stop(self.profile_token) call at L84. These actions can affect physical device behavior, but the file contains no confirmation prompt, user-facing logging, or explicit warning text describing that commands will be sent to a camera over the network.
The module docstring states '鉴权关闭,无密码' and emphasizes no hardcoded credentials, which conveys that this integration operates without authentication. However, get_rtsp_url URL-encodes self.user and self.pass_ and embeds them into an RTSP URL, indicating credential-based access is used in practice for streaming.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
return False
rtsp = self.get_rtsp_url()
try:
subprocess.Popen([vlc, rtsp], start_new_session=True)
return True
except Exception:
return False
The SSL context disables hostname checking and certificate validation, which weakens transport security for requests sent by this module. The file does not include any warning, comment, or user disclosure explaining this safety-impacting behavior or its risks.
This code performs HTTP requests to a device control endpoint and is used by movement functions such as ContinuousMove, AbsoluteMove, and Stop, which can directly affect physical device behavior. Although there is a brief module comment about workspace files, there is no confirmation prompt, logging, or user-facing warning in this file that camera-control commands will be transmitted over the network.
This code exposes movement operations for a network-connected camera, including absolute move, continuous move, stop, and home positioning, but provides no user-facing disclosure, confirmation, or warning that these calls will physically move the device. Physical control of surveillance equipment can affect privacy and system behavior, so some visible warning is expected when such actions are invoked.
The function constructs and returns an RTSP URL containing username and password in the authority component. Even with URL encoding, embedding secrets directly in a reusable string increases the chance of credential leakage through logs, exceptions, telemetry, UI display, clipboard use, or downstream storage by callers.
Adding an external process-launch capability to a PTZ control module increases attack surface and crosses from device control into local command execution. In this context, the feature is not necessary for core PTZ behavior and becomes more dangerous because it can be triggered in environments where the agent has desktop or host access, potentially exposing camera credentials and enabling abuse of local execution paths.
This code passes a credential-bearing RTSP URL to an external VLC process without any disclosure or containment. That creates additional leakage paths because command-line arguments may be visible to local process inspection tools, crash reports, desktop integration, or player logs, exposing camera credentials beyond the current process.
The code launches an external executable using a path taken from configuration, which creates a trust boundary issue: if an attacker can influence vlc_path, they can cause arbitrary local program execution under the agent's privileges. Although subprocess.Popen is invoked without a shell and thus avoids classic shell injection, it still executes whatever binary path is supplied and passes a credential-bearing RTSP URL to that process.
return False
rtsp = self.get_rtsp_url()
try:
subprocess.Popen([vlc, rtsp], start_new_session=True)
return True
except Exception:
return False
This code sends SOAP requests over the network to ONVIF endpoints and injects WS-UsernameToken authentication derived from the provided credentials. Although the module docstrings describe functionality, there is no confirmation prompt, user-facing log, or explicit warning that credentials and camera-control commands will be transmitted to a remote device.
The code advertises WS-Security header injection, computes a nonce and password digest, and then does nothing with them because _add_wsse_header ends with pass. As a result, requests are sent without the expected authentication header, which can cause unauthenticated PTZ/media operations, fallback to weaker behavior by integrators, or deployment of a client that operators wrongly believe is authenticated.
_ptz_envelope claims to construct a SOAP envelope with WSSE authentication, but emits <soap-env:Header/> with no security content. In this context, the skill controls cameras via ONVIF PTZ, so a false sense of authentication is especially risky because sensitive device-control traffic may be issued assuming it is protected when it is not.
The skill can launch a live camera stream in VLC from a simple natural-language command without any confirmation, safety warning, or access-control step visible here. In the context of surveillance devices, this can expose real-time private footage to an operator or local session unexpectedly, making the privacy impact more serious than a generic media-open action.
The skill captures screenshots from all configured cameras and saves them to disk, then returns file paths for later analysis, without any consent check, retention policy, or user-facing privacy notice in this code path. In a camera-control skill, silent persistence of images increases privacy risk because sensitive scenes may be recorded and left on disk for unintended access or later misuse.
The script's title, status messages, and test inputs are all hard-coded in Chinese, indicating a fixed language/locale experience. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is explicitly justified, which is not present here.
The natural-language warning comment is written only in Chinese, which imposes a language choice on readers of this configuration without offering an alternative or documenting a locale-specific scope. Under the stated policy, language-specific instructions should be opt-in or clearly justified.
The dependency specification uses a broad lower-bound version (opencv-python>=4.8.0) rather than pinning to a known-safe release, so installations may resolve to different versions across environments and could include vulnerable releases if advisories affect allowed versions. Because this skill interfaces with camera/image processing, it may ingest untrusted image or video data, which increases the practical relevance of OpenCV parsing and memory-safety CVEs.
The natural-language documentation includes Chinese instructions and operational text but does not indicate that the user can choose another language or that the package is intentionally region-specific. This can violate a language/locale policy when a skill implicitly forces one language without opt-in.
The module docstring and subsequent inline documentation are written entirely in Chinese, and there is no indication that language choice is optional or that the skill is intentionally limited to a Chinese-speaking context. Under the policy rules, forcing a specific language without user opt-in is a natural-language policy concern.