Back to skill

Security audit

slides-generation-skills

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent for generating presentations, but its setup and workflows can expose API keys and send user content to 2slides without clear privacy warnings.

Install only if you are comfortable sending presentation text, document summaries, and reference image URLs to 2slides for processing. Avoid using confidential, regulated, or private documents unless you have permission. Prefer the direct scripts with the API key in an environment variable, protect shell config files, avoid sharing MCP configuration, and pin or review any local 2slides-mcp package before enabling it.

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
references/mcp-integration.md:49
Finding

Unpinned NPM Package Execution in MCP Configuration

Content
View full analysis

Vulnerability Details

File Location: references/mcp-integration.md:49-70
Additional Location: SKILL.md:302-310
Vulnerability Type: Unpinned third-party dependency execution
Risk Level: Medium

Vulnerable Code

json
{
  "mcpServers": {
    "2slides": {
      "command": "npx",
      "args": ["2slides-mcp"],
      "env": {
        "API_KEY": "YOUR_2SLIDES_API_KEY"
      }
    }
  }
}

The troubleshooting instructions also recommend executing the package directly:

bash
npx 2slides-mcp

Technical Analysis

The MCP configuration invokes 2slides-mcp through npx without specifying an exact package version, lockfile, checksum, or integrity constraint. Depending on the local NPM state, npx can retrieve and execute the package version currently resolved by the public registry.

This creates a supply-chain trust boundary in which the effective executable code can change after the Skill itself has been reviewed. A compromised package maintainer account, malicious package release, registry compromise, or dependency compromise could therefore introduce arbitrary code into subsequent installations.

Because the package is configured as a persistent MCP command, the affected release may execute whenever the MCP client launches the server. The process is also explicitly provided with the user's 2slides API key.

