Back to skill

Security audit

kami-conflict-detection

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real conflict-detection tool, but it handles sensitive surveillance footage and has several high-impact privacy and supply-chain risks that need review before installation.

Install only if you are comfortable with selected camera frames leaving your environment for Kami analysis and with alerts or snapshots going to configured third-party channels. Avoid Feishu's sm.ms fallback unless public image hosting is acceptable, protect config.json and logs, use a dedicated low-privilege camera account, and prefer reviewed/pinned setup dependencies and model artifacts.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Findings (5)

T03 · Remote Payload Retrieval and Execution

Error
Location
setup.sh:40
Finding

Remote Installer Is Downloaded and Executed Without Verification

Content
View full analysis
/dev/null; then if command -v curl &> /dev/null; then curl -LsSf https://astral.sh/uv/install.sh | sh elif command -v wget &> /dev/null; then wget -qO- https://astral.sh/uv/install.sh | sh else echo "ERROR: curl or wget is required to install uv." exit 1 fi export PATH="$HOME/.local/bin:$PATH" fi ``` ### Technical Analysis The setup process streams a remote HTTP response directly into `sh`. The downloaded installer is not pinned to a specific release and is not validated using a cryptographic checksum or signature before execution. Although `astral.sh` is the documented installation source for uv, this pattern creates a mutable code-execution channel. The effective installer can change after the Skill has been reviewed. A compromise of the remote distribution service, its deployment process, DNS resolution, or the applicable TLS trust chain could cause arbitrary shell commands to run under the account invoking `setup.sh`. The use of HTTPS protects transport under normal conditions but does not provide artifact-level integrity or ensure that the audited payload is the payload executed later. ### Attack Path 1. Python 3.10 and uv are absent on the target system. 2. The user or agent runs `bash setup.sh`. 3. An attacker compromises or substitutes the response from `https://astral.sh/uv/install.sh`. 4. `curl` or `wget` streams the attacker-controlled response directly to `sh`. 5. The payload executes with all privileges available to the invoking user. 6. The payload can read user-accessible files, alter shell configuration, install persistent user-level components, or replace project artifacts. ### Impact Assessment Successful exploitation provides arbitrary command execution as the user running the ...[truncated 358 chars]
Remediation
View remediation

other

Error
Location
conflict_detector_last.py:393
Finding

Private Surveillance Images Are Automatically Uploaded to a Public Image Host

Content
View full analysis
str: """Upload a local image to the sm.ms anonymous image host. Returns the public https URL on success, or '' on any failure. sm.ms accepts anonymous multipart uploads (no API key required); per-IP daily quota applies. Used by the Feishu push as a fallback to obtain a clickable image URL when no Feishu app credentials are configured. """ if not local_path or not os.path.isfile(local_path): return "" try: with open(local_path, "rb") as f: files = {"smfile": (os.path.basename(local_path), f.read(), "image/jpeg")} resp = requests.post( "https://sm.ms/api/v2/upload", files=files, timeout=15, ) resp.raise_for_status() data = resp.json() if data.get("success") and data.get("data", {}).get("url"): return data["data"]["url"] if data.get("code") == "image_repeated" and data.get("images"): return data["images"] logger.warning(f"sm.ms upload non-success response: {data}") return "" except Exception as e: logger.error(f"Image host upload failed ({local_path}): {e}") return "" ``` The function is invoked automatically by the Feishu notification path: ```python image_key = "" snapshot_url = "" if snapshot_local and app_id and app_secret: image_key = _feishu_upload_image(app_id, app_secret, snapshot_local) # Fallback: public image host URL if not image_key and snapshot_local: snapshot_url = _upload_image_to_imghost(snapshot_local) ``` ### Technical Analysis A snapshot captured from a configured surveillance stream is sent to the anonymous `sm.ms` image-hos ...[truncated 1896 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Error
Location
requirements.txt:1
Finding

Unpinned and Unnecessary Python Dependencies Create Supply-Chain Exposure

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Error
Location
conflict_detector_last.py:790
Finding

Downloaded Model Archive Is Not Integrity-Checked and Is Extracted Without Path Validation

