Back to skill

Security audit

jf-open-pro-traffic-heatmap

Security checks for vulnerabilities and agentic risk

Overview

The skill’s camera heatmap purpose is coherent, but it needs review because it enables recurring indoor monitoring and automatically loads unverified model files from GitHub.

Review before installing. Use it only for authorized camera locations with appropriate notice and retention rules; do not put real JF secrets into scheduled task text; prefer manually installing a vetted model with a verified hash; pin dependencies; and treat generated reports, thumbnails, and summaries as sensitive data.

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 (3)

T08 · Insecure Dependencies

Error
Location
scripts/detect.py:27
Finding
Unverified Remote Model Retrieval and Loading<![CDATA[ ## Vulnerability Details **File Location**: `scripts/detect.py:27-29, 33-58, 80-86` **Vulnerability Type**: Unverified third-party model download and unsafe supply-chain trust **Risk Level**: High ### Vulnerable Code ```python MODEL_DOWNLOAD_URLS = [ ("head-yolov8m.pt", "https://github.com/Abcfsa/YOLOv8_head_detector/raw/main/medium.pt"), ("head-yolov8s.pt", "https://github.com/Abcfsa/YOLOv8_head_detector/raw/main/nano.pt"), ] def _download_model(save_dir: str, max_retries: int = 3) -> bool: """Download model weights from GitHub and retry automatically.""" import urllib.request import time os.makedirs(save_dir, exist_ok=True) for filename, url in MODEL_DOWNLOAD_URLS: target = os.path.join(save_dir, filename) if os.path.exists(target): return True for attempt in range(1, max_retries + 1): try: urllib.request.urlretrieve(url, target) return True except Exception as e: if os.path.exists(target): os.remove(target) if attempt < max_retries: time.sleep(attempt * 5) return False ``` The downloaded file is subsequently passed directly to Ultralytics: ```python models_dir = os.path.join(SKILL_DIR, "models") if _download_model(models_dir): for path in MODEL_PATHS: if os.path.exists(path): return YOLO(path), False ``` ### Technical Analysis When no local model is available, the Skill downloads model artifacts from URLs referencing the mutable `main` branch of a third-party GitHub repository. The downloaded files are accepted solely based on successful transfer and existence on disk. The implementation does not perform any of the following controls: - Verification against a pinned SHA-256 digest - Signature or trusted-manifest verification - Pinning to an immutable release or commit - Validation of the downloaded artifact format - Enf ...[truncated 2090 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin each model to an immutable release artifact or repository commit rather than the mutable `main` branch. 2. Publish an independently reviewed SHA-256 digest with the Skill and verify it before loading: ```python import hashlib EXPECTED_SHA256 = { "head-yolov8m.pt": "<reviewed-sha256>", "head-yolov8s.pt": "<reviewed-sha256>", } def verify_sha256(path, expected): digest = hashlib.sha256() with open(path, "rb") as model_file: for block in iter(lambda: model_file.read(1024 * 1024), b""): digest.update(block) return digest.hexdigest() == expected ``` 3. Download to a uniquely created temporary file in the destination directory. 4. Enforce an expected maximum and minimum artifact size during transfer. 5. Reject redirects whose final scheme or hostname is not explicitly approved. 6. Validate the hash and artifact structure before atomically renaming the temporary file to the trusted model path. 7. Delete the temporary artifact on every validation or loading failure. 8. Prefer a non-executable tensor serialization format, such as `safetensors`, where the model stack supports it. 9. Consider packaging the reviewed model with the Skill or requiring explicit administrator installation instead of automatic retrieval. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/report.py:164
Finding
Stored JavaScript Injection Through Camera Metadata in Generated Reports<![CDATA[ ## Vulnerability Details **File Location**: `scripts/report.py:164-188`; `assets/report-template.html:100-102` **Vulnerability Type**: Stored script injection in an executable HTML script context **Risk Level**: Medium ### Vulnerable Code Camera names and identifiers are copied from configuration into report data: ```python cameras_data.append({ "id": cam_id, "name": cam.get("name", cam_id), "heatmap_base64": heatmap_b64, "time_series": time_series, "stats": stats, "history": history_with_thumbs }) summary = generate_summary(cameras_data, start, end) report_data = { "cameras": cameras_data, "start": start.strftime("%Y-%m-%d"), "end": end.strftime("%Y-%m-%d"), "generated_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "summary": summary } with open(TEMPLATE_PATH, "r", encoding="utf-8") as f: template = f.read() html = template.replace("__REPORT_DATA__", json.dumps(report_data, ensure_ascii=False)) ``` The serialized JSON is inserted directly into an executable script element: ```html <script> var REPORT_DATA = __REPORT_DATA__; var currentCamera = REPORT_DATA.cameras[0].id; ``` ### Technical Analysis `json.dumps()` safely escapes JSON string delimiters, but it does not make arbitrary JSON safe for direct insertion into an HTML `<script>` element. In particular, a JSON string may contain the literal sequence `</script>`. HTML parsers recognize the closing `</script>` sequence even when it appears inside a JavaScript string literal. A malicious camera name can therefore terminate the report's original script element and introduce a new executable HTML script element. For example, the following configured camera name is sufficient to break out of the data context: ```text </script><script>alert(document.domain)</script> ``` Later use of `textContent` for camera labels does not prevent exploitation because the injected payload executes while the browser initially parses the generated report, ...[truncated 2019 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not insert ordinary JSON directly into an executable script context. 2. Prefer a non-executable JSON container: ```html <script id="reportData" type="application/json">__REPORT_DATA__</script> <script src="report.js"></script> ``` Parse it with: ```javascript var REPORT_DATA = JSON.parse( document.getElementById('reportData').textContent ); ``` 3. Before embedding JSON in HTML, escape HTML-significant characters: ```python serialized = json.dumps(report_data, ensure_ascii=False) serialized = ( serialized .replace("&", "\\u0026") .replace("<", "\\u003c") .replace(">", "\\u003e") .replace("\u2028", "\\u2028") .replace("\u2029", "\\u2029") ) html = template.replace("__REPORT_DATA__", serialized) ``` 4. Apply schema validation to camera metadata: - Enforce reasonable maximum lengths. - Require camera identifiers to match an expected restricted character set. - Reject control characters in display names. 5. Continue using `textContent` rather than `innerHTML` for values derived from configuration or databases. 6. Replace the remaining dynamically assembled `innerHTML` output with DOM creation and `textContent` where practical. 7. Add a restrictive Content Security Policy and move trusted JavaScript to an external file so inline scripts can be disallowed. 8. Add regression tests that generate reports with values including: - `</script><script>alert(1)</script>` - `<img src=x onerror=alert(1)>` - Ampersands, Unicode separators, quotation marks, and backslashes 9. Verify in tests that no attacker-provided string can terminate the report-data container or create an executable element. ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding
Unbounded and Non-Reproducible Third-Party Dependencies<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-6` **Vulnerability Type**: Unpinned dependencies without integrity hashes **Risk Level**: Low ### Vulnerable Code ```text # traffic-heatmap-skill dependencies opencv-python>=4.8.0 numpy>=1.24.0 ultralytics>=8.0.0 requests>=2.28.0 matplotlib>=3.7.0 ``` ### Technical Analysis Every dependency uses an unrestricted lower-bound version constraint. As a result, future installations may retrieve any later package version from the configured package index without requiring a repository change or renewed review. The dependency set also lacks cryptographic hashes or a lock file. Builds are therefore not reproducible and cannot verify that downloaded distributions match reviewed artifacts. The `requests` package is listed even though the implementation scan found no use of it. This contradicts the Skill documentation, which states that `requests` is not needed, and unnecessarily expands the dependency and transitive-dependency surface. This finding does not establish that any currently named package is malicious. The risk arises from accepting mutable future package-index state and unnecessary components. ### Attack Path 1. A dependency account, release process, package-index entry, or future package release is compromised. 2. A user installs the Skill's dependencies after the compromised version becomes available. 3. Because the requirement specifies only a lower bound, the package installer selects the affected newer version. 4. Because no hashes are supplied, the installer has no project-provided integrity value against which to validate the distribution. 5. Malicious package installation hooks or imported package code execute with the installing or runtime user's privileges. ### Impact Assessment A compromised dependency can execute with the privileges of the Python installation or Skill process. Depending on when malicious code runs, it may gain access to: - The Python environment a ...[truncated 468 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `requests` unless a concrete implementation requirement is introduced. 2. Pin each direct dependency to a reviewed version rather than using unrestricted lower bounds. 3. Generate a lock file that includes all transitive dependencies. 4. Record hashes for every permitted distribution and install with hash enforcement, for example: ```bash python -m pip install --require-hashes -r requirements.lock ``` 5. Generate lock files separately for supported Python versions and operating systems where binary wheels differ. 6. Use an approved package index or internal mirror with provenance and access controls. 7. Run dependency vulnerability and license scanning in continuous integration. 8. Update dependencies through a controlled review process that includes tests for model loading, image parsing, report generation, and database behavior. 9. Document the exact supported Python and dependency versions in `SKILL.md` so installation instructions match the reviewed environment. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (34)

Missing User Warnings

High
Confidence
95% confidence
Finding
The skill centers on surveillance capture, head/person detection, and occupancy reporting but does not prominently warn users about privacy, consent, retention, and monitoring implications. In this context, missing notice is dangerous because the skill processes potentially sensitive imagery and behavioral data from indoor spaces, where legal and policy requirements are often strict.

Missing User Warnings

High
Confidence
95% confidence
Finding
The scheduled collection and IM push workflow enables persistent monitoring and external transmission of summaries without a concentrated warning about surveillance scope, recipients, retention, and data-sharing implications. Because this converts a manual analysis skill into ongoing automated observation and reporting, the privacy and governance risk is materially higher.

Ssd 3

High
Confidence
99% confidence
Finding
The example scheduled-task message explicitly includes full credential values and instructs later steps to read and use them. This is a direct secret-handling vulnerability: natural-language payloads are likely to be stored, logged, displayed, copied, or audited in places not meant for secret storage, enabling credential theft and replay.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The scheduled-task template instructs embedding raw JF_UUID, JF_APP_KEY, JF_APP_SECRET, and JF_MOVE_CARD values directly into the payload message. That propagates secrets into task definitions, logs, and any downstream systems that can inspect or replay the scheduled job, creating a clear credential exposure path beyond the heatmap feature itself.

Lp3

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding
The skill documents file reads/writes and network access, but it does not declare an explicit tool scope such as permissions or allowed-tools. In practice this weakens least-privilege controls and makes it easier for an agent runtime to grant broader capabilities than the skill actually needs, especially given it also handles captures, reports, and model downloads.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The trigger list contains broad everyday phrases such as usage/help wording that may overlap with ordinary conversation. That increases the chance of accidental activation of a skill that performs monitoring-related actions, file operations, network access, and potentially scheduled surveillance workflows without sufficiently explicit user intent.

Intent-Code Divergence

Medium
Confidence
87% confidence
Finding
The file explicitly states that device communication should be handled by dependent JF skills and notes that `requests` is not needed because communication is delegated. Later, it says `detect.py` will automatically download model weights from GitHub if missing, which is active network behavior performed by this skill itself; that contradicts the presented intent that the skill does not need its own outbound communication.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill states that model files may be automatically downloaded from GitHub if missing, but does not provide a prominent warning about network access, integrity risk, or supply-chain implications. Downloading executable model artifacts at runtime from a third-party source can expose users to tampering, unexpected egress, and reproducibility problems.

Vague Triggers

Medium
Confidence
87% confidence
Finding
The workflow allows the agent to enter the skill when it merely 'judges' the user may be a first-time user, which is a vague activation condition. In a skill that manages monitoring devices and can schedule recurring collection, ambiguous auto-entry increases the risk of unintended execution and privacy-impacting actions.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The HTML document declares `lang="zh-CN"`, and the visible UI text throughout the template is fixed in Chinese. This indicates a hard-coded language/locale choice without any user opt-in or documented justification, which matches the language/locale policy violation criteria.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The module description, CLI help text, and rendered summary strings are all hard-coded in Chinese, and the code explicitly searches for Chinese fonts. There is no opt-in, language selection, or documentation that this skill is intentionally limited to a Chinese-speaking or region-specific context.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
This code saves intermediate and final image files to disk, including a summary labeled as office traffic data, but provides no confirmation prompt, warning comment, or disclosure message beyond printing the output path. Because the output appears to summarize potentially sensitive workplace activity data, the file-writing behavior lacks visible user disclosure required by the rule.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The user-facing natural language in the module docstring and CLI argument descriptions is entirely Chinese, which implies the skill is intended to operate in a fixed language/locale without offering a choice. The policy specifically calls for flagging language or locale constraints when they are forced without opt-in or documented justification.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The schema stores camera passwords directly in the `cameras` table as plaintext (`password TEXT NOT NULL`), which creates immediate credential exposure risk if the SQLite file is copied, backed up insecurely, logged, or accessed by another local user/process. In this skill’s context, those credentials likely grant access to surveillance cameras, so compromise can expose live feeds, allow reconfiguration, or enable broader network pivoting depending on camera capabilities.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The code hardcodes external GitHub URLs and will fetch model weights at runtime when local files are absent. Pulling code-adjacent artifacts from the network without declaration, integrity verification, or an explicit trust step creates a supply-chain risk and breaks expectations for an offline/local video-analysis skill.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The function automatically retrieves and persistently stores model artifacts from external URLs into a shared local directory. Because the downloaded `.pt` files are then loaded by the ML framework, a compromised upstream source or man-in-the-middle scenario could introduce malicious or unsafe model artifacts, making this a meaningful supply-chain exposure beyond simple heatmap processing.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill performs network download and local file write behavior automatically, without explicit warning, approval, or a visible security boundary. This is risky because operators may believe they are running a local analytics workflow while the code silently reaches out to third-party infrastructure and persists artifacts that later affect execution.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The module docstring is written as a Chinese-only user-facing description, and the generated summaries and status labels throughout the script are also hard-coded in Chinese. This creates a language/locale restriction without any opt-in or explanation that the skill is intended only for a Chinese-speaking or region-specific context.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# traffic-heatmap-skill dependencies
opencv-python>=4.8.0
numpy>=1.24.0
ultralytics>=8.0.0
requests>=2.28.0
Confidence
98% confidence
Finding
The dependency is specified with a lower-bound range instead of an exact pinned version, which makes builds non-reproducible and can unintentionally pull in vulnerable or compromised releases over time. In a computer-vision skill that processes external inputs and likely runs unattended, supply-chain drift increases the chance of introducing exploitable package behavior without code changes.

Unverifiable Dependency: opencv-python has 16 known advisory(ies) (CVE-2017-12864 (Integer Overflow or Wraparound in OpenCV); CVE-2017-12598 (Out-of-bounds Read in OpenCV ); CVE-2019-14493 (NULL Pointer Dereference in OpenCV.) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
93% confidence
Finding
The manifest does not identify which opencv-python release will actually be installed, so known CVEs affecting some versions cannot be ruled out. In a skill that processes image data from cameras, vulnerable native code in OpenCV could increase exposure to memory-safety issues triggered by crafted media or input handling.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# traffic-heatmap-skill dependencies
opencv-python>=4.8.0
numpy>=1.24.0
ultralytics>=8.0.0
requests>=2.28.0
matplotlib>=3.7.0
Confidence
98% confidence
Finding
Using an unpinned numpy version allows future installs to resolve to different releases, including versions with security defects or breaking behavior. Although this file alone does not prove exploitation, it creates a real supply-chain risk because the installed package version cannot be controlled or audited precisely.

Unverifiable Dependency: numpy has 16 known advisory(ies) (CVE-2014-1859 (Numpy arbitrary file write via symlink attack); CVE-2021-41495 (NumPy NULL Pointer Dereference); CVE-2021-33430 (NumPy Buffer Overflow (Disputed)) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
91% confidence
Finding
Because numpy is not pinned, it is impossible to verify whether the installed version is affected by any of the listed advisories. This creates avoidable uncertainty in the deployment's security posture and may expose native extension attack surface if vulnerable builds are resolved.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# traffic-heatmap-skill dependencies
opencv-python>=4.8.0
numpy>=1.24.0
ultralytics>=8.0.0
requests>=2.28.0
matplotlib>=3.7.0
Confidence
99% confidence
Finding
The unpinned ultralytics dependency is more concerning because this package family has had a documented malicious-package incident. A version range means installations may retrieve an unsafe release, turning a dependency-management issue into a potential code-execution or cryptominer supply-chain compromise.

Unverifiable Dependency: ultralytics has 1 known advisory(ies) (PYSEC-2024-154 (A number of releases of ultralytics contained malicious crypto miner software.)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
99% confidence
Finding
The unverifiable ultralytics dependency is particularly dangerous because there is a known advisory involving malicious crypto-miner software in certain releases. Without version pinning, an installation could fetch a compromised package, leading to arbitrary code execution, resource theft, or persistence on the host.

Unpinned Dependencies

Low
Category
Supply Chain
Content
opencv-python>=4.8.0
numpy>=1.24.0
ultralytics>=8.0.0
requests>=2.28.0
matplotlib>=3.7.0
Confidence
97% confidence
Finding
Leaving requests unpinned permits silent upgrades to releases that may contain security regressions or unresolved advisories. Because this skill likely communicates with cameras or remote endpoints, dependency drift in an HTTP client can affect transport security, credential handling, or request validation.

Static analysis

No suspicious patterns detected.