Back to skill

Security audit

Apple Style PPT Maker

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its presentation-making purpose, but it searches more broadly than documented for local .env credential files before sending slide prompts to Google’s image API.

Install only if you are comfortable using Google GenAI for slide content and can control where the skill is run. Avoid running it on slide plans inside unrelated or untrusted project trees because it may load a parent .env file; prefer setting APPLE_STYLE_PPT_MAKER_GEMINI_API_KEY directly in the environment and running from a clean working directory.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/workflow_core.py:64
Finding

Overbroad Environment File Discovery Crosses Project Trust Boundaries

Content
View full analysis
Path | None: """Load the first discovered .env file from common locations.""" script_dir = Path(__file__).resolve().parent candidates: list[Path] = [ Path.cwd() / ".env", script_dir / ".env", plan_path.parent / ".env", ] candidates.extend(parent / ".env" for parent in plan_path.parent.parents) candidates.append(Path.home() / ".codex" / "skills" / "open-apple-style-ppt-maker" / ".env") seen: set[Path] = set() for candidate in candidates: candidate = candidate.resolve() if candidate in seen: continue seen.add(candidate) if candidate.exists(): load_dotenv(candidate, override=False) return candidate load_dotenv(override=False) return None ``` ### Technical Analysis The function searches for `.env` files in the current working directory, the script directory, the plan directory, and every ancestor of the plan directory up to the filesystem root. It then loads the first existing file into the process environment. This behavior exceeds the documented environment-file scope in `SKILL.md`, which only mentions the current directory and Skill directory. A plan located inside an unrelated project can therefore cause the Skill to read that project's `.env` file without explicit user approval. Although `override=False` prevents loaded values from replacing variables already present in the environment, it does not prevent previously unset secrets from being imported. The generation workflow subsequently obtains a Gemini credential from the resulting environment: ```python def get_api_key() -> str: key = os.getenv("APPLE_STYLE_PPT_MAKER_GEMINI_API_KEY") or os.getenv("GEMINI_API_KEY") ...[truncated 1891 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/generate_slides.py:2
Finding

Automatically Bootstrapped Dependencies Are Not Reproducibly Pinned

Content
View full analysis
=3.10" # dependencies = [ # "google-genai>=1.0.0", # "pillow>=10.0.0", # "python-dotenv>=1.0.0", # ] # /// ``` The export script follows the same pattern: ```python # /// script # requires-python = ">=3.10" # dependencies = [ # "python-pptx>=1.0.2", # "pillow>=10.0.0", # ] # /// ``` The documented execution procedure automatically resolves and installs these dependencies: ```markdown Dependency management: - each executable script uses PEP 723 inline metadata - run scripts with `uv run ...` so dependencies bootstrap automatically ``` ### Technical Analysis The PEP 723 dependency declarations specify only lower bounds. Consequently, `uv run` may resolve any later version accepted by the constraints at execution time. The project does not include a reviewed lockfile, exact dependency versions, or integrity hashes in the audited files. The executable code therefore depends on mutable package-registry state rather than a reproducible dependency set. A future compromised or malicious release could be downloaded and imported during an otherwise normal Skill invocation. This exposure is particularly significant because the dependencies run in a process that can access: - Gemini API credentials loaded from the environment. - Full slide-plan content and generated prompts. - User-selected input and output paths. - Generated images, metadata, and PPTX files. - All filesystem resources available to the invoking user. No evidence showed that the currently named packages are malicious. The finding concerns the unsafe dep ...[truncated 1472 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The description claims a broad presentation-generation skill covering planning, structured JSON workflow, content/spec creation, image generation, iterative redesign, and PPTX export. The actual code chunk only handles the final export step: converting existing slide images into a PowerPoint file. While PPTX export is part of the declared description, the code’s primary purpose is much narrower than the declared skill behavior, and none of the upstream generation/editing capabilities are present in this chunk. This is a material description-to-behavior mismatch rather than a mere partial implementation detail.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The description presents a broader, end-to-end presentation creation system, while the actual code shown is only the image-generation portion of that workflow. Its primary function is to render slide images from a preexisting strict JSON plan and manage prompts, metadata, and a manifest. Although some described elements partially align—strict JSON-first input, image generation, and partial rerendering—the code does not implement several major declared capabilities such as clarifying user requirements, locking content/structure, producing per-slide textual content/specs, or exporting to PPTX. Additionally, it exposes broader image output options than the description states. This is a material description-behavior mismatch for the supplied code chunk.

Content

No source excerpt is available for this finding.

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_slides.py (reported line 100)May include surrounding context.

python
def find_and_load_env(plan_path: Path) -> Path | None:
    """Load the first discovered .env file from common locations."""
    script_dir = Path(__file__).resolve().parent
    candidates: list[Path] = [
        Path.cwd() / ".env",

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/regenerate_slide.py (reported line 86)May include surrounding context.

python
def find_and_load_env(plan_path: Path) -> Path | None:
    """Load the first discovered .env file from common locations."""
    script_dir = Path(__file__).resolve().parent
    candidates: list[Path] = [
        Path.cwd() / ".env",

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/workflow_core.py (reported line 64)May include surrounding context.

python
def find_and_load_env(plan_path: Path) -> Path | None:
    """Load the first discovered .env file from common locations."""
    script_dir = Path(__file__).resolve().parent
    candidates: list[Path] = [
        Path.cwd() / ".env",

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/workflow_core.py (reported line 67)May include surrounding context.

python
"""Load the first discovered .env file from common locations."""
    script_dir = Path(__file__).resolve().parent
    candidates: list[Path] = [
        Path.cwd() / ".env",
        script_dir / ".env",
        plan_path.parent / ".env",
    ]

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/workflow_core.py (reported line 68)May include surrounding context.

python
"""Load the first discovered .env file from common locations."""
    script_dir = Path(__file__).resolve().parent
    candidates: list[Path] = [
        Path.cwd() / ".env",
        script_dir / ".env",
        plan_path.parent / ".env",
    ]

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/workflow_core.py (reported line 71)May include surrounding context.

python
"""Load the first discovered .env file from common locations."""
    script_dir = Path(__file__).resolve().parent
    candidates: list[Path] = [
        Path.cwd() / ".env",
        script_dir / ".env",
        plan_path.parent / ".env",
    ]

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/workflow_core.py (reported line 72)May include surrounding context.

python
"""Load the first discovered .env file from common locations."""
    script_dir = Path(__file__).resolve().parent
    candidates: list[Path] = [
        Path.cwd() / ".env",
        script_dir / ".env",
        plan_path.parent / ".env",
    ]

Credential Access

High
Category
Privilege Escalation
Confidence
66% confidence
Finding

The code recursively searches parent directories for a .env file and loads the first one found, which can cause the process to trust configuration from an unintended ancestor directory. In shared or untrusted workspaces, an attacker could plant a higher-level .env to influence runtime behavior, including swapping API keys or redirecting configuration indirectly.

Content

Scanner excerpt · scripts/workflow_core.py (reported line 69)May include surrounding context.

python
candidates: list[Path] = [
        Path.cwd() / ".env",
        script_dir / ".env",
        plan_path.parent / ".env",
    ]
    candidates.extend(parent / ".env" for parent in plan_path.parent.parents)
    candidates.append(Path.home() / ".codex" / "skills" / "open-apple-style-ppt-maker" / ".env")

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill instructs the agent to read and write local files, inspect environment configuration, and execute local commands via uv run, but it does not declare any explicit tool scope such as permissions or allowed-tools. That creates an under-specified trust boundary: a host agent may grant broader capabilities than users expect, increasing the chance of unintended file access, environment exposure, or command execution during use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The function sends the full slide-generation prompt, including deck text and user-provided content, to an external Google GenAI API. In a presentation-making skill, that means potentially sensitive business or personal content is transmitted off-host; this is especially relevant because the workflow is designed to process arbitrary user slide content and there is no consent gate, redaction, or policy check in this file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The JSON sets "language": "en", which is a natural-language locale constraint. Under the policy rules, forcing a specific language without user opt-in or clear justification is a reportable issue, and this file does not provide either.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The JSON sets "language": "en" as a fixed value, which is a natural-language locale constraint. Under the policy criteria, forcing a specific language without user opt-in or justification is a reportable issue.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This code accesses credential-like environment variables and uses them to initialize a remote API client, but there is no confirmation prompt, logging, or comment warning the user that local .env files and environment secrets will be read and used. Under the code-file criteria, sensitive environment variable access should be disclosed unless that warning exists elsewhere.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.