Content
View full analysis
/dev/null; then curl -L --fail -o "$TMPZIP" "$MODEL_URL" elif command -v wget &> /dev/null; then wget -O "$TMPZIP" "$MODEL_URL" else echo "ERROR: curl or wget is required to download the model bundle." exit 1 fi echo "Extracting model bundle..." unzip -o "$TMPZIP" -d "$SKILL_DIR/" fi ``` ### Technical Analysis The model archive is downloaded from a mutable URL without validating a committed checksum or digital signature. HTTPS provides transport security but does not establish that the downloaded artifact is the exact model reviewed by the project. Both extraction implementations trust archive member paths. Py ...[truncated 1540 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
conflict_detector_last.py:1007
Finding

Credential-Bearing Camera URLs Are Persisted and Logged in Plaintext

Content
View full analysis
{cam['rtsp_url']}") ``` The Skill instructs users to provide credential-bearing URL forms and persist them in `config.json`: ```text TP-Link: rtsp://:@:554/stream1 Hikvision: rtsp://:@:554/Streaming/Channels/101 Dahua: rtsp://:@:554/cam/realmonitor?channel=1&subtype=0 ``` ```python def load_config() -> dict: cfg_path = os.path.join(script_dir, "config.json") if not os.path.isfile(cfg_path): return {} try: with open(cfg_path, "r", encoding="utf-8") as f: data = json.load(f) or {} return data if isinstance(data, dict) else {} ``` ### Technical Analysis RTSP URLs commonly include a camera username and password in the URL user-information component. The project directs the agent to write these URLs into `config.json`, reads that plaintext file without enforcing restrictive permissions, and logs the complete URL at startup and when stream opening fails. The file logger writes to `conflict_detector.log` in the project directory. As a result, a single credential can be duplicated into configuration, logs, backups, diagnostic archives, and accidentally committed project copies. Logging also exposes internal camera addresses and stream paths. This behavior is not necessary for conflict detection. Logging a redacted host and camer ...[truncated 1037 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (46)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code uploads conflict snapshot images to public or third-party services, including anonymous sm.ms hosting, without a clear warning that surveillance images may become externally accessible. Because these are snapshots of physical incidents captured by cameras, public hosting materially increases privacy, compliance, and evidentiary risks.

Content

No source excerpt is available for this finding.

Chaining Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

Piping downloaded content into sh is effectively command chaining that converts a network fetch into immediate code execution. In setup context this is especially dangerous because users expect bootstrap scripts to prepare the environment, so a compromised upstream installer can gain full user-level execution and tamper with the virtualenv, PATH, or local files.

Content

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

sh
echo "python3.10 not found. Installing it locally via uv (no sudo required)..."
    if ! command -v uv &> /dev/null; then
        if command -v curl &> /dev/null; then
            curl -LsSf https://astral.sh/uv/install.sh | sh
        elif command -v wget &> /dev/null; then
            wget -qO- https://astral.sh/uv/install.sh | sh
        else

Chaining Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This is the wget equivalent of the curl pipe-to-shell pattern and carries the same remote code execution risk. Any compromise of the remote script source or network trust path results in arbitrary shell commands running during setup.

Content

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

sh
if command -v curl &> /dev/null; then
            curl -LsSf https://astral.sh/uv/install.sh | sh
        elif command -v wget &> /dev/null; then
            wget -qO- https://astral.sh/uv/install.sh | sh
        else
            echo "ERROR: curl or wget is required to install uv."
            exit 1

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

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

sh
unzip -o "$TMPZIP" -d "$SKILL_DIR/" > /dev/null

    if [ -d "$EXTRACT_DIR" ]; then
        find "$EXTRACT_DIR" -name '*.onnx' -exec mv {} "$SKILL_DIR/" \;
        rm -rf "$EXTRACT_DIR"
    fi
    rm -f "$TMPZIP"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README states that frames are sent to a remote multimodal LLM API for conflict analysis, but it does not prominently warn users that camera imagery is being transmitted off-device for third-party processing. For a surveillance workflow, this is privacy-sensitive data handling, and insufficient disclosure can lead users to expose live or recorded footage of people and private spaces without informed consent.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README explicitly documents a fallback that uploads conflict snapshots to the public sm.ms image host, which can expose sensitive camera imagery of people involved in violent incidents to an unrelated third-party public service. In the context of a surveillance/conflict-detection skill, this creates a serious privacy and data-disclosure risk because snapshots may contain faces, interiors, and incident evidence that users may not expect to leave their environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The README explicitly fixes Feishu push language to Chinese and Discord/Telegram push language to English. This imposes a locale/language choice without offering user opt-in, configuration, or justification that the skill is limited to a region-specific deployment.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · README.md (reported line 297)May include surrounding context.

