Back to skill

Security audit

工作伴侣|四件小事判官

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent Chinese workday decision-helper skill; the main caution is to review shareable image cards because privacy checks are not fully enforced by code.

Install only if you want a Chinese-language workday decision helper. Treat generated cards as shareable only after checking that real names, workplaces, addresses, routes, payment details, and health information are not present, especially in alt text.

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/judgment_to_card.py:59
Finding

Caller-Controlled Privacy Flag Allows Sensitive Data in Shareable Cards

Content
View full analysis

Vulnerability Details

File Location: scripts/judgment_to_card.py:59-66, 69-94; related validation in scripts/validate_card.py:22-38, 88-97 and scripts/render_card.py:24-40, 53-61, 82-83
Vulnerability Type: Trusting caller-controlled safety metadata and ineffective sensitive-data validation
Risk Level: Medium

Vulnerable Code

From scripts/judgment_to_card.py:

python
def validate_judgment(data: dict[str, Any]) -> list[str]:
    errors: list[str] = []
    for key in REQUIRED:
        if key not in data:
            errors.append(f"missing field: {key}")
    if data.get("module") not in MODULE_META:
        errors.append("module unsupported")
    for key in ["title", "verdict", "reason", "action"]:
        if not isinstance(data.get(key), str) or not data.get(key, "").strip():
            errors.append(f"{key} must be non-empty text")
    if data.get("share_safe") is not True:
        errors.append("share_safe must be true for renderable card")
    return errors