Attack Path

  1. An attacker compromises the 2slides-mcp package, its maintainer account, or one of its transitive dependencies.
  2. The attacker publishes a malicious release that remains compatible with the unversioned package name.
  3. A user follows the documented MCP configuration or runs npx 2slides-mcp while troubleshooting.
  4. npx resolves, downloads, and executes the malicious release.
  5. The malicious package executes with the permissions of the user running Claude Desktop or the terminal.
  6. It can access the explicitly supplied `API_KE ...[truncated 607 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin the MCP package to an exact reviewed version:

    json
    {
      "mcpServers": {
        "2slides": {
          "command": "npx",
          "args": ["--yes", "2slides-mcp@REVIEWED_EXACT_VERSION"],
          "env": {
            "API_KEY": "YOUR_2SLIDES_API_KEY"
          }
        }
      }
    }
    
  2. Prefer a controlled installation backed by a committed lockfile and NPM integrity metadata rather than allowing runtime package resolution.

  3. Verify and document the expected package publisher, registry, source repository, and package signature or checksum.

  4. Review direct and transitive dependencies before updating the pinned version.

  5. Run the MCP process in a restricted environment with minimal filesystem permissions, a limited environment, and constrained outbound network access.

  6. Replace troubleshooting instructions that execute an unversioned package with version-pinned commands.

T09 · Insecure Skill Coding Practices

Warning
Location
references/mcp-integration.md:21
Finding

API Key Exposed in MCP URL Query Parameter

Content
View full analysis

Vulnerability Details

File Location: references/mcp-integration.md:21-39
Additional Locations: references/mcp-integration.md:184-200, SKILL.md:302-305
Vulnerability Type: Credential exposure through URL query parameters
Risk Level: Medium

Vulnerable Code

json
{
  "mcpServers": {
    "2slides": {
      "url": "https://2slides.com/api/mcp?apikey=YOUR_2SLIDES_API_KEY"
    }
  }
}

The troubleshooting guidance reinforces this authentication mechanism:

text
For HTTP mode: API key must be in the URL query parameter
text
Verify URL format: https://2slides.com/api/mcp?apikey=YOUR_KEY

Technical Analysis

Placing an API key in a URL query parameter increases its exposure surface. Although HTTPS protects the request contents while in transit, complete URLs may still be recorded by the MCP client, local diagnostics, reverse proxies, observability systems, network middleware, crash reports, support bundles, configuration backups, or copied command output.

Query parameters are commonly treated as non-secret telemetry fields. They are consequently more likely to be retained than credentials sent through a dedicated authorization header or secret-management mechanism.

The key is also stored directly in the Claude Desktop configuration URL, making accidental disclosure through configuration sharing or backup collection more likely.

Attack Path

  1. A user inserts a valid 2slides API key into the documented MCP endpoint URL.
  2. Claude Desktop, an intermediary service, diagnostic tooling, or a configuration backup records the complete URL.
  3. An attacker gains access to the resulting log, support bundle, telemetry record, backup, screenshot, or shared configuration file.
  4. The attacker extracts the apikey query value.
  5. The attacker reuses the credential against the 2slides service until the key is revoked or expires.

Impact Assessment

An e ...[truncated 448 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace query-string authentication with an HTTP authorization header:

    http
    Authorization: Bearer YOUR_2SLIDES_API_KEY
    
  2. If the MCP client supports header configuration, reference the credential through an environment variable or secret store rather than embedding it directly in the URL.

  3. If the protocol cannot avoid query authentication, use short-lived, narrowly scoped tokens and ensure all clients, proxies, and monitoring systems redact the apikey parameter.

  4. Prevent full MCP URLs from appearing in diagnostics, telemetry, error messages, browser history, and support bundles.

  5. Restrict access to Claude Desktop configuration files and exclude them from source control and broadly accessible backups.

  6. Rotate any API key that has previously appeared in a URL, log, screenshot, or shared configuration.

  7. Add explicit documentation warning users that slide text, document summaries, and optional reference-image data are transmitted to the third-party 2slides service.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (17)

Tainted flow: 'headers' from os.environ.get (line 120, 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/generate_slides.py (reported line 74)May include surrounding context.

python
timeout = 90 if mode == "sync" else 30

    print(f"Generating slides in {mode} mode...", file=sys.stderr)
    response = requests.post(url, headers=headers, json=payload, timeout=timeout)
    response.raise_for_status()

    result = response.json()

Tainted flow: 'headers' from os.environ.get (line 120, 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/generate_slides.py (reported line 142)May include surrounding context.

python
timeout = 90 if mode == "sync" else 30

    print(f"Generating slides in {mode} mode...", file=sys.stderr)
    response = requests.post(url, headers=headers, json=payload, timeout=timeout)
    response.raise_for_status()

    result = response.json()

Tainted flow: 'headers' from os.environ.get (line 45, credential/environment) → requests.get (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/get_job_status.py (reported line 53)May include surrounding context.

python
url = f"{API_BASE_URL}/jobs/{job_id}"

    print(f"Checking job status: {job_id}...", file=sys.stderr)
    response = requests.get(url, headers=headers)
    response.raise_for_status()

    result = response.json()

Tainted flow: 'headers' from os.environ.get (line 47, credential/environment) → requests.get (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/search_themes.py (reported line 60)May include surrounding context.

python
url = f"{API_BASE_URL}/themes/search"

    print(f"Searching themes{f': {query}' if query else ''}...", file=sys.stderr)
    response = requests.get(url, headers=headers, params=params)
    response.raise_for_status()

    result = response.json()

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The code chunk’s actual function is narrowly limited to theme discovery in the 2slides catalog. While theme selection is mentioned in the description, the primary declared purpose is presentation generation. This script does not create presentations, upload or summarize documents, transform text into slides, use reference images, or manage generation modes. Therefore the code’s primary behavior is materially different from the declared description.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill instructs the agent to read documents and use reference image URLs with an external 2slides API but does not clearly warn that this content will be transmitted to a third-party service. This creates a significant privacy and data-governance risk because users may unknowingly expose confidential document text, embedded sensitive information, or internal image URLs.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% 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 20)May include surrounding context.

python
def get_api_key() -> str:
    """Get API key from environment variable."""
    api_key = os.environ.get("SLIDES_2SLIDES_API_KEY")
    if not api_key:
        raise ValueError(

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/get_job_status.py (reported line 18)May include surrounding context.

python
def get_api_key() -> str:
    """Get API key from environment variable."""
    api_key = os.environ.get("SLIDES_2SLIDES_API_KEY")
    if not api_key:
        raise ValueError(

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/search_themes.py (reported line 18)May include surrounding context.

python
def get_api_key() -> str:
    """Get API key from environment variable."""
    api_key = os.environ.get("SLIDES_2SLIDES_API_KEY")
    if not api_key:
        raise ValueError(

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
# 2slides Skills for Claude Code

AI-powered presentation generation using the [2slides API](https://2slides.com). This Claude Code skill enables you to create professional presentations from text content, match reference image styles, or summarize documents into slides.

## Important Links

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README encourages users to upload research papers and provide reference image URLs to an external API, but it does not warn that attached documents and images may be transmitted to a third-party service. This can lead users to unknowingly send sensitive, confidential, or regulated data off-platform, increasing privacy and compliance risk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill invokes scripts, requires an environment variable API key, and sends data over the network, but it does not declare any explicit tool scope or allowed-tools boundary. This weakens least-privilege controls and can cause the agent to access env/network capabilities implicitly, increasing the chance of unintended data access or outbound transmission.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger description is broad enough to cause the skill to activate for many presentation-related requests, including cases involving sensitive documents or externally hosted images. Over-broad invocation increases the risk that private user content is routed to this third-party workflow without sufficiently specific user intent or consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation explicitly tells users to embed the API key in the MCP server URL as a query parameter. Query-string credentials are commonly exposed through logs, process listings, browser/history artifacts, screenshots, config sharing, crash reports, and intermediary infrastructure, so this increases the chance of credential leakage even if TLS is used.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
83% confidence
Finding

User-provided presentation content is transmitted to an external third-party API for processing. In an agent skill context, this can expose sensitive or proprietary data if users provide confidential text and there is no explicit consent, redaction, or policy check before sending it off-platform.

Content

Scanner excerpt · scripts/generate_slides.py (reported line 74)May include surrounding context.

python
timeout = 90 if mode == "sync" else 30

    print(f"Generating slides in {mode} mode...", file=sys.stderr)
    response = requests.post(url, headers=headers, json=payload, timeout=timeout)
    response.raise_for_status()

    result = response.json()

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

This path sends both user content and a user-supplied reference image URL to an external service. In addition to third-party data exposure, accepting arbitrary reference image URLs can cause the remote service to fetch internal or sensitive URLs supplied by a user, creating indirect SSRF or confidential resource exposure through the vendor.

Content

Scanner excerpt · scripts/generate_slides.py (reported line 142)May include surrounding context.

python
print("Generating slides from reference image...", file=sys.stderr)
    print(f"(Timeout set to {timeout}s for {page} page(s))", file=sys.stderr)
    response = requests.post(url, headers=headers, json=payload, timeout=timeout)
    response.raise_for_status()

    result = response.json()

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The instructions recommend persisting the API key in shell startup files using a plaintext export command, but do not warn about credential exposure risks from shared machines, backups, dotfile syncing, shell history, or accidental disclosure. While common, this practice can leak long-lived API credentials if users follow it without understanding the tradeoffs.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.