md
4. Add the bot to your target group (or just DM the bot)
5. Get the **chat ID**:
   - DM `@userinfobot` → it replies with your User ID (for private messages)
   - Or call `https://api.telegram.org/bot<TOKEN>/getUpdates` after sending a message in the group → find `"chat":{"id":-100xxxxx}` in the response
   - Group/channel IDs are negative numbers (e.g., `-1001234567890`)

> Push language: **English**

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest and main description present this skill as a detector that monitors camera streams and emits alerts. These sections document interactive bot/channel capabilities for receiving messages and triggering detection or conversational responses via external apps, which is not justified by the narrow purpose of physical-conflict detection and suggests broader control-plane functionality.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill describes capabilities to read and write local files, access the network, and execute shell commands, but it does not declare any explicit tool scope or permissions boundary. That creates a confused-deputy risk where an agent may grant broader-than-necessary authority to a surveillance workflow that can persist configuration, download code or models, and continuously exfiltrate alerts and media off-device.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases are broad and overlap with ordinary requests like 'detect conflict' or 'monitor for fights,' which could cause accidental invocation of a high-impact surveillance skill. In context, accidental activation is more dangerous because the skill is designed to start persistent multi-camera monitoring, modify config, run setup scripts, and send alerts in the same turn.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill performs persistent surveillance, captures and saves clips and snapshots, and transmits data to external services, but the operational description does not provide an immediate, prominent warning or explicit consent flow before use. This is risky because users may not realize that camera footage and event imagery can be retained locally and sent to third parties, including an external API for analysis.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Captured surveillance frames are base64-encoded and sent to a remote detection API without an explicit warning, consent gate, or transmission notice at the point of use. In a camera-monitoring skill, this is sensitive because live or recorded footage of people involved in conflicts may leave the local environment and be processed by a third party.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The duplicate finding reflects the same sensitive outbound transmission of surveillance frames to a remote API. Although functionally expected, it remains a real privacy and data-governance concern in this skill context.

Content

Scanner excerpt · conflict_detector_last.py (reported line 318)May include surrounding context.

python
"videoFile": ""
            }

            response = requests.post('https://kamiclaw-skill-api.kamihome.com/v1/detect', headers=headers, json=json_x)
            logger.info(f"API response: {response.text}")

            response_data = json.loads(response.text)

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The duplicate finding reflects the same sensitive outbound transmission of surveillance frames to a remote API. Although functionally expected, it remains a real privacy and data-governance concern in this skill context.

Content

Scanner excerpt · conflict_detector_last.py (reported line 318)May include surrounding context.

python
"videoFile": ""
            }

            response = requests.post('https://kamiclaw-skill-api.kamihome.com/v1/detect', headers=headers, json=json_x)
            logger.info(f"API response: {response.text}")

            response_data = json.loads(response.text)

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The implementation uploads conflict snapshots to sm.ms and Feishu OpenAPI even though the skill description only mentions stdout, inbox file, Feishu, Discord, and Telegram alerting. This is dangerous because operators may not realize images are being shared with an additional public third-party hosting service, creating an undisclosed surveillance data disclosure path.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
99% confidence
Finding

This uploads local conflict snapshots to sm.ms, an anonymous public image host. In a surveillance skill, that is highly risky because sensitive incident images may be publicly accessible or processed outside approved enterprise controls.

Content

Scanner excerpt · conflict_detector_last.py (reported line 407)May include surrounding context.

