Back to skill

Security audit

COSER模卡生成器cosercard-skill

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to be a legitimate card generator, but it automatically keeps local history/profile-linked usage data and has an output path weakness that users should review before installing.

Review this skill before installing if you will process real personal photos or contact/social/location details. Use a dedicated output folder, avoid names containing path separators or '..', inspect or clear learning_data.json after use, and consider disabling or patching the automatic history write if privacy matters.

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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/coser_card.py:2356
Finding

Unsanitized Profile Name Permits Output Path Traversal

Content
View full analysis

Vulnerability Details

File Location: scripts/coser_card.py:2356
Vulnerability Type: Path traversal and arbitrary file creation or overwrite
Risk Level: Medium

Vulnerable Code

python
# Generate each requested format
for fmt in formats:
    if fmt not in FORMAT_SIZES:
        print(f"Warning: unknown format {fmt}; skipping")
        continue

    output_file = os.path.join(
        args.output,
        f"{profile.name}_{args.template}_{args.style}_{fmt}.jpg"
    )
    generate_card(
        profile,
        args.template,
        args.style,
        fmt,
        output_file,
        args.watermark
    )

The resulting path is subsequently used by the following file-writing logic in generate_card:

python
# Save
os.makedirs(os.path.dirname(output_path) or ".", exist_ok=True)
canvas.save(output_path, quality=95)

The same vulnerable construction also appears in the batch-preview path at scripts/coser_card.py:1759:

python
preview_path = os.path.join(
    output_dir,
    f"{profile.name}_batch_preview_{format_type}.jpg"
)
os.makedirs(output_dir, exist_ok=True)
canvas.save(preview_path, quality=90)

Technical Analysis

profile.name can originate from the --name command-line argument, interactive input, or a JSON configuration file. It is embedded directly into an output filename without rejecting directory separators, absolute path syntax, or traversal components such as ...

os.path.join() does not establish a security boundary. Traversal components in the generated filename are preserved and resolved by the operating system when Pillow opens the destination for writing. In the normal generation path, generate_card() also creates the derived parent directories before saving the image.

Consequently, a user or upstream agent that supplies an attacker-controlled profile name can cause the generated JPEG to be written outside the directory selected by --output.

Attack Path

  1. The attacker controls or ...[truncated 1237 chars]
Remediation
View remediation

Remediation Suggestions

  1. Convert the profile name into a strict filename-safe slug. Prefer an allowlist of letters, digits, underscores, and hyphens.

  2. Reject names containing /, \, .., NUL bytes, control characters, drive prefixes, or absolute-path syntax.

  3. Resolve both the output directory and final output path, then verify containment before writing:

    python
    from pathlib import Path
    import re
    
    def safe_filename_component(value: str) -> str:
        value = re.sub(r"[^A-Za-z0-9_-]+", "_", value).strip("_")
        if not value:
            raise ValueError("The profile name does not contain a safe filename component")
        return value
    
    output_root = Path(args.output).resolve()
    safe_name = safe_filename_component(profile.name)
    output_file = (
        output_root /
        f"{safe_name}_{args.template}_{args.style}_{fmt}.jpg"
    ).resolve()
    
    if output_root not in output_file.parents:
        raise ValueError("Output path escapes the configured output directory")
    
  4. Apply the same validation and containment check to batch-preview output paths.

  5. Avoid silently overwriting existing files. Use an explicit overwrite option or exclusive file-creation strategy where practical.

  6. Add tests covering ../, absolute paths, Windows drive paths, mixed separators, empty sanitized names, and valid Unicode names.

Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (12)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README states the tool can 'automatically learn preferences' and remember best configurations, implying persistent storage of user behavior/history, but it does not disclose what is stored, where it is stored, or how long it is retained. In a tool that processes personal photos and profile-like metadata, silent preference/history retention creates a privacy risk because users may unknowingly leave local traces of sensitive usage patterns.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill documentation describes capabilities that read user-supplied photo paths and write generated outputs and history data, but it declares no explicit tool scope or permission boundaries. In an agent setting, this can lead to overbroad file-system access assumptions and makes it easier for the skill to be used on unintended files or write locations without clear policy constraints.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill encourages collection of personal, body, social, contact, and location information, including sensitive profile details, without any privacy notice, retention statement, or minimization guidance. This increases the risk of unnecessary exposure, mishandling, or downstream leakage of personally identifiable and sensitive personal data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill states that user preferences/history are automatically recorded to learning_data.json and reused by quick mode, but it gives no explicit consent, opt-out, or retention controls. Silent persistence of user behavior and profile preferences can create a privacy risk, especially when combined with identity, body metrics, and social/contact details described elsewhere in the skill.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code implements long-term tracking of user preferences and generation history through recommendation and best-config features, which is not necessary for basic image layout functionality. In this skill context, users supply personal profile data and photos, so retaining derived history increases privacy risk and broadens the attack surface if the host environment is shared or later compromised.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script automatically persists generation history and profile-associated metadata into ../learning_data.json on successful runs, which expands data handling beyond the stated card-generation purpose. Even though this is local storage rather than overt exfiltration, it creates an unnecessary retention surface for personal data and output metadata without clear consent or minimization.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code stores sensitive profile-linked data such as name, social-account presence, location indicators, output history, and generation metadata in a local learning database without prominent disclosure or consent. In a card tool for cosers/models, this context is more sensitive because the script also collects contact details and social identities, creating a meaningful privacy and stalking risk if local files are accessed by other users or malware.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The README advertises photo analysis and tone recognition but does not prominently warn users that supplied photos are automatically analyzed as part of normal operation. Even if analysis is local and limited, photos may contain sensitive personal imagery, so undisclosed analysis reduces informed consent and can surprise users about how their inputs are processed.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency is specified as Pillow>=9.0.0, which allows any future version to be installed and makes builds non-reproducible. This increases supply-chain risk and can unintentionally pull in vulnerable or breaking releases, especially for an image-processing skill that is likely to handle untrusted image files.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
Pillow>=9.0.0

Unverifiable Dependency: Pillow has 16 known advisory(ies) (CVE-2016-2533 (Pillow buffer overflow in ImagingPcdDecode); CVE-2023-50447 (Arbitrary Code Execution in Pillow); CVE-2021-27922 (Pillow Uncontrolled Resource Consumption) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
92% confidence
Finding

Pillow has a history of security advisories, including issues such as resource exhaustion and possible code-execution bugs in image parsers. Because the manifest does not pin a specific version, it is impossible to verify whether deployments will receive a patched release, which is more concerning here since this skill’s purpose centers on processing user-supplied images.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

Natural-language strings throughout the file, including the module description, CLI help text, prompts, warnings, and status output, are all presented in Chinese with no language-selection mechanism. That creates a locale/language policy concern because users are not offered a choice or explicit opt-in to this language.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The wrapper is described as merely adding learning functionality, but it silently changes the behavior of generate_card so every successful generation triggers a persistent write. This mismatch is dangerous because it hides stateful data collection behind a normal rendering operation, undermining user expectations and making privacy-impacting behavior easy to miss during review.

Content

No source excerpt is available for this finding.