Back to skill

Security audit

Baoyu Seedream Ppt

Security checks for vulnerabilities and agentic risk

Overview

This PPT generator mostly matches its purpose, but unsafe path handling could expose local Markdown files to the image API or write outputs outside the intended folder.

Install only if you are comfortable sending slide content and generated prompts to Volcengine Seedream. Use it on non-sensitive material, avoid untrusted config files, and do not pass custom layout/style/project names unless the code is fixed to enforce allowlists and output-directory containment.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
baoyu_seedream_ppt.py:179
Finding

Path Traversal Enables Local Markdown Disclosure to the Seedream API

Content
View full analysis

Vulnerability Details

File Location: baoyu_seedream_ppt.py:179-195, 247-264; interactive.py:207-220, 250-285, 498-510
Vulnerability Type: Path traversal resulting in local file disclosure
Risk Level: High

Vulnerable Code

python
# baoyu_seedream_ppt.py:179-195
skill_root = os.path.dirname(os.path.abspath(__file__))
baoyu_root = os.path.join(os.path.dirname(skill_root), "baoyu-infographic")

layout_path = os.path.join(
    baoyu_root, "references", "layouts", f"{args.layout}.md"
)
style_path = os.path.join(
    baoyu_root, "references", "styles", f"{args.style}.md"
)
base_prompt_path = os.path.join(
    baoyu_root, "references", "base-prompt.md"
)

if not os.path.exists(layout_path):
    print(f"❌ 布局不存在: {args.layout}")
    print(f"   请检查 {layout_path}")
    sys.exit(1)

if not os.path.exists(style_path):
    print(f"❌ 风格不存在: {args.style}")
    print(f"   请检查 {style_path}")
    sys.exit(1)
python
# baoyu_seedream_ppt.py:203-211
with open(layout_path, 'r', encoding='utf-8') as f:
    layout_def = f.read()

with open(style_path, 'r', encoding='utf-8') as f:
    style_def = f.read()

with open(base_prompt_path, 'r', encoding='utf-8') as f:
    base_prompt = f.read()
python
# baoyu_seedream_ppt.py:247-264
full_prompt = base_prompt
full_prompt = full_prompt.replace("{{LAYOUT}}", args.layout)
full_prompt = full_prompt.replace("{{STYLE}}", args.style)
full_prompt = full_prompt.replace("{{ASPECT_RATIO}}", args.aspect)
full_prompt = full_prompt.replace("{{LANGUAGE}}", "Chinese")
full_prompt = full_prompt.replace("{{LAYOUT_GUIDELINES}}", layout_def)
full_prompt = full_prompt.replace("{{STYLE_GUIDELINES}}", style_def)
full_prompt = full_prompt.replace("{{CONTENT}}", page_content)
full_prompt = full_prompt.replace("{{TEXT_LABELS}}", "")

