Back to skill

Security audit

gpt-image2-ppt-skills

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a disclosed PPT-generation tool, but it includes a full-auto Codex fallback, broad installation effects, and a few unsafe handling patterns that deserve review before installation.

Review this before installing, especially on shared or high-trust machines. Prefer the direct OpenAI API path over `--backend codex`, avoid running the installer with elevated privileges, install dependencies in a virtual environment, do not store real API keys in persistent agent config unless you intend that scope, and only use trusted OpenAI-compatible endpoints because returned image URLs are fetched by the host.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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)

T01 · Skill Instruction Hijacking

Error
Location
scripts/codex_backend.py:137
Finding

Prompt Injection into a Full-Auto Codex Sub-Agent

Content
View full analysis
10KB;若失败请报错退出非零。\n" f"- 不要向我解释或改写 prompt,直接出图。\n\n" f"图片 prompt:\n" f"-----BEGIN PROMPT-----\n" f"{prompt}\n" f"-----END PROMPT-----\n" ) ``` ```python instruction = self._build_instruction(prompt, output_path, reference_image_path) argv = shlex.split(self.codex_cmd) + [instruction] print(f"🔗 [scene {scene_index}] dispatching to codex ({len(instruction)} chars)") try: result = subprocess.run( argv, capture_output=True, text=True, timeout=self.timeout, check=False, ) ``` ### Technical Analysis The slide image prompt is incorporated verbatim into a natural-language instruction passed to a separate `codex exec --full-auto` process. The `BEGIN PROMPT` and `END PROMPT` markers are textual conventions rather than an enforceable data boundary. An attacker who controls slide content, imported presentation text, or another source used to construct `image_prompt` can insert instructions that tell the spawned Codex agent to disregard the surrounding image-generation request. Because the subprocess is a general autonomous agent rather than a narrowly scoped image API, it may have filesystem and tool capabilities beyond those required to create an image. The use of an argument array prevents operating-system shell injection, but it does not prevent semantic prompt injection against the Codex agent. ### Attack Path 1. An attacker supplies presentation content that conta ...[truncated 966 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/image_generator.py:110
Finding

Server-Side Request Forgery Through Model-Controlled Image URLs

Content
View full analysis
None: # 安全提示:只接受 http/https;下载前打印 host,便于用户识别异常域; # 设最大 50MB 上限避免恶意大文件;非 image/* Content-Type 警告但仍写盘。 from urllib.parse import urlparse parsed = urlparse(url) if parsed.scheme not in ("http", "https"): raise ValueError(f"拒绝下载非 http(s) 协议的 URL: {parsed.scheme}") print(f"📥 下载图片 host={parsed.netloc} path={parsed.path[:80]}") resp = requests.get(url, stream=True, timeout=REQUEST_TIMEOUT_SECS) resp.raise_for_status() ctype = resp.headers.get("content-type", "") if ctype and not ctype.startswith("image/"): print(f"(!) 非 image Content-Type: {ctype}(仍尝试写盘,请人工核对)") MAX_BYTES = 50 * 1024 * 1024 written = 0 with open(output_path, "wb") as f: for chunk in resp.iter_content(chunk_size=8192): written += len(chunk) if written > MAX_BYTES: f.close() os.remove(output_path) raise ValueError(f"下载超过 {MAX_BYTES} 字节上限,已丢弃 {url[:80]}") f.write(chunk) ``` Related permissive URL extraction occurs in `scripts/image_generator.py:193-200`: ```python # 3) 裸图片 URL m = re.search(r"(https?://[^\s\)]+\.(?:png|jpg|jpeg|webp|gif))", text, re.IGNORECASE) if m: return m.group(1) # 4) 任意 http 链接(最后兜底) m = re.search(r"(https?://[^\s\)]+)", text) if m: return m.group(1) ``` ### Technical Analysis The application downloads any HTTP or HTTPS URL returned by the configured image service. It does not reject loopback, private, link-local, reserved, or cloud metadata addresses. The `requests` library follows redirects by default, and redirected destinations are not revalidated. The code also accepts an arbitrary HTTP URL as a fallback even if it does not look like an image. A no ...[truncated 1541 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
install_as_skill.sh:122
Finding

API Credentials Stored in a Predictable Shared Temporary File

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned Dependencies Installed into the Active Python Environment