def convert_judgment(data: dict[str, Any], ratio: str = "9:16") -> dict[str, Any]:
    errors = validate_judgment(data)
    if errors:
        raise ValueError("; ".join(errors))
    if ratio not in RATIOS:
        raise ValueError("ratio must be 9:16 or 3:4")
    module_label, route, default_time, default_corner = MODULE_META[str(data["module"])]
    tags = split_entry(data.get("backup")) + split_entry(data.get("follow_up"))
    if not tags:
        tags = [module_label[:4]]
    card = {
        "module": module_label,
        "route": route,
        "time_label": clipped(data.get("time_label", default_time), TEXT_LIMITS["time_label"]),
        "title": clipped(data["title"], TEXT_LIMITS["title"]),
        "reason": clipped(data["reason"], TEXT_LIMITS["reason"]),
        "action": clipped(data["action"], TEXT_LIMITS["action"]),
        "tags": tags[:4],
        "corner": clipped(split_entry(data.get("follow_up"))[0] if split_entry(data.get("follow_up")) else default_corner
...[truncated 4091 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not trust caller-controlled safety metadata

    • Treat input share_safe as an untrusted claim rather than proof.
    • Default converted cards to share_safe: false.
    • Set the flag to true only after a dedicated sanitizer and validator complete successfully.
  2. Separate private source data from public card data

    • Define an explicit allowlist of fields and content classes permitted in shareable cards.
    • Keep precise locations, names, routes, health details, and account information in non-renderable fields.
    • Construct public summaries from sanitized categories rather than copying source strings.
  3. Implement value-oriented sensitive-data detection

    • Detect common telephone-number, email-address, coordinate, account-identifier, and detailed-address patterns.
    • Add configurable detection for names, company terms, meeting identifiers, and route descriptions.
    • Normalize Unicode and punctuation before matching to reduce trivial bypasses.
    • Treat detection as defense in depth rather than a complete substitute for structured data separation.
  4. Apply one sanitizer consistently

    • Sanitize title, reason, action, backup, follow_up, tags, and alt_text.
    • Use the same sanitized representation for HTML, SVG, and PNG output.
    • Avoid reconstructing alt_text from unsanitized judgment fields.
  5. Require explicit confirmation for intentional disclosure

    • If users request inclusion of real names or locations, present the exact content that will be shared.
    • Require affirmative confirmation before producing a publicly shareable artifact.
    • Mark such artifacts as containing user-approved sensitive content rather than generically safe.
  6. Strengthen tests

    • Add negative test cases containing realistic telephone numbers, email addresses, street addresses, coordinates, company names, meeting titles, and health details.
    • Verify that sensitive values are absent from ...[truncated 413 chars]
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (46)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Repository-wide scanning, loading local Python modules, and package validation introduce broad local access and code-loading behaviors that do not match the stated assistant function. Even if intended for QA, bundling them into a user-facing skill increases the risk of unintended execution paths, local information exposure, or abuse of trusted installation contexts.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Repository-wide scanning, loading local Python modules, and package validation introduce broad local access and code-loading behaviors that do not match the stated assistant function. Even if intended for QA, bundling them into a user-facing skill increases the risk of unintended execution paths, local information exposure, or abuse of trusted installation contexts.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Repository-wide scanning, loading local Python modules, and package validation introduce broad local access and code-loading behaviors that do not match the stated assistant function. Even if intended for QA, bundling them into a user-facing skill increases the risk of unintended execution paths, local information exposure, or abuse of trusted installation contexts.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Repository-wide scanning, loading local Python modules, and package validation introduce broad local access and code-loading behaviors that do not match the stated assistant function. Even if intended for QA, bundling them into a user-facing skill increases the risk of unintended execution paths, local information exposure, or abuse of trusted installation contexts.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Repository-wide scanning, loading local Python modules, and package validation introduce broad local access and code-loading behaviors that do not match the stated assistant function. Even if intended for QA, bundling them into a user-facing skill increases the risk of unintended execution paths, local information exposure, or abuse of trusted installation contexts.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill declares no explicit tool scope even though the package reportedly contains file read, file write, and shell-capable components. In an agent environment, undeclared high-risk capabilities undermine least-privilege controls and can enable unintended file access or command execution if the runtime grants defaults or if later prompts route into those components.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The invocation examples and trigger phrases are broad everyday expressions, which can cause accidental activation or over-collection of user context when a general conversation happens to match. In agent ecosystems, ambiguous triggers can route benign chat into a skill with extra capabilities or side effects the user did not intend to invoke.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The routing table uses generic signals like '烦' or '任务' without firm disambiguation rules, increasing the chance that ordinary conversation is misrouted into the skill. This becomes more concerning given the reported hidden file/shell-related capabilities elsewhere in the package, because accidental activation expands exposure to unnecessary tool use.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The activation description includes broad everyday phrases like 来张图 and 只要一张图, and it does not provide exclusion conditions or negative examples. This makes it unclear when this adapter should activate versus ordinary image-related conversation, increasing the chance of accidental invocation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

All user-facing manifest text, including the default prompt instruction, is presented only in Chinese, and there is no indication that users may choose another language or locale. This can violate language or locale policy when a skill imposes a specific language without opt-in or documented justification.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The default prompt auto-invokes the skill with a broad phrase like '今天全套,快点', which creates loose activation boundaries and may cause the agent to route user requests into this skill even when the user did not clearly request it. In a decision-assistant context, this can lead to unintended handling of adjacent requests, user confusion, and over-collection of contextual data under an ambiguous trigger.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This JSON asset presents all user-facing text exclusively in Chinese, including the module, title, reason, action, footer, and alt text. Because there is no indication that the skill is region-specific or that users can opt into this locale, it may violate the language/locale policy requiring choice or documented justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This markdown file presents all guidance and examples exclusively in Chinese, which effectively forces a specific language for users and downstream skill authors. The policy allows locale constraints only when they are explicitly justified or when users are offered a language choice, neither of which appears here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This markdown file contains user-facing instructions and output templates exclusively in Chinese, including the core prompts and response formats. Because the skill does not offer the user an opt-in language choice or explain that it is intentionally limited to Chinese-speaking users, it can violate the language/locale policy for natural-language behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The entire skill contract is written as a mandatory Chinese-only interaction pattern, with fixed Chinese trigger phrases and output labels, but it does not indicate that users may choose another language or opt into Chinese output. This creates a language/locale policy concern because the skill appears to require a specific language by default rather than offering a choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The document is written entirely in Chinese and provides no indication that language selection is optional or that the skill is intentionally limited to Chinese-speaking users. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless clearly justified.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The default prompt embeds an activation pattern ('$workday-companion') but does not define clear invocation boundaries or fallback behavior, while also using broad natural-language phrasing like '今天全套,快点'. In systems that reuse this listing text for discovery or prompt chaining, the ambiguity can lead to accidental invocation, prompt confusion, or misrouting of general conversation into the skill.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The public trigger examples include very common conversational phrases such as '今天烦' and '下班想逃', which can overlap with ordinary user speech and increase the chance of accidental invocation or misleading routing in host environments. In a directory or launcher that uses fuzzy matching, this can cause unintended activation, user confusion, or the skill being surfaced for sensitive emotional statements without explicit intent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The release assertion "listing_uses_chinese_primary_name" indicates a hard requirement for Chinese-primary presentation. This is a language/locale constraint stated without any user choice, opt-in mechanism, or documented region-specific justification, which conflicts with the language-choice policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This manifest/config file contains natural-language enum values restricted to Chinese only, which imposes a specific language on downstream use. The file does not indicate user opt-in, alternative locales, or a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module metadata and generated card text contain fixed Chinese-language strings, and the script provides no option for users to select another language or opt into this locale. This constitutes a language/locale policy issue because the output format is forced rather than user-selectable or explicitly justified as region-specific.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/package_release.py (reported line 95)May include surrounding context.

python
with ZipFile(archive_path) as archive:
            archive.extractall(temp)
        installed = temp / ROOT.name
        subprocess.run(
            [sys.executable, str(installed / "scripts/validate_skill.py"), "--quiet"],
            cwd=installed,
            check=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/package_release.py (reported line 100)May include surrounding context.

python
cwd=installed,
            check=True,
        )
        subprocess.run(
            [sys.executable, str(installed / "scripts/validate_rendered_cards.py")],
            cwd=installed,
            check=True,

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/render_card.py (reported line 65)May include surrounding context.

python
def load_card(path: str) -> dict[str, Any]:
    raw = Path(path).read_text(encoding="utf-8") if path != "-" else __import__("sys").stdin.read()
    data = json.loads(raw)
    if not isinstance(data, dict):
        raise SystemExit("Card JSON must be an object.")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/validate_rendered_cards.py (reported line 38)May include surrounding context.

python
stem = card_path.stem
    html_path = out_dir / f"{stem}.html"
    svg_path = out_dir / f"{stem}.svg"
    subprocess.run(
        [
            sys.executable,
            str(RENDER_SCRIPT),

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/package_release.py:32

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/validate_skill.py:76