Back to skill

Security audit

Lerwee Alert Inspection

Security checks for vulnerabilities and agentic risk

Overview

This monitoring report skill is not proven malicious, but it needs Review because it uses API credentials and live monitoring data while requiring unsafe temporary script execution and retaining sensitive local report data.

Install only in a trusted internal environment after reviewing the exporter workflow. Require HTTPS for LWJK_API_URL, keep LWJK_API_SECRET out of shared files, restrict the output directory, avoid untrusted report names or paths, inspect or replace the temporary Excel script generation, and delete intermediate JSON/temp files if they contain sensitive infrastructure data.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (5)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:94
Finding

Mandatory Third-Party Attribution Alters User-Facing Reports

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
alert_data.py:75
Finding

Sensitive Monitoring API Traffic Uses Plaintext HTTP

Content
View full analysis
dict: payload = dict(params) payload["timestamp"] = int(datetime.now().timestamp()) payload["sign"] = make_sign(payload, api_secret) body = json.dumps(payload, ensure_ascii=False).encode("utf-8") request = urllib.request.Request( api_url.rstrip("/") + route, data=body, headers={"Content-Type": "application/json"}, method="POST", ) with urllib.request.urlopen(request, timeout=timeout) as response: return json.loads(response.read().decode("utf-8")) ``` ```python api_url = os.environ.get("LWJK_API_URL", "") api_secret = os.environ.get("LWJK_API_SECRET", "") if not api_url or not api_secret: raise SystemExit("LWJK_API_URL 和 LWJK_API_SECRET 未配置,请检查 skills/alert-inspection/.env") problems = fetch_all_pages( api_url, api_secret, "/api/v6/alert/problem-list", build_problem_params(args), args.problem_page_size or args.page_size, "problem-list", ) ``` ### Technical Analysis The configured API endpoint uses `http://`. Consequently, monitoring filters, timestamps, secret-derived SHA-1 signatures, host inventories, IP addresses, and alert records can traverse the network without transport encryption or server authentication. The API secret is not directly included in the request body. It is used to derive the `sign` value. Nevertheless, the signature and associated request parameters are observable over plaintext transport. The timestamp provides limited freshness, but the code does not demonstrate a nonce or client-side replay prevention. Plain H ...[truncated 1234 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
references/export_excel_template.py:26
Finding

Unsafe Executable-Template Substitution and Predictable Temporary Script

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
references/export_excel_template.py:98
Finding

Spreadsheet Formula Injection in Exported Monitoring Data

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
alert_data.py:211
Finding

Complete Raw API Objects Are Unnecessarily Persisted to Disk