Content
View full analysis
=2.31 python-dotenv>=1.0 python-pptx>=1.0 jsonschema>=4.0 pymupdf>=1.24 pillow>=10.0 openai>=1.83,<2 ``` The installer resolves and installs these mutable dependency ranges directly: ```bash print_info "安装 Python 依赖..." if command_exists pip3; then pip3 install -q -r "$SKILL_DIR/requirements.txt" else pip install -q -r "$SKILL_DIR/requirements.txt" fi print_success "依赖安装完成" ``` ### Technical Analysis Most dependencies specify only lower version bounds. Consequently, the exact code installed can change over time without any change to the audited repository. No lock file or package hashes are used to verify downloaded artifacts. The installation command also targets whichever environment the detected `pip3` or `pip` command controls. It does not create a dedicated virtual environment. This can alter system-wide or user-wide Python packages, introduce version conflicts, and expand the impact of a compromised dependency. The package names shown do not establish dependency confusion or typosquatting by themselves. The confirmed issue is the mutable, non-reproducible dependency resolution and lack of artifact integrity verification. ### Attack Path 1. A new dependency version becomes available within one of the permitted ranges, or a package-distribution account is compromised. 2. A user runs `install_as_skill.sh`. 3. `pip` resolves the then-current package versions from its configured index. 4. The packages are installed without checking repository-approved hashes. 5. Malicious or incompatible package code executes when installed, imported, or used by the Skill. 6. Because the active Python environment is used, unrelated Python applications may also be affected. ### Impact Assessment A compromised dependency executes with the pri ...[truncated 302 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (200)

Tainted flow: 'VISION_TIMEOUT_SECS' from os.getenv (line 29, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/template_analyzer.py (reported line 241)May include surrounding context.

python
last_err: Optional[Exception] = None
        for attempt in range(1, VISION_MAX_RETRIES + 1):
            try:
                resp = requests.post(
                    self.endpoint, headers=headers, json=payload, timeout=VISION_TIMEOUT_SECS
                )
                if resp.status_code != 200:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · .gitignore (reported line 138)May include surrounding context.

text
*.sage.py

# Environments
.env
.envrc
.venv
env/

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared purpose is about slide/PPT generation functionality, but the supplied code chunk does not generate presentations or images at all. Its primary purpose is local installation and environment setup for the skill. While this may support the overall project, it is a materially different behavior from the declared user-facing description and introduces undeclared capabilities such as filesystem modification, dependency installation, and environment/config handling.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description promises a user-facing slide generation tool that uses gpt-image-2, supports style files or PPTX template mimicry, and outputs presentation assets. The supplied code instead implements an offline POC pipeline for editable PPTX reconstruction: it loads scene JSON, resolves asset paths, builds or loads a repair mask, composites a clean plate from a visual master and edited candidate, renders an editable PPTX via internal helpers, inspects PPTX shapes for native text and pictures, and writes a quality-report JSON. This is materially different in primary purpose and capabilities. While both involve PPTX output, the actual code is a reconstruction/QA utility, not a slide-generation skill matching the declared behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose describes an end-user feature for generating complete presentation slides and decks, including image generation, styling/template application, and output artifacts (PNGs and PPTX). This code chunk does not implement any of those behaviors. Instead, it is a schema/validation module for scene descriptions used in an editable PPTX proof of concept. While such validation could be a supporting component of a PPTX system, this chunk’s actual behavior is materially narrower and different from the declared primary purpose. It also accesses local file paths for clean_plate and image assets, which is consistent with scene validation but not with the advertised generation capability. Therefore this description does not accurately represent what this supplied code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The declared description emphasizes AI-driven slide generation with gpt-image-2, style selection, template mimicry, and production of slide PNGs plus a PPTX. This code chunk does something narrower and different: it loads preauthored scene files, checks consistency, renders an editable PPTX, re-renders it to PNGs through local office software, and produces a QA report. While outputting a PPTX and PNG renders is adjacent to the declared domain, the primary behavior here is editable deck assembly and verification, not image-model-based presentation generation. The local backend requirement is also a meaningful undeclared operational dependency.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code chunk is only an image generator module. It creates a single image from a prompt using gpt-image-2-compatible APIs, with optional reference images and aspect-ratio validation. While this supports part of the declared workflow (producing slide-like PNG imagery), it does not perform several core functions claimed in the description: there is no code to read styles/.md, no code to parse or mimic a .pptx template, and no code to generate or write a 16:9 .pptx presentation. Because those are central parts of the declared purpose rather than incidental implementation details, the description overstates what this supplied code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

There is a clear description-behavior mismatch. The declared purpose centers on creating finished presentation assets (high-resolution slide PNGs and a PowerPoint deck) using OpenAI's gpt-image-2 and optional style/template inputs. The actual code chunk only converts a human-authored markdown planning document into a machine-readable JSON structure describing slides. This may be a supporting preprocessing step within a larger presentation pipeline, but on its own it does not perform the skill's core declared functionality and instead has a materially different primary purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The description promises an end-user presentation generation capability driven by OpenAI image generation and style/template mimicry, with outputs including high-resolution slide PNGs and a finished .pptx deck. The actual code chunk is much narrower and different in purpose: it converts an existing .pptx into page PNGs for template rendering, manages caching/manifests, probes local rendering backends, and falls back across PowerPoint, Keynote, LibreOffice, PDF rasterization, and related dependencies. While template handling is loosely related to the declared template-mimic concept, this code neither generates new slides nor produces a presentation deck, and it has no OpenAI integration. Therefore the code chunk materially differs from the declared primary purpose.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
91% confidence
Finding

Using --noconfirm in package installation guidance suppresses an important safety interlock and can enable unattended tool execution with permanent system effects. In this skill, that risk is amplified because the broader workflow already includes shell, file, and environment interactions, so broad activation could cascade into autonomous host modification.

Content

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

md
| macOS | `brew install --cask libreoffice` |
| Linux (Debian/Ubuntu) | `sudo apt-get install -y libreoffice` |
| Linux (Fedora/RHEL) | `sudo dnf install -y libreoffice` |
| Linux (Arch) | `sudo pacman -S --noconfirm libreoffice-fresh` |

装完再次检查,确认存在可用渲染后端再继续后续流程。

Agent Config Directory Access

High
Category
Agent Snooping
Confidence
96% confidence
Finding

The skill explicitly instructs use of user-level and project-level agent configuration files such as ~/.claude/settings.json and .claude/settings.local.json for environment injection. Accessing or modifying agent config directories expands the trust boundary into sensitive local configuration that may contain secrets, tokens, or settings unrelated to this task.

Content

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

md
不要把本 skill 的密钥写进调用者业务项目根目录的 `.env`,也不要为了出图去读取用户项目里的通用 `.env`。环境变量建议按 agent 框架的标准方式注入:

- **通用 / CI / 服务器**:用系统环境变量、Docker Compose `environment` / `env_file`、Kubernetes Secret、CI Secret 等注入。
- **Claude Code**:用用户级 `~/.claude/settings.json` 或项目级 `.claude/settings.local.json` 注入环境变量;命令行环境变量优先级最高。
- **OpenClaw / 自定义 Agent**:用框架配置里的 `apiKey` / env reference 引用系统环境变量,避免把 key 明文写进项目配置。
- **本地 standalone CLI fallback**:可以设置 `GPT_IMAGE2_PPT_ENV=/path/to/private.env`,或使用 skill 安装目录下的 `.env`;这只是备用方式,不是业务项目 `.env`。

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill mandates Simplified Chinese output and font/language constraints without user opt-in, overriding user intent and potentially changing the semantic content of generated materials. In a presentation-generation context, this can corrupt documents, misrepresent source content, or cause policy-sensitive transformations of user data without consent.

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 478)May include surrounding context.

md
- 文字和独立图片对象必须从 `clean-plate.png` 中移除;移动对象后不能露出第二份相同对象。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
|---- docs/README.en.md # 英文 README

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · agents/openclaw.yaml (reported line 8)May include surrounding context.

yaml
# Trust surface (what the user agrees to when installing this skill):
#   - Reads process env, platform-injected env, explicit GPT_IMAGE2_PPT_ENV,
#     and skill-owned .env fallback only; never walks parent project directories.
#   - Hits exactly the OPENAI_BASE_URL endpoint you set, plus optional
#     VISION_BASE_URL endpoint you set (only when the caller agent is text-only).
#   - Downloads images returned by the model API; URLs are printed before

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/generate_ppt.py (reported line 76)May include surrounding context.

python
# Trust surface (what the user agrees to when installing this skill):
#   - Reads process env, platform-injected env, explicit GPT_IMAGE2_PPT_ENV,
#     and skill-owned .env fallback only; never walks parent project directories.
#   - Hits exactly the OPENAI_BASE_URL endpoint you set, plus optional
#     VISION_BASE_URL endpoint you set (only when the caller agent is text-only).
#   - Downloads images returned by the model API; URLs are printed before

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/generate_ppt.py (reported line 78)May include surrounding context.

python
# Trust surface (what the user agrees to when installing this skill):
#   - Reads process env, platform-injected env, explicit GPT_IMAGE2_PPT_ENV,
#     and skill-owned .env fallback only; never walks parent project directories.
#   - Hits exactly the OPENAI_BASE_URL endpoint you set, plus optional
#     VISION_BASE_URL endpoint you set (only when the caller agent is text-only).
#   - Downloads images returned by the model API; URLs are printed before

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/generate_ppt.py (reported line 113)May include surrounding context.

python
# Trust surface (what the user agrees to when installing this skill):
#   - Reads process env, platform-injected env, explicit GPT_IMAGE2_PPT_ENV,
#     and skill-owned .env fallback only; never walks parent project directories.
#   - Hits exactly the OPENAI_BASE_URL endpoint you set, plus optional
#     VISION_BASE_URL endpoint you set (only when the caller agent is text-only).
#   - Downloads images returned by the model API; URLs are printed before

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/template_analyzer.py (reported line 895)May include surrounding context.

python
# Trust surface (what the user agrees to when installing this skill):
#   - Reads process env, platform-injected env, explicit GPT_IMAGE2_PPT_ENV,
#     and skill-owned .env fallback only; never walks parent project directories.
#   - Hits exactly the OPENAI_BASE_URL endpoint you set, plus optional
#     VISION_BASE_URL endpoint you set (only when the caller agent is text-only).
#   - Downloads images returned by the model API; URLs are printed before

Agent Config Directory Access

High
Category
Agent Snooping
Confidence
90% confidence
Finding

Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Content

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

md
If you use direct API mode, inject environment variables through your agent
framework instead of writing secrets into the caller project's root `.env`:

- Claude Code: user-level `~/.claude/settings.json`, or project-level `.claude/settings.local.json`
- OpenClaw / custom agents: reference system env vars from `apiKey` / env config
- CI / servers: system env vars, Docker Compose, Kubernetes Secrets, or CI Secrets
- Standalone CLI: set `GPT_IMAGE2_PPT_ENV=/path/to/private.env`, or use the skill install directory `.env` as a fallback

Agent Config Directory Access

High
Category
Agent Snooping
Confidence
90% confidence
Finding

Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Content

Scanner excerpt · docs/README.en.md (reported line 202)May include surrounding context.

md
If you use direct API mode, inject environment variables through your agent
framework instead of writing secrets into the caller project's root `.env`:

- Claude Code: user-level `~/.claude/settings.json`, or project-level `.claude/settings.local.json`
- OpenClaw / custom agents: reference system env vars from `apiKey` / env config
- CI / servers: system env vars, Docker Compose, Kubernetes Secrets, or CI Secrets
- Standalone CLI: set `GPT_IMAGE2_PPT_ENV=/path/to/private.env`, or use the skill install directory `.env` as a fallback

Agent Config Directory Access

High
Category
Agent Snooping
Confidence
90% confidence
Finding

The document instructs an agent to place secrets into agent configuration locations such as ~/.claude/settings.json and project-local settings files. Having an automated agent modify persistent config files with API credentials can leak secrets across projects, widen their exposure surface, and create long-lived credential residue outside the user's intended secret-management boundary.

Content

Scanner excerpt · docs/install.md (reported line 56)May include surrounding context.

md
优先通过当前 agent 框架或运行环境注入,不要写进调用者业务项目根目录 `.env`:

- Claude Code:用户级 `~/.claude/settings.json`,或项目级 `.claude/settings.local.json`
- OpenClaw / 自定义 Agent:用 `apiKey` / env reference 引用系统环境变量,避免明文写进项目配置
- CI / 服务器:用系统环境变量、Docker Compose、Kubernetes Secret 或 CI Secret
- standalone CLI fallback:设置 `GPT_IMAGE2_PPT_ENV=/path/to/private.env`,或使用 skill 安装目录下的 `.env`

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · docs/install.md (reported line 88)May include surrounding context.

5.(可选)清理临时目录

bash
rm -rf /tmp/gpt-image2-ppt-skills

冒烟测试(用户重启 agent 后)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · docs/install.md (reported line 88)May include surrounding context.

5.(可选)清理临时目录

bash
rm -rf /tmp/gpt-image2-ppt-skills

冒烟测试(用户重启 agent 后)

Ae3

High
Category
analysis-evasion
Confidence
90% confidence
Finding

Text artifact contains embedded NUL bytes

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
.env.example:3