Back to skill

Security audit

GoAI Image to PPT

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its image-to-PPT purpose, but it should be reviewed because it uploads user files, uses an API key, allows endpoint override, and automatically opens downloaded output without strong validation.

Install only if you are comfortable sending selected images or PDFs to GoAI and storing a GOAI_API_KEY for the skill. Do not set GOAI_BASE_URL unless you fully trust that endpoint and are using an appropriate key. Treat generated PPT files like internet downloads: review the saved file path before opening, and prefer a sandboxed viewer for sensitive environments.

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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/common.py:59
Finding

API Key Can Be Transmitted to an Arbitrary Configured Endpoint

Content
View full analysis
dict[str, str]: headers = {"Accept": "application/json"} if auth_mode == "auth": headers["Authorization"] = f"Bearer {self.api_key}" return headers ``` ```python def json_request( self, method: str, url: str, auth_mode: str, *, query: dict[str, Any] | None = None, body: dict[str, Any] | None = None, ) -> dict[str, Any]: try: response = self._http.request( method, url, headers=self._headers(auth_mode), params=query, json=body, ) ``` ### Technical Analysis The API destination is taken directly from `GOAI_BASE_URL` without validating its scheme or hostname. Authenticated requests then include `GOAI_API_KEY` as a bearer token. Although endpoint overriding is documented, the implementation does not ensure that the override uses HTTPS or belongs to a trusted GoAI domain. A malicious or accidentally unsafe environment configuration can consequently redirect authenticated requests to an attacker-controlled server. An `http://` override could additionally expose credentials and request data to a network observer. This behavior exceeds least privilege because a production credential should only be disclosed to the service origin for which it was issued. ### Attack Path 1. An attacker, compromised launcher, or unsafe configuration modifies `GOAI_BASE_URL`. 2. The user invokes the Skill with a valid `GOAI_API_KEY`. 3. `GoAIClient` builds conversion and signing URLs from the attacker-controlled base URL. 4. `_headers(" ...[truncated 663 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/common.py:366
Finding

Backend-Controlled Download Is Automatically Opened Without Validation

Content
View full analysis
str: if not media_url: raise GoAIError("download URL is required") output_path = Path(output_name).expanduser() if not output_path.is_absolute(): output_path = (Path.cwd() / output_name).resolve() output_path.parent.mkdir(parents=True, exist_ok=True) try: response = self._http.get(media_url) except httpx.RequestError: raise GoAIError(f"download failed: {media_url}") from None if response.status_code not in {200, 201}: raise GoAIError(f"download failed: {media_url}") output_path.write_bytes(response.content) return str(output_path) ``` ```python def open_local_ppt(path: str) -> None: system = platform.system() try: if system == "Darwin": subprocess.run(["open", path], check=True, capture_output=True) elif system == "Linux": subprocess.run(["xdg-open", path], check=True, capture_output=True) elif system == "Windows": subprocess.run(["start", "", path], check=True, shell=True, capture_output=True) except subprocess.CalledProcessError: pass ``` ```python download_url = client.poll_task( f"{client.base_url}/api/v2/convert/images-to-ppt/{job_id}", "downloadUrl", interval_seconds=5, max_attempts=120, timeout_message="Images to PPT conversion timed out", ) output_path = client.download_media(download_url, f"goai-images-{job_id}.pptx") open_local_ppt(output_path) ``` ### Technical Analysis The conversion backend supplies `downloadUrl`, but the client does not validate its scheme, hostname, destination address, MIM ...[truncated 1800 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
pyproject.toml:1
Finding

Dependency Installation Is Not Reproducibly Locked

Content
View full analysis
=3.10" dependencies = [ "httpx>=0.27,<1", ] ``` ### Technical Analysis The project permits any `httpx` version from 0.27 up to, but excluding, 1.0. No `uv.lock` file is present in the audited project, even though `SKILL.md` states that the dependency set comes from both `pyproject.toml` and `uv.lock`. On a fresh system, `uv` may resolve and install a different dependency graph over time. This weakens reproducibility and expands supply-chain exposure because newly released versions and transitive dependencies may be installed without being represented in the reviewed artifact. No malicious or typosquatted dependency was identified. The risk arises from mutable dependency resolution rather than from confirmed malicious package content. ### Attack Path 1. The Skill runs on a machine without its prepared local environment. 2. Bootstrap invokes `uv run --project`. 3. Because no lockfile is present, `uv` resolves the allowed dependency versions from the configured package source. 4. A newly released, compromised, or otherwise unsafe permitted package version is selected. 5. Package code executes within the Skill's Python environment and receives the process environment and the same local and network access available to the Skill. ### Impact Assessment A compromised dependency could access image inputs, environment variables such as `GOAI_API_KEY`, network connections, and files available to the invoking user. The practical likelihood is reduced because the declared package is the legitimate `httpx` project and its major-version range is bounded, but the missing lockfile prevents deterministic review and deployment. ]]>
Remediation
View remediation
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (18)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose is image-to-PPT conversion, but the documented behavior also includes runtime bootstrapping, interpreter acquisition, dependency installation, and self-reexecution through uv. Even if operationally legitimate, this expands execution behavior beyond what the description advertises and can mask supply-chain, persistence, or unexpected code-execution risk.

Content

No source excerpt is available for this finding.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
85% confidence
Finding

os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Content

Scanner excerpt · scripts/bootstrap.py (reported line 50)May include surrounding context.