Content
View full analysis
dict: classification = first_value(host, "classification_label", "classificationLabel", "classification_name", "classificationName") if classification in (None, ""): classification = CLASSIFICATION_LABELS.get(safe_int(first_value(host, "classification")), "") active_status = safe_int(first_value(host, "active_status", "activeStatus", "status"), -1) power_status = safe_int(first_value(host, "power_status", "powerStatus", "available"), 0) monitor_status = first_value( host, "active_status_label", "activeStatusLabel", "status_text", "statusText", "monitor_status_text", "monitorStatusText", ) if monitor_status in (None, ""): monitor_status = ACTIVE_STATUS_LABELS.get(active_status, str(active_status)) collect_status = first_value( host, "power_label", "powerLabel", "available_text", "availableText", "collect_status_text", "collectStatusText", ) if collect_status in (None, ""): collect_status = POWER_STATUS_LABELS.get(power_status, str(power_status) if power_status else "") return { "hostid": str(first_value(host, "hostid", "id", "hostId") or ""), "name": str(first_value(host, "name", "host_name", "hostName", "hostname") or ""), "ip": str(first_value(host, "ip", "hostip", "host_ip", "true_ip", "agent_ip") or ""), "classification": classification or "", "active_status": active_status, "active_status_label": str(monitor_status or ""), "monitor_status": str(monitor_status or ""), "power_status": power_status, "power_label": str(collect_st ...[truncated 3137 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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
Findings (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared behavior says the skill exports a finished 4-sheet Excel workbook, but the documented flow actually returns a template path and instructs creation/execution of a temporary script, while also producing additional JSON artifacts not clearly disclosed in the description. This mismatch is dangerous because reviewers and users may approve the skill under incomplete assumptions, and downstream agents may execute extra file-generation steps or rely on outputs that were never promised.

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 · generate_report.py (reported line 60)May include surrounding context.

python
return read_json_rows(args.hosts_file), read_json_rows(args.problems_file)

    skill_dir = Path(__file__).resolve().parent
    load_env(skill_dir / ".env")
    load_env(skill_dir.parent / "alert-inspection" / ".env")

    api_url = Path

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 · generate_report.py (reported line 61)May include surrounding context.

python
return read_json_rows(args.hosts_file), read_json_rows(args.problems_file)

    skill_dir = Path(__file__).resolve().parent
    load_env(skill_dir / ".env")
    load_env(skill_dir.parent / "alert-inspection" / ".env")

    api_url = Path

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 · generate_report.py (reported line 70)May include surrounding context.

python
return read_json_rows(args.hosts_file), read_json_rows(args.problems_file)

    skill_dir = Path(__file__).resolve().parent
    load_env(skill_dir / ".env")
    load_env(skill_dir.parent / "alert-inspection" / ".env")

    api_url = Path

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill performs sensitive operations including reading environment variables, making network requests, and writing files, but SKILL.md declares no explicit tool scope or permission boundaries. This creates unnecessary ambient authority: an agent may invoke the skill with broader capabilities than users expect, increasing the chance of unintended data access or file-system side effects.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The workflow instructs the agent to copy a template to /tmp, substitute values, and execute the generated Python script, while also writing multiple local files, without any user-facing warning or consent step. Generating and executing temporary scripts is a powerful side effect that can expand attack surface, especially if placeholder values or file paths are influenced by untrusted data or if the environment treats /tmp as shared.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrases are broad everyday requests such as '做巡检' and related variants, which can cause accidental invocation in contexts where the user did not intend network access, credential use, file writes, or script execution. Because this skill has side effects and uses external data sources, overly broad triggers materially increase the risk of unintended execution.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The report template, workbook contract, and field names mandate Chinese titles, labels, and worksheet names, and the file does not provide any language-selection option. This creates a locale policy concern because the skill imposes a specific language without user opt-in or an explicit region-specific justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file embeds user-visible status and classification labels entirely in Chinese, with no indication that language is configurable or selected by the user. This can violate language/locale policy when a skill imposes a specific locale by default without offering choice or documenting a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code constructs and sends HTTP POST requests containing request parameters and a signed payload to an external API, but the function has no user-facing prompt, warning, or explanatory comment/docstring about transmitting data off-host. For a code file, outbound network operations that may send user or system data should have some form of disclosure unless the warning is documented elsewhere or clearly evident from the skill context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script accesses LWJK_API_URL and LWJK_API_SECRET, which are credentials or sensitive configuration, but gives no prior user-facing indication that secrets will be loaded from .env files or environment variables. Under the code-file criteria, access to sensitive environment variables should not be silent when there is no other visible disclosure in the file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code calls remote API endpoints via fetch_all_pages and transmits authentication material loaded from LWJK_API_SECRET, but the script provides no confirmation prompt, print/log notice, or inline warning describing that outbound requests and credential use will occur. For code files, network calls that transmit user or system data should have some form of visible disclosure unless clearly communicated elsewhere in the skill, which is not evident in this file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script writes a Markdown report plus normalized host and problem datasets to disk without any user-facing warning or consent. Because these files can contain hostnames, IPs, alert descriptions, and operational status, silent persistence may create sensitive local artifacts that can be read, copied, or retained longer than intended.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The manifest says the skill generates a Markdown inspection report and exports an Excel workbook with 4 sheets. In this file, the payload explicitly sets "excel_file" to None and only provides a template path plus a "next_step" instruction to generate another script later, so the claimed Excel export behavior is not implemented here.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The file requires LWJK_API_SECRET and says it is read from .env, but it does not warn users that the skill accesses credentials and transmits monitoring data to an external API. For a markdown skill description, this omission leaves privacy and credential usage insufficiently disclosed.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · alert_data.py (reported line 289)May include surrounding context.

python
def build_problem_params(args) -> dict:
    params = {"searchtype": args.searchtype or "history", "status": args.status}
    for attr in ("clock_begin", "clock_end", "ip", "keyword", "priority", "sort_order", "sort_name"):
        value = getattr(args, attr)
        if value not in (None, ""):
            key = attr.replace("_", "")
            if attr in {"sort_order", "sort_name"}:

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · alert_data.py (reported line 296)May include surrounding context.

python
def build_problem_params(args) -> dict:
    params = {"searchtype": args.searchtype or "history", "status": args.status}
    for attr in ("clock_begin", "clock_end", "ip", "keyword", "priority", "sort_order", "sort_name"):
        value = getattr(args, attr)
        if value not in (None, ""):
            key = attr.replace("_", "")
            if attr in {"sort_order", "sort_name"}:

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · alert_data.py (reported line 316)May include surrounding context.

python
def build_problem_params(args) -> dict:
    params = {"searchtype": args.searchtype or "history", "status": args.status}
    for attr in ("clock_begin", "clock_end", "ip", "keyword", "priority", "sort_order", "sort_name"):
        value = getattr(args, attr)
        if value not in (None, ""):
            key = attr.replace("_", "")
            if attr in {"sort_order", "sort_name"}:

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

Several user-visible strings, including errors, report headings, conclusions, and next-step instructions, are hardcoded in Chinese throughout the script. The policy requires avoiding forced language/locale behavior unless the user is given a choice or the region-specific constraint is explicitly justified, which is not present here.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The script writes normalized host and problem JSON files to disk in addition to the user-visible report, even though the skill description only mentions report generation and Excel export. Persisting extra structured monitoring data can expose sensitive infrastructure details, increase data retention risk, and surprise users who did not consent to those artifacts being stored.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.