Back to skill

Security audit

Mediapipe vision

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent local MediaPipe computer-vision skill; main risks are explicit webcam/media processing, local output files, and unpinned Python dependencies.

Install in a virtual environment or container, consider pinning dependencies before production use, and only run webcam or biometric landmark processing with consent from anyone who may be captured. Review output paths carefully because annotated media, JSON, CSV, and mask files may contain sensitive face/body data and can overwrite files at the paths you provide.

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

T08 · Insecure Dependencies

Warning
Location
scripts/requirements.txt:3
Finding

Unpinned Third-Party Executable Dependencies

Content
View full analysis
=0.10.14 opencv-python>=4.8.0 numpy>=1.24.0 ``` The documented installation procedure in `SKILL.md:62` executes: ```bash pip install -r scripts/requirements.txt ``` ### Technical Analysis All three executable Python dependencies specify only a minimum version. No maximum version, exact version, lock file, or cryptographic package hash is provided. Consequently, installations performed at different times may resolve to different package releases that were not reviewed with this project. Python packages can execute code during installation and when imported at runtime. If an upstream account, release process, package repository, or subsequently allowed package version is compromised, following the documented installation procedure could introduce attacker-controlled code. The package names appear legitimate, and the audit found no evidence of typosquatting or a currently malicious package. The risk arises from trusting all future versions without integrity verification. ### Attack Path 1. An attacker compromises the release process or repository account of one of the listed packages. 2. The attacker publishes a malicious version greater than or equal to the declared minimum version. 3. A user follows the documented command: `pip install -r scripts/requirements.txt`. 4. Pip resolves the malicious release because the requirement permits future versions and provides no trusted hash. 5. Malicious package code executes during installation or when the application imports the dependency. ### Impact Assessment Successfully exploited dependency compromise would execute code with the privileges of the user or service account running pip or the MediaPipe script. Depending on those privileges, the attacker could access local file ...[truncated 381 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/run_mediapipe.py:445
Finding

Unbounded Memory Accumulation During Video and Webcam Processing

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code largely matches the declared description: it uses MediaPipe on-device for landmarks, detection, segmentation, and supports image/video/webcam inputs plus legacy Solutions and Tasks APIs. It also outputs annotated media, JSON, and CSV as described. The main description-behavior mismatch is that the legacy API supports an additional selectable mode, 'holistic', which is not mentioned in the declared purpose/triggers. This is a real end-user capability, not just an internal detail. Other differences are not material to purpose: saving a raw segmentation mask and emitting JSON/CSV are consistent with the description. There is also a likely coding bug: OutputWriter is used as a context manager though enter/exit are incorrectly indented under run_pipeline rather than the class, and the CSV row/header shapes appear inconsistent. Those are implementation issues, not description mismatches.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
pip install -r scripts/requirements.txt

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
pip install -r scripts/requirements.txt

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill documents file-writing behavior such as saving annotated images/videos, JSON, CSV, and segmentation masks, but does not declare any explicit tool scope or permissions boundary. In an agent environment, undeclared write capability can lead to unexpected filesystem modification, overwrite of user files, or writing artifacts to sensitive locations if path handling is not constrained.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill can access a live webcam and then save annotated video/images plus structured detection JSON/CSV without any explicit privacy notice, confirmation, or retention controls. In an agent setting this is more sensitive because users may not realize biometric or environmental data from their camera can be captured and persisted to disk.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code appends CSV rows in the order [frame_index, timestamp_ms, kind, landmark_index, x, y, z, visibility, presence] at L514-L518, but the header written at L535-L536 omits timestamp_ms and labels the second column as kind. This inline output documentation actively misdescribes the generated file format, causing consumers to misinterpret exported landmark data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README explicitly promotes live webcam processing but does not warn users about privacy implications such as capturing sensitive imagery, bystanders, or unintended retention of output files. In a computer-vision skill, this omission can lead to unsafe real-world use even if processing is nominally on-device.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill supports live webcam input and even advertises it in examples, but does not warn users about camera activation, local capture of bystanders, or the sensitivity of generated landmark/face data. In agent-driven use, missing disclosure can cause users to unknowingly grant access to a live camera feed or process personal biometric information without clear notice.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

This is a markdown file, so SQP-2 applies to omissions in user-facing warnings. The section provides a direct curl command that performs a network download and writes a file to disk, but the surrounding text does not explicitly warn that it will contact an external host and save model artifacts locally.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency specification uses a lower-bound only version constraint, which allows future unreviewed releases of MediaPipe to be installed. This weakens build reproducibility and can expose consumers to supply-chain risk or breaking changes if a later version introduces a vulnerability or unsafe behavior.

Content

Scanner excerpt · scripts/requirements.txt (reported line 3)May include surrounding context.

text
# MediaPipe Vision Skill - Python dependencies
# Python 3.9-3.12 recommended (see mediapipe release notes for your platform).
mediapipe>=0.10.14
opencv-python>=4.8.0
numpy>=1.24.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

opencv-python>=4.8.0 is unpinned, so installations may resolve to different releases over time, including versions with newly disclosed flaws or incompatible native binaries. Because OpenCV processes untrusted image and video data in this skill, dependency drift can increase exposure to parser-level vulnerabilities.

Content

Scanner excerpt · scripts/requirements.txt (reported line 4)May include surrounding context.

text
# MediaPipe Vision Skill - Python dependencies
# Python 3.9-3.12 recommended (see mediapipe release notes for your platform).
mediapipe>=0.10.14
opencv-python>=4.8.0
numpy>=1.24.0

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
90% confidence
Finding

The manifest does not pin opencv-python, so it is impossible to determine whether the installed version is affected by any of the known OpenCV advisories. In this skill context, that matters more because OpenCV may parse attacker-controlled images or video streams, making vulnerable builds a realistic attack surface.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

numpy>=1.24.0 is also unpinned, which permits non-deterministic installs and makes it harder to verify whether deployed environments include vulnerable or incompatible versions. While NumPy is less directly exposed than a media parser here, uncontrolled upgrades still create avoidable supply-chain and stability risk.

Content

Scanner excerpt · scripts/requirements.txt (reported line 5)May include surrounding context.

text
# Python 3.9-3.12 recommended (see mediapipe release notes for your platform).
mediapipe>=0.10.14
opencv-python>=4.8.0
numpy>=1.24.0

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
84% confidence
Finding

Because numpy is not pinned, the security posture of the installed version cannot be verified against known advisories. This is primarily a supply-chain assurance issue rather than a direct exploitable flaw in the file itself, but it still reduces confidence in deployed safety.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The Tasks mode requires a model path and later opens that file from disk, which is a file-access operation. Although this is part of the feature, the code provides only a parameter description and no explicit warning that a local file will be read; however, this is low severity because loading a model file is closely aligned with the tool's stated purpose.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/run_mediapipe.py (reported line 203)May include surrounding context.

python
def __enter__(self):
        mp = ensure_mediapipe()
        self.mp = mp
        module = getattr(mp.solutions, SOLUTION_MODULES[self.kind])
        common = {"min_detection_confidence": self.min_conf}
        if self.kind == "face":
            self.solver = module.FaceMesh(

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/run_mediapipe.py (reported line 246)May include surrounding context.

python
def serialize(self, results):
        records = []
        for name, field in zip(self.names, self.fields):
            lm_lists = getattr(results, field)
            if lm_lists is None:
                continue
            if not isinstance(lm_lists, (list, tuple)):

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/run_mediapipe.py (reported line 345)May include surrounding context.

python
from mediapipe.tasks import BaseOptions
        from mediapipe.tasks.python import vision as mp_vision
        self.mp_vision = mp_vision
        opts_cls = getattr(mp_vision, TASK_OPTIONS[self.kind])
        running_mode = (mp_vision.VisionRunningMode.IMAGE if self.static
                        else mp_vision.VisionRunningMode.VIDEO)
        kwargs = {

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/run_mediapipe.py (reported line 373)May include surrounding context.

python
kwargs.update(score_threshold=self.min_conf)
        elif self.kind == "image_segmenter":
            kwargs.update(output_category_mask=True, output_confidence_masks=False)
        self.landmarker = getattr(mp_vision, TASK_CREATORS[self.kind]).create_from_options(
            opts_cls(**kwargs))
        return self

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/run_mediapipe.py (reported line 420)May include surrounding context.

python
"face_landmarker": ("face_landmarks", None),
        }[self.kind]
        out = []
        lm_lists = getattr(res, field) or []
        for i, lm_list in enumerate(lm_lists):
            rec = {"kind": self.kind,
                   "landmarks": [{"x": lm.x, "y": lm.y, "z": lm.z} for lm in lm_list]}

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/run_mediapipe.py (reported line 424)May include surrounding context.

python
for i, lm_list in enumerate(lm_lists):
            rec = {"kind": self.kind,
                   "landmarks": [{"x": lm.x, "y": lm.y, "z": lm.z} for lm in lm_list]}
            if label_field and getattr(res, label_field, None) and i < len(getattr(res, label_field)):
                rec["label"] = getattr(res, label_field)[i].category_name
            out.append(rec)
        return out

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/run_mediapipe.py (reported line 425)May include surrounding context.

python
rec = {"kind": self.kind,
                   "landmarks": [{"x": lm.x, "y": lm.y, "z": lm.z} for lm in lm_list]}
            if label_field and getattr(res, label_field, None) and i < len(getattr(res, label_field)):
                rec["label"] = getattr(res, label_field)[i].category_name
            out.append(rec)
        return out

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/run_mediapipe.py (reported line 458)May include surrounding context.

python
if res is None:
            return frame_bgr
        drawing = self.mp.solutions.drawing_utils
        for lm_list in getattr(res, field) or []:
            proto = to_proto_landmark_list(lm_list)
            if proto is not None:
                drawing.draw_landmarks(frame_bgr, proto, connections)

Static analysis

No suspicious patterns detected.