Back to skill

Security audit

Kami Image Search

Security checks for vulnerabilities and agentic risk

Overview

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.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
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

T09 · Insecure Skill Coding Practices

Error
Location
image_search.py:467
Finding

Unvalidated API endpoint can receive private images, search text, and the API key

Content
View full analysis
Optional[dict]: """Call Kamivision cloud API, return result dict or None on failure.""" headers = { "Content-Type": "application/json", "X-API-Key": cfg.KAMIVISION_API_KEY, } payload = { "detectType": detect_type, "detectSubType": "", "skillId": "SK_IMAGE_TEXT_SEARCH", "prompt": prompt, "imageFile": image_b64, "videoFile": "", } try: resp = _requests.post(cfg.KAMIVISION_API_URL, headers=headers, json=payload, timeout=60) ``` Image content is serialized before transmission: ```python try: with open(image_path, "rb") as f: img_b64 = base64.b64encode(f.read()).decode("utf-8") result = _kamivision_call(self.cfg, "SUMMARY", image_b64=img_b64) ``` ### Technical Analysis Base64 encoding is a normal method of placing binary image data in JSON and is not, by itself, covert or malicious. Uploading images and search queries is also part of the Skill's declared cloud-analysis functionality. The security issue is that `KAMIVISION_API_URL` is fully controlled by `image_config.json`. The ...[truncated 1907 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
image_search.py:1141
Finding

Unverified PID files allow termination of unrelated same-user processes

Content
View full analysis
str: """PID file path: {DATA_DIR}/{device_id}/capturer.pid""" d = os.path.join(cfg.DATA_DIR, device_id) Path(d).mkdir(parents=True, exist_ok=True) return os.path.join(d, "capturer.pid") def _read_pid(pid_file: str) -> Optional[int]: """Read PID file, return PID or None.""" if not os.path.exists(pid_file): return None try: with open(pid_file, "r") as f: return int(f.read().strip()) except (ValueError, OSError): return None def _is_pid_alive(pid: int) -> bool: """Check if process is alive.""" try: os.kill(pid, 0) return True except OSError: return False ``` ```python def _stop_daemon(cfg: Config, device_id: str) -> dict: """Stop background capture process for a specific camera.""" pid_file = _get_pid_file(cfg, device_id) pid = _read_pid(pid_file) if pid is None: return {"status": "not_running", "device_id": device_id, "message": "No running capture process found"} if not _is_pid_alive(pid): os.remove(pid_file) return {"status": "not_running", "device_id": device_id, "message": f"Process (PID={pid}) no longer exists, PID file cleaned up"} # Send SIGTERM for graceful stop os.kill(pid, signal.SIGTERM) # Wait up to 10 seconds for _ in range(20): if not _is_pid_alive(pid): break _time.sleep(0.5) if _is_pid_alive(pid): os.kill(pid, signal.SIGKILL) _time.sleep(0.5) if os.path.exists(pid_file): os.remove(pid_file) ``` ### Technical Analy ...[truncated 1880 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Error
Location
setup.sh:48
Finding

Setup installs mutable and unpinned third-party code

Content
View full analysis
/dev/null || { print_error "Failed to clone pyenv. Please check network or install manually:" echo " git clone --depth 1 https://github.com/pyenv/pyenv.git \$HOME/.pyenv" ``` ```bash if ! pyenv install 3.10.14; then print_error "pyenv install failed (likely missing build dependencies)." 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 \ libxmlsec1-dev libffi-dev liblzma-dev pyenv install 3.10.14 || { print_error "Still failed. Please check errors above." exit 2 } else print_error "Cannot proceed without Python 3.10." exit 2 fi fi pyenv global 3.10.14 ``` ```bash "$VENV_DIR/bin/pip" install -q -r "$SKILL_DIR/requirements.txt" ``` The dependency file contains no version or hash constraints: ```text opencv-python-headless numpy requests Pillow faiss-cpu hypothesis ``` ### Technical Analysis The pyenv URL is the project's official GitHub repository rather than a pastebin or apparent personal download host. However, `git clone --depth 1` follows the reposito ...[truncated 2377 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (40)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 276)May include surrounding context.

md
- 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

Chaining Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

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.

Content

Scanner excerpt · setup.sh (reported line 73)May include surrounding context.

sh
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 \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
83% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
83% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
84% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
83% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
83% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

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.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

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.

Content

Scanner excerpt · image_search.py (reported line 484)May include surrounding context.

python
"videoFile": "",
    }
    try:
        resp = _requests.post(cfg.KAMIVISION_API_URL, headers=headers,
                              json=payload, timeout=60)
        resp.raise_for_status()
        body = resp.json()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

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.

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 · image_search.py (reported line 1128)May include surrounding context.

python
"--config", config_path, "--device", device_id,
           "--log-file", cam_log]

    proc = subprocess.Popen(
        cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
        start_new_session=True,
    )

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · setup.sh (reported line 25)May include surrounding context.

sh
# ============================================================
# 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)
# ============================================================

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · setup.sh (reported line 41)May include surrounding context.

sh
# ============================================================
# 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)
# ============================================================

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · setup.sh (reported line 43)May include surrounding context.

sh
# ============================================================
# 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)
# ============================================================

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · setup.sh (reported line 65)May include surrounding context.

sh
# ============================================================
# 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)
# ============================================================

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · setup.sh (reported line 197)May include surrounding context.

sh
# ============================================================
# 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)
# ============================================================

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
50% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · setup.sh (reported line 41)May include surrounding context.

sh
"$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)..."

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
97% confidence
Finding

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.

Content

Scanner excerpt · setup.sh (reported line 73)May include surrounding context.

sh
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 \

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.