T09 · Insecure Skill Coding Practices
- Location
image_search.py:618- Finding
Camera credentials and API secrets are stored and logged without adequate protection
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This camera-search skill appears purpose-built, but it handles private images and credentials with enough overbroad and under-protected behavior that users should review it carefully before installing.
Install only if you are comfortable sending selected camera frames, imported images, and search text to Kamivision. Before use, restrict image_config.json and log-file permissions, avoid embedding camera passwords in stream URLs when possible, verify KAMIVISION_API_URL is the intended HTTPS Kami endpoint, review setup.sh before running it, and do not approve sudo package installation unless you accept system-wide changes.
image_search.py:618Camera credentials and API secrets are stored and logged without adequate protection
image_search.py:467Unvalidated API endpoint can receive private images, search text, and the API key
image_search.py:1141Unverified PID files allow termination of unrelated same-user processes
setup.sh:48Setup installs mutable and unpinned third-party code
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- Captured frames are stored in the working directory; users can delete them at any time
- Supports `retention_days` parameter for automatic expiration and deletion of historical data
- API Key is cached in `~/.kami/credentials.json` (permission 600, readable only by the current user)
### User Control
The chained sudo apt update && sudo apt install -y combines repository metadata refresh and package installation in one privileged flow. In the context of a camera-history/image-search skill, this is more dangerous because the installer is expected to set up an application, not perform broad root-level host administration; that mismatch increases the chance users will approve changes they do not fully expect.
echo ""
read -p "Install build dependencies with sudo? [y/N] " confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
sudo apt update && sudo apt install -y \
make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev \
libncursesw5-dev xz-utils tk-dev libxml2-dev \
The README explicitly states that camera frames and local images are sent to the Kamivision cloud API for description generation and embeddings, but it does not provide a clear privacy, consent, retention, or data-handling warning. In a smart-home camera context, this is sensitive visual data that may contain people, interiors, and private activities, so omission of disclosure and guidance materially increases privacy and compliance risk.
The skill documents capabilities to run shell commands, read and write files, and access network resources, but it does not declare any explicit tool scope or permissions boundary. In an agent environment, this creates an authorization gap where a user may invoke a skill with powerful side effects without clear, enforced least-privilege constraints.
The trigger phrase search image is close to built-in search semantics and may shadow or intercept generic search requests. Because this skill can access camera history and invoke cloud analysis, accidental routing to this skill could reveal sensitive visual data or cause unintended processing.
The trigger phrase find image overlaps with generic built-in find behavior and can cause ambiguous or unintended invocation. In this skill's context, that ambiguity is more dangerous because invocation may expose local or captured imagery and send related queries to an external service.
The trigger search camera is highly generic and likely to conflict with standard search or device-control language. Given the skill operates on home camera feeds, an unintended trigger could start privacy-sensitive searches across stored frames and return information about occupants, visitors, or household activity.
The phrase find photo is a generic command pattern that can shadow native assistant functionality. In this context, accidental invocation is privacy-relevant because the skill may access imported images or stored camera frames and return sensitive visual results.
The trigger search photos is broad and overlaps with normal assistant or system photo-search actions. Because this skill spans local image stores, camera captures, and cloud processing, misrouting ordinary photo queries here could expose sensitive media or cause unexpected external API use.
The trigger list contains broad, natural phrases such as search- and find-related terms that are likely to overlap with ordinary user intent. In a skill that can access cameras, local files, cloud APIs, and shell-based setup, unintended invocation could expose sensitive imagery or initiate data processing without sufficiently explicit user intent.
The setup flow describes enabling capture and cloud analysis without prominently warning that frames and imported images may contain sensitive personal, household, or bystander data. In the context of home cameras and cloud inference, insufficient upfront disclosure increases the risk of uninformed consent and accidental transmission of highly sensitive visual data.
The privacy notice says the API key is cached in ~/.kami/credentials.json, while earlier instructions direct the user to store and update it in image_config.json. This inconsistency can cause users and reviewers to misunderstand where sensitive credentials reside, leading to weaker protection, accidental disclosure, or incomplete cleanup when rotating or deleting secrets.
This code performs external network transmission of image and text content to a cloud API, using an endpoint configurable by local configuration. The transmission itself is intentional, but in this skill context it handles smart-home camera data, so any misconfiguration, unexpected third-party processing, or insufficient user awareness can cause serious privacy exposure.
"videoFile": "",
}
try:
resp = _requests.post(cfg.KAMIVISION_API_URL, headers=headers,
json=payload, timeout=60)
resp.raise_for_status()
body = resp.json()
The skill base64-encodes captured or imported images and sends them to a remote Kamivision API for summarization and embedding without an explicit runtime warning, consent prompt, or clear local-only alternative. In a smart-home camera context, this can expose highly sensitive interior, occupant, and bystander imagery to a third party, making the privacy impact substantially more serious than in a generic image-processing tool.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
"--config", config_path, "--device", device_id,
"--log-file", cam_log]
proc = subprocess.Popen(
cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
start_new_session=True,
)
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
# ============================================================
# Step 1: Check / install Python 3.10
# Strategy aligned with kami-smarthome-suite:
# - Debian/Ubuntu : conda > pyenv > system python3.10 (avoid sudo for venv)
# - Other systems : system python3.10 > pyenv > conda
# - Auto-install fallback: conda > pyenv (no sudo)
# ============================================================
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
# ============================================================
# Step 1: Check / install Python 3.10
# Strategy aligned with kami-smarthome-suite:
# - Debian/Ubuntu : conda > pyenv > system python3.10 (avoid sudo for venv)
# - Other systems : system python3.10 > pyenv > conda
# - Auto-install fallback: conda > pyenv (no sudo)
# ============================================================
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
# ============================================================
# Step 1: Check / install Python 3.10
# Strategy aligned with kami-smarthome-suite:
# - Debian/Ubuntu : conda > pyenv > system python3.10 (avoid sudo for venv)
# - Other systems : system python3.10 > pyenv > conda
# - Auto-install fallback: conda > pyenv (no sudo)
# ============================================================
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
# ============================================================
# Step 1: Check / install Python 3.10
# Strategy aligned with kami-smarthome-suite:
# - Debian/Ubuntu : conda > pyenv > system python3.10 (avoid sudo for venv)
# - Other systems : system python3.10 > pyenv > conda
# - Auto-install fallback: conda > pyenv (no sudo)
# ============================================================
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
# ============================================================
# Step 1: Check / install Python 3.10
# Strategy aligned with kami-smarthome-suite:
# - Debian/Ubuntu : conda > pyenv > system python3.10 (avoid sudo for venv)
# - Other systems : system python3.10 > pyenv > conda
# - Auto-install fallback: conda > pyenv (no sudo)
# ============================================================
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
"$python_bin" -m venv --help >/dev/null 2>&1
}
# Install pyenv + Python 3.10.14 (no sudo for pyenv itself; build deps may need sudo)
install_pyenv() {
print_info "Installing pyenv (no sudo required)..."
The setup script goes beyond isolated skill setup and can clone pyenv from GitHub, create conda environments, and optionally install system-wide build dependencies with apt. For an end-user image search skill, this expands the trust boundary and can materially alter the host environment, increasing supply-chain and local system modification risk even if the author likely intended convenience rather than harm.
This line conditionally executes sudo apt update && sudo apt install -y after an interactive prompt, allowing the skill setup flow to trigger system-wide package installation as root. Even with confirmation, embedding privileged package management in a skill installer is dangerous because it alters the host beyond the skill sandbox and increases the blast radius of mistakes or downstream package compromise.
echo ""
read -p "Install build dependencies with sudo? [y/N] " confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
sudo apt update && sudo apt install -y \
make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev \
libncursesw5-dev xz-utils tk-dev libxml2-dev \
L280 states the skill 'will not auto-discover or connect to cameras,' but the core documented functionality is to monitor camera feeds and capture frames from configured RTSP/RTMP/HTTP stream URLs (for example L63, L68, L114, and the start-capture commands at L168-L174). While it likely means it does not auto-discover cameras, the wording contradicts the described connection behavior.
The config points to a fixed region/service endpoint in natural-language-identifiable form ("kamiclaw-skill-api.kamihome.com") with no indication that this locale or jurisdiction choice is optional or documented. Under the policy rule, forcing a specific locale or regional service without user opt-in or clear justification can be a natural-language policy concern.
No suspicious patterns detected.