prompt_file = os.path.join(output_dir, f"prompts_page_{page_num:02d}.md")
with open(prompt_file, 'w', 
...[truncated 3346 chars]
Remediation
View remediation

Remediation Suggestions

  1. Build explicit allowlists from the available layout and style templates and reject every value not present in those allowlists.
  2. Reject absolute paths, path separators, . components, and .. components before constructing a path.
  3. Resolve the candidate path and verify that its parent is exactly the expected template directory:
python
layouts_dir = (baoyu_root / "references" / "layouts").resolve()
available_layouts = {path.stem for path in layouts_dir.glob("*.md")}

if layout not in available_layouts:
    raise ValueError("Unsupported layout")

layout_path = (layouts_dir / f"{layout}.md").resolve()
if layout_path.parent != layouts_dir:
    raise ValueError("Invalid layout path")
  1. Apply the same validation independently to styles.
  2. Validate configuration-loaded values exactly as strictly as direct command-line values.
  3. Add tests covering ../, absolute paths, nested paths, encoded separators, and valid allowlisted names.
  4. Warn users that slide content and selected template text are sent to an external image-generation provider.

T09 · Insecure Skill Coding Practices

Warning
Location
baoyu_seedream_ppt.py:84
Finding

Unvalidated API-Provided Image URL Permits Server-Side Request Forgery

Content
View full analysis

Vulnerability Details

File Location: baoyu_seedream_ppt.py:84-103
Vulnerability Type: Server-side request forgery through an untrusted image URL
Risk Level: Medium

Vulnerable Code

python
def download_image(url, save_path):
    """下载生成的图片"""
    try:
        resp = requests.get(url, timeout=60)
        if resp.status_code == 200:
            with open(save_path, 'wb') as f:
                f.write(resp.content)
            file_size = os.path.getsize(save_path) / 1024 / 1024
            print(f"✅ 已保存: {os.path.basename(save_path)} ({file_size:.2f} MB)")
            return True
        else:
            print(f"❌ 下载失败: {resp.status_code}")
            return False
    except Exception as e:
        print(f"❌ 下载异常: {e}")
        return False

The URL reaches this function through the API response:

python
result = response.json()
if 'data' in result and len(result['data']) > 0:
    image_url = result['data'][0]['url']
    return image_url

Technical Analysis

The image-generation response is treated as trusted, and the returned URL is passed directly to requests.get(). The code does not validate:

  • The URL scheme.
  • The destination hostname.
  • The resolved destination IP address.
  • Redirect destinations.
  • Whether the target is loopback, private, link-local, or otherwise reserved.
  • The response content type.
  • The maximum response size.

Python Requests follows HTTP redirects by default. Therefore, validating only the initial hostname in a future partial fix would remain insufficient unless every redirect destination is also checked.

Exploitation requires control over, compromise of, or manipulation of the image API response. It is not directly triggered by ordinary slide content alone based on the reviewed code. If that trust boundary is compromised, however, the application becomes a network request primitive from the host running the Skil ...[truncated 1439 chars]

Remediation
View remediation

Remediation Suggestions

  1. Allow only HTTPS image URLs.
  2. Maintain an allowlist of documented image-delivery hostnames used by the Seedream service.
  3. Resolve the hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved IP ranges for both IPv4 and IPv6.
  4. Disable automatic redirects or validate the scheme, hostname, and resolved address at every redirect.
  5. Require an expected image content type such as image/png or image/jpeg.
  6. Stream the response in bounded chunks and enforce a conservative maximum download size.
  7. Reject malformed URLs, URLs containing embedded credentials, and unexpected ports.
  8. Consider using a dedicated image-download client with outbound firewall or proxy restrictions.
  9. Verify that the downloaded data is a valid supported image before passing it to python-pptx.

T09 · Insecure Skill Coding Practices

Warning
Location
interactive.py:250
Finding

Configuration-Controlled Project Name Enables Output-Directory Traversal

Content
View full analysis

Vulnerability Details

File Location: interactive.py:250-268, 491-510
Vulnerability Type: Path traversal causing arbitrary file creation or overwrite
Risk Level: Medium

Vulnerable Code

python
# interactive.py:250-268
if not project_name:
    content_path = analysis["content_path"]
    project_name = os.path.splitext(os.path.basename(content_path))[0]

# 创建输出目录
output_path = Path(output_dir) / project_name
images_dir = output_path / "images"
prompts_dir = output_path / "prompts"
output_path.mkdir(parents=True, exist_ok=True)
images_dir.mkdir(parents=True, exist_ok=True)
prompts_dir.mkdir(parents=True, exist_ok=True)
python
# interactive.py:491-510
with open(args.config, 'r', encoding='utf-8') as f:
    config = json.load(f)

# 需要重新分析内容获取pages
analysis = creator.step1_analyze_content(config["content_path"])

# 重新生成提示词(用户可能修改过)
prompt_info = creator.step2_generate_prompts(
    analysis,
    config["layout"],
    config["style"],
    config["aspect"],
    config["project_name"],
    args.output_dir
)

# 生成图片
result = creator.step3_generate_images(prompt_info, args.model, args.interval)

Files are subsequently written under the derived path:

python
prompt_file = prompts_dir / f"page_{page_num:02d}.md"
with open(prompt_file, 'w', encoding='utf-8') as f:
    f.write(full_prompt)

with open(output_path / "config.json", 'w', encoding='utf-8') as f:
    json.dump(config, f, ensure_ascii=False, indent=2)

Technical Analysis

In normal content-file workflows, project_name is reduced to the basename of the content path. In the generate workflow, however, the value is loaded directly from a caller-supplied JSON configuration and passed to step2_generate_prompts().

Path(output_dir) / project_name does not guarantee containment within output_dir. A project name containing ../ can escape the output root. If project_name is an ...[truncated 1798 chars]

Remediation
View remediation

Remediation Suggestions

  1. Treat project_name as a filename component rather than a path.
  2. Reject absolute paths, separators, . and .., empty names, and platform-specific reserved names.
  3. Restrict names to a conservative character set and length, for example letters, digits, underscores, and hyphens.
  4. Resolve both the output root and destination and verify containment before creating directories:
python
output_root = Path(output_dir).resolve()

if (
    not project_name
    or Path(project_name).is_absolute()
    or Path(project_name).name != project_name
):
    raise ValueError("Invalid project name")

output_path = (output_root / project_name).resolve()
if output_path.parent != output_root:
    raise ValueError("Project output escapes the output directory")
  1. Validate the entire supplied JSON document against a strict schema.
  2. Avoid overwriting existing files by default; use exclusive creation or require an explicit overwrite option.
  3. Apply containment checks again immediately before writing the configuration, prompts, images, and PPTX.
  4. Add regression tests for relative traversal, absolute Unix paths, Windows drive paths, UNC paths, nested names, and symbolic-link edge cases.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (37)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill documents capabilities that read user files, write generated images/PPTs to disk, and call an external image-generation API, but it does not declare any explicit tool scope or allowed-tools restrictions. That creates an overbroad execution surface where an agent may infer broad filesystem and network access from natural-language instructions, increasing the risk of unintended data access, exfiltration, or arbitrary file writes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill says it can analyze user-provided content links/materials and generate images via Seedream, but it does not clearly warn that content may be transmitted to an external third-party image-generation service. This creates a meaningful privacy and confidentiality risk if users provide proprietary documents, sensitive text, or internal URLs expecting only local processing.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The invocation examples use broad trigger phrases like generating a PPT from provided content without constraining what sources may be read or what destinations may be written. In an agent setting, vague triggers can cause the model to over-collect local content, follow embedded links, or perform multi-step actions the user did not explicitly authorize.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · baoyu_seedream_ppt.py (reported line 69)May include surrounding context.

python
"size": resolution
    }
    
    response = requests.post(
        f"{BASE_URL}/images/generations",
        headers=headers,
        json=data,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This code forcibly replaces the language placeholder with "Chinese" for every generated prompt. The file does not offer a user opt-in, locale selection, or a documented region-specific reason for enforcing that language, which conflicts with the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code hard-codes {{LANGUAGE}} to Chinese, which imposes a specific language on generated output regardless of user preference. This is a natural-language policy concern because the file provides no opt-in, fallback, or documented region-specific justification for the locale restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file contains a natural-language requirement that fixes the output language to Chinese. The policy allows locale constraints only when the user is given a choice or when the restriction is clearly documented and justified as region-specific; neither is stated here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This line reinforces a mandatory single-language policy for all generated text. Because no alternative language option or opt-in mechanism is provided, it constitutes a locale/language policy concern under the stated rules.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file explicitly sets the language to Chinese, which is a natural-language locale restriction. Because it does not provide an opt-in choice or explain why the locale is required, it fits the policy-violation criterion for forced language selection.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This line operationalizes the Chinese-only requirement by directing that all text must use the specified language. That is a natural-language policy concern because it removes language choice without indicating user consent or a documented regional/compliance need.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This file explicitly fixes the output language to Chinese, which is a natural-language policy concern when no user selection or opt-in is offered. The requirement is reinforced again later as a mandatory instruction for all text content, making the locale constraint unconditional rather than user-driven.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This line operationalizes the earlier language constraint by requiring all text to use the specified language, with no alternative or opt-in path. Because the skill does not present this as a user-selectable setting or justified regional limitation, it constitutes a policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown instruction explicitly fixes the output language to Chinese, and later reiterates that all text must use the specified language. Under the policy, forcing a specific language without user opt-in is a natural-language locale violation unless clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This line requires all text content to use the specified language, which in this file is Chinese. Because the prompt does not offer a language choice or explain a justified regional requirement, it conflicts with the language/locale policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This file explicitly sets the language to Chinese, which is a natural-language locale restriction. Because the prompt does not provide opt-in, alternatives, or a documented region-specific justification, it violates the policy against forcing a specific language without user choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This line operationalizes the earlier locale restriction by requiring all generated text to be in the specified language. Since no user choice or justified regional scope is provided, this is a policy-relevant language constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown instruction explicitly fixes the output language to Chinese, and later reinforces that all text content must use the specified language. Under the policy, forcing a specific language without user opt-in or a documented justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This line operationalizes the earlier Chinese-only requirement by requiring all text to use the specified language, with no opt-in or alternative locale path. That creates a policy issue because the skill enforces a language choice rather than offering one.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown prompt explicitly sets the language to Chinese, which is a natural-language locale constraint. Under the policy criteria, forcing a specific language without user opt-in or clear regional justification is a violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This line operationalizes the earlier language requirement by requiring all text to use the specified language. Because the specified language is Chinese and no alternative or opt-in is provided, it perpetuates the same locale policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file contains a natural-language instruction that fixes the output language to Chinese. Under the policy, forcing a specific language without user opt-in or a clearly documented justification is a locale-policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The instruction requires use of the specified language for all text content, which in this file is Chinese. Because no alternative locale option or justification is provided, this repeats the same language-policy concern in operational instructions.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The file explicitly sets "Language: Chinese," which imposes a specific language requirement. Under the policy, forcing a language without offering user choice or documenting a justified locale constraint is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The line "Use the specified language for all text content" operationalizes the earlier forced Chinese-language setting. Because no alternative language option or opt-in mechanism is provided, this conflicts with the language/locale policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Line L009 explicitly sets the language to Chinese, and L026 reinforces that all text content must use the specified language. This imposes a fixed locale without any opt-in or explanation that the skill is region-specific, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.