python
print(_uv_install_hint(), file=sys.stderr)
        raise SystemExit(1)

    os.execvpe(
        uv_bin,
        [
            uv_bin,

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/bootstrap.py (reported line 61)May include surrounding context.

python
str(script_path),
            *sys.argv[1:],
        ],
        os.environ.copy(),
    )

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This is a true tool-parameter abuse issue because a shell is invoked on Windows while handling a path associated with downloaded remote content. In the context of a skill that fetches files from an external API and then auto-opens them, an attacker who can influence the resulting filename or path may achieve arbitrary command execution on the host.

Content

Scanner excerpt · scripts/convert_images_to_ppt.py (reported line 50)May include surrounding context.

python
elif system == "Linux":
            subprocess.run(["xdg-open", path], check=True, capture_output=True)
        elif system == "Windows":
            subprocess.run(["start", "", path], check=True, shell=True, capture_output=True)
    except subprocess.CalledProcessError:
        pass

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill clearly performs sensitive actions including shell execution, network access, environment variable use, and file reads/writes, but it does not declare any explicit tool scope such as permissions or allowed-tools. That omission weakens reviewability and enforcement, making it easier for the skill to run with broader capabilities than users or the platform may expect.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill states that local image files will be uploaded to a remote service, but it does not require an explicit privacy warning or consent prompt before transmitting potentially sensitive user data. Because screenshots and images commonly contain confidential information, silent upload to a third-party endpoint creates a meaningful data-exposure risk.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The skill explicitly allows first-run creation of a local environment, installation of dependencies, and even downloading Python, which introduces persistent changes to the host system. In security-sensitive environments, this increases attack surface and creates supply-chain and persistence concerns, especially when paired with shell execution and network access.

Content

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

md
This package currently targets the production PPT service at `https://ppt.mustgoai.com`. Override `GOAI_BASE_URL` only when you intentionally need a different endpoint.

This skill now uses a single cross-platform Python entrypoint through `uv`. Treat `uv` as the only runtime dependency the user needs to install manually. On first run, `uv` may create a local environment, install `httpx`, and download Python if the machine does not already have a usable interpreter. That first-run setup is expected and should not be described as an error.

# Script Rules

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
- macOS: `brew install uv`
- Windows: `winget install astral-sh.uv`

After `uv` is installed, rerun the same command. Do not ask the user to install Python packages by hand; `uv` is responsible for preparing Python and the skill dependencies.

If execution reports a missing Python module such as `httpx`, do not run `pip install`, `pip install --user`, or `pip install --break-system-packages`. Re-run the skill through `uv`; the dependency set comes only from `pyproject.toml` and `uv.lock`.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code uploads arbitrary local image files to a remote service after resolving user-provided paths, but provides no built-in consent, disclosure, or boundary checks in this layer. In an agent setting, that creates a real data exfiltration risk because a prompt or tool chain could cause sensitive local files to be sent off-host if the caller passes a path instead of a URL.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This function similarly accepts a local file path, reads the file, obtains a signed remote upload URL, and transmits the file contents without any user-facing warning or confirmation at this code boundary. In a skill designed to convert images/PDFs to PPT remotely, this behavior is expected, but it is still security-relevant because misuse could expose private local documents to the external API.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The --language argument is hard-coded to default to zh, which forces a specific language choice unless the user overrides it. This is a natural-language locale policy concern because the skill does not present language selection as opt-in or justify the default as region-specific.

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 · scripts/convert_images_to_ppt.py (reported line 46)May include surrounding context.

python
system = platform.system()
    try:
        if system == "Darwin":
            subprocess.run(["open", path], check=True, capture_output=True)
        elif system == "Linux":
            subprocess.run(["xdg-open", path], check=True, capture_output=True)
        elif system == "Windows":

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 · scripts/convert_images_to_ppt.py (reported line 48)May include surrounding context.

python
if system == "Darwin":
            subprocess.run(["open", path], check=True, capture_output=True)
        elif system == "Linux":
            subprocess.run(["xdg-open", path], check=True, capture_output=True)
        elif system == "Windows":
            subprocess.run(["start", "", path], check=True, shell=True, capture_output=True)
    except subprocess.CalledProcessError:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

On Windows, this code uses subprocess.run with shell=True and passes a path derived from remotely influenced content into a shell-mediated command. If the filename or path contains shell metacharacters, this can lead to command execution instead of merely opening the PPT, making the auto-open behavior significantly more dangerous in this skill's context.

Content

Scanner excerpt · scripts/convert_images_to_ppt.py (reported line 50)May include surrounding context.

python
elif system == "Linux":
            subprocess.run(["xdg-open", path], check=True, capture_output=True)
        elif system == "Windows":
            subprocess.run(["start", "", path], check=True, shell=True, capture_output=True)
    except subprocess.CalledProcessError:
        pass

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script resolves image inputs and sends their URLs to the GoAI API, which can transmit user-provided image data or references off the local system. Although the overall purpose suggests remote conversion, this file provides no print/log/comment/docstring disclosure that images are uploaded or sent to an external service.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: httpx has 2 known advisory(ies) (CVE-2021-41945 (Improper Input Validation in httpx); CVE-2021-41945 (Encode OSS httpx <=1.0.0.beta0 is affected by improper input validation in `http)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The download_media function fetches content from a remote URL and writes it to a local path, creating parent directories as needed, but it provides no confirmation or visible disclosure that a filesystem write will occur. File creation is a potentially impactful operation and should be surfaced to users unless already clearly documented by the skill.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

When insufficient credits are detected, the script prints a Chinese-only message regardless of the user's selected language or locale. This creates an inconsistent forced-language experience and violates the requirement to avoid imposing a specific language without opt-in.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.