python
try:
        with open(local_path, "rb") as f:
            files = {"smfile": (os.path.basename(local_path), f.read(), "image/jpeg")}
        resp = requests.post(
            "https://sm.ms/api/v2/upload",
            files=files,
            timeout=15,

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · conflict_detector_last.py (reported line 434)May include surrounding context.

python
"""
    url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
    body = {"app_id": app_id, "app_secret": app_secret}
    resp = requests.post(url, json=body, timeout=10)
    resp.raise_for_status()
    data = resp.json()
    if data.get("code") != 0:

Tainted flow: 'data' from requests.post (line 413, network input) → requests.post (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · conflict_detector_last.py (reported line 459)May include surrounding context.

python
files = {"image": (os.path.basename(local_path), file_bytes, "image/jpeg")}
        data = {"image_type": "message"}
        headers = {"Authorization": f"Bearer {token}"}
        resp = requests.post(url, headers=headers, data=data, files=files, timeout=15)
        resp.raise_for_status()
        result = resp.json()
        if result.get("code") != 0:

Tainted flow: 'req' from requests.post (line 548, network input) → urllib.request.urlopen (network output)

Medium
Category
Data Flow
Confidence
84% confidence
Finding

The code sends alert contents to an arbitrary webhook_url using urllib.request.urlopen with no host validation or allowlist. If configuration is tampered with, surveillance metadata and potentially sensitive descriptions can be exfiltrated to an attacker-controlled endpoint, and the skill context makes this more serious because the alerts originate from camera monitoring.

Content

Scanner excerpt · conflict_detector_last.py (reported line 552)May include surrounding context.

python
webhook_url, data=data,
            headers={"Content-Type": "application/json; charset=utf-8"},
        )
        with urllib.request.urlopen(req, timeout=5) as resp:
            resp_body = resp.read().decode("utf-8", errors="replace")
            logger.info(f"Feishu push ok ({resp.status}): {resp_body[:200]}")
    except Exception as e:

Tainted flow: 'data' from requests.post (line 413, network input) → requests.post (network output)

Medium
Category
Data Flow
Confidence
88% confidence
Finding

This posts alert payloads and attached conflict snapshots to a configurable Discord webhook without validating the destination. An attacker who can alter config can redirect sensitive surveillance alerts and images to an external endpoint; in this skill, that means leaking camera-derived evidence of physical altercations.

Content

Scanner excerpt · conflict_detector_last.py (reported line 605)May include surrounding context.

python
file_bytes = f.read()
            files = {"files[0]": (filename, file_bytes, "image/jpeg")}
            data = {"payload_json": json.dumps(payload, ensure_ascii=False)}
            resp = requests.post(webhook_url, data=data, files=files,
                                 headers=headers, proxies=proxies, timeout=10)
        else:
            embed["fields"].append({

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This sends alert content to Discord, which is an external third-party messaging platform. In this surveillance context, outbound transmission of incident descriptions, camera identifiers, and possibly snapshot references is sensitive and should be treated as a real data-sharing risk.

Content

Scanner excerpt · conflict_detector_last.py (reported line 615)May include surrounding context.

python
})
            payload = {"embeds": [embed]}
            headers["Content-Type"] = "application/json; charset=utf-8"
            resp = requests.post(webhook_url, json=payload, headers=headers,
                                 proxies=proxies, timeout=5)
        resp.raise_for_status()
        logger.info(f"Discord push ok ({resp.status_code}): {resp.text[:200]}")

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

This sends a conflict snapshot image to Telegram via sendPhoto, which exports sensitive surveillance imagery to a third-party messaging platform. Because the image may depict people engaged in a physical altercation, the privacy and compliance impact is higher than text-only alerting.

Content

Scanner excerpt · conflict_detector_last.py (reported line 659)May include surrounding context.

python
headers = {"User-Agent": "KamiConflictDetector/2.0"}
        proxies = {"https": proxy, "http": proxy} if proxy else None
        if snapshot_image and os.path.isfile(snapshot_image):
            url = f"https://api.telegram.org/bot{bot_token}/sendPhoto"
            with open(snapshot_image, "rb") as f:
                file_bytes = f.read()
            files = {"photo": (os.path.basename(snapshot_image), file_bytes, "image/jpeg")}

Tainted flow: 'data' from requests.post (line 413, network input) → requests.post (network output)

Medium
Category
Data Flow
Confidence
88% confidence
Finding

The Telegram sendPhoto request transmits alert text and a locally saved surveillance snapshot to a remote service based on user-configured bot credentials, with optional proxy routing. While expected functionality, it becomes a real data-exfiltration risk if configuration or proxy settings are maliciously changed, especially in a surveillance skill handling sensitive imagery.

Content

Scanner excerpt · conflict_detector_last.py (reported line 668)May include surrounding context.

python
"caption": text,
                "parse_mode": "HTML",
            }
            resp = requests.post(url, data=data, files=files,
                                 headers=headers, proxies=proxies, timeout=10)
        else:
            url = f"https://api.telegram.org/bot{bot_token}/sendMessage"

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

This is the text-only Telegram message path, still constituting external transmission of security-relevant incident data. While less severe than image upload, it can still leak operational details about conflict events and monitored spaces.

Content

Scanner excerpt · conflict_detector_last.py (reported line 671)May include surrounding context.

python
resp = requests.post(url, data=data, files=files,
                                 headers=headers, proxies=proxies, timeout=10)
        else:
            url = f"https://api.telegram.org/bot{bot_token}/sendMessage"
            text_with_path = (
                text
                + f"\n<b>{html_escape(t['snapshot'])}</b>: "

Static analysis

No suspicious patterns detected.