Back to skill

Security audit

platform-script

Security checks for vulnerabilities and agentic risk

Overview

This template skill is mostly a static coding aid, but it includes ready-to-use examples that could expose passwords, reset many accounts, delete business data, and generate unsafe SQL.

Review carefully before installing. This skill should only be used by operators who can spot and rewrite unsafe generated platform scripts. Do not copy the password-reset listener, do not log credentials, validate SQL inputs or use parameters, and test destructive or data-changing scripts in a non-production environment with rollback plans.

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

T09 · Insecure Skill Coding Practices

Error
Location
references/platform-script-templates.txt:121
Finding
Mass Credential Disclosure and Weak Password Reset## Vulnerability Details **File Location**: `references/platform-script-templates.txt`, lines 121–133 **Vulnerability Type**: Plaintext credential exposure and insecure account modification **Risk Level**: Critical ### Vulnerable Code ```groovy def 账号数据 = DataModelUtils.getCIByAttr("gdmp_account") for(aa in 账号数据){ if(aa.dataFieldMap.accountNo != "admin" && aa.dataFieldMap.accountNo != "guest"){ def 原始账号 = aa.dataFieldMap.accountNo println "原始账号==" + 原始账号 def 原始密码 = aa.dataFieldMap.password println "原始密码==" + 原始密码 def 修改密码 = "123456" println "修改密码==" + 修改密码 aa.dataFieldMap.password = 修改密码 DataModelUtils.saveCi(aa) } } ``` ### Technical Analysis The listener template retrieves every record from the platform account table, reads the existing password field, and prints that password to application logs. It then replaces the password of every account except `admin` and `guest` with the same hardcoded value, `123456`. This violates credential confidentiality and password-storage best practices. If the password field contains plaintext or reversible values, the original credentials become available to anyone with log access. Independently, assigning one predictable password to many accounts creates a platform-wide credential compromise. Excluding two accounts does not protect the remaining users. Although this code is distributed as a template rather than an automatically executed package script, `SKILL.md` explicitly directs the Agent to read and reuse this reference when generating platform scripts. ### Attack Path 1. An attacker requests a platform listener script based on the bundled listener example or convinces an operator to deploy it. 2. The generated listener executes with access to the `gdmp_account` data model. 3. It enumerates all account records and writes original password values to logs. 4. ...[truncated 829 chars]
Remediation
## Remediation Suggestions - Remove the credential-reading and mass password-reset example from the reference file. - Never print password fields, password hashes, reset tokens, or other authentication material. - Do not access password columns through generic data-model APIs. - Route password changes through a dedicated, authenticated password-reset service. - Require explicit authorization and target one identified account per administrative operation. - Enforce strong password policy and generate a unique reset secret for each account. - Store passwords only as salted, computationally expensive hashes. - Require the user to replace temporary credentials immediately and invalidate active sessions after a reset. - Review existing logs for exposed credentials, securely purge affected records where permitted, rotate exposed credentials, and notify affected users. - Add a security test or static-analysis rule that rejects scripts reading, logging, or directly assigning account password fields.

T09 · Insecure Skill Coding Practices

Error
Location
references/platform-script-templates.txt:207
Finding
SQL Injection Through Interpolated Form Parameters## Vulnerability Details **File Location**: `references/platform-script-templates.txt`, lines 207–231 **Vulnerability Type**: SQL injection **Risk Level**: High ### Vulnerable Code ```groovy def sql = """ """ if(飞机号){ sql += """ AND RN = '${飞机号}' """ } if(起飞机场){ sql += """ AND Dep_Airport_CN = '${起飞机场}' """ } if(到达机场){ sql += """ AND Arr_Airport_CN = '${到达机场}' """ } def data = ScriptUtils.runScriptByCode("调用北京华龙通用接口",attrmap); ``` The interpolated values are populated earlier from form input: ```groovy if(args$&&args$.attrKVs){ args$.attrKVs.each{ if(it.attribute=="飞机号"&&it.value){ 飞机号=it.value } if(it.attribute=="起飞机场全称"&&it.value){ 起飞机场=it.value } if(it.attribute=="到达机场全称"&&it.value){ 到达机场=it.value } } } ``` ### Technical Analysis Values taken from `args$.attrKVs` are inserted directly into SQL string literals. No prepared statement, parameter binding, escaping, or allowlist validation separates user-controlled data from SQL syntax. An attacker can include quote characters and SQL operators in a form field to terminate the intended string literal and append a new predicate. The resulting query is then forwarded to a platform script responsible for querying the external interface. ### Attack Path 1. An attacker obtains access to the form or API that supplies `args$.attrKVs`. 2. The attacker submits a crafted field value such as `' OR '1'='1`. 3. The value is assigned to an aircraft or airport variable. 4. Groovy interpolation places the payload directly into the SQL statement. 5. The query is passed to the external-query script and executed under that script's database privileges. 6. The injected predicate bypasses intended filtering and returns records outside the attacker's authorized ...[truncated 491 chars]
Remediation
## Remediation Suggestions - Replace all interpolation with parameterized SQL placeholders. - Pass aircraft and airport values separately through the query API's parameter collection. - Apply strict maximum lengths and allowlist expected identifier characters. - Reject control characters, quotes, comments, and malformed airport or aircraft identifiers as defense in depth. - Ensure the downstream database account has read-only access to the minimum required views. - Disable stacked statements in the database driver. - Add tests containing quotes, SQL comments, Boolean predicates, and statement separators to verify that input is always treated as data.

T09 · Insecure Skill Coding Practices

Error
Location
references/platform-script-templates.txt:1304
Finding
SQL Injection and Resource Exhaustion Through Pagination Parameters## Vulnerability Details **File Location**: `references/platform-script-templates.txt`, lines 1304–1317 **Vulnerability Type**: SQL injection and unbounded pagination **Risk Level**: High ### Vulnerable Code ```groovy def pageNo=args$.pageNo def pageSize=args$.pageSize def 当前日期 = System.currentTimeMillis() def headers = [] headers << ['name': "id", 'dataType':"string"]; headers << ['name': "提醒人", 'dataType':"string"]; headers << ['name': "飞机号", 'dataType':"string"]; def sql = """ """ def totalData = DataModelUtils.queryForListMap(sql,null) def total = totalData.size() sql += "LIMIT ${pageSize} OFFSET (${pageNo} - 1) * ${pageSize}" def data = DataModelUtils.queryForListMap(sql,null) ``` ### Technical Analysis `pageNo` and `pageSize` are obtained directly from `args$` and interpolated into SQL syntax. The template does not establish that these values are integers, positive, or within an acceptable upper bound. A caller able to supply strings rather than strongly typed integers may inject SQL tokens through either field. Even where the platform coerces the values to numbers, an excessively large page size or offset can trigger expensive scans, excessive result allocation, and database or application resource exhaustion. The separate unpaginated query used only to calculate `total` also loads the complete result set, magnifying denial-of-service risk for large datasets. ### Attack Path 1. An attacker calls the dataset endpoint with crafted `pageNo` or `pageSize` values. 2. The script copies those values from `args$` without validation. 3. String interpolation places the supplied values directly into the `LIMIT` and `OFFSET` clause. 4. A SQL payload can alter the statement if the runtime accepts string values. 5. Alternatively, the attacker repeatedly requests extremely large page sizes or offsets. 6. The database performs expensive work, while the preliminary total query materiali ...[truncated 414 chars]
Remediation
## Remediation Suggestions - Parse `pageNo` and `pageSize` as integers before constructing the query and reject parsing failures. - Require `pageNo` to be at least 1 and enforce a conservative maximum `pageSize`. - Use supported parameter binding for `LIMIT` and `OFFSET`; if the database cannot bind these clauses, interpolate only validated integer primitives. - Calculate the offset in application code with overflow-safe arithmetic. - Replace full-result materialization with `SELECT COUNT(*)` for total-count calculation. - Set database statement timeouts and per-request result limits. - Apply API rate limits to expensive dataset endpoints.

T09 · Insecure Skill Coding Practices

Error
Location
references/platform-script-templates.txt:2008
Finding
SQL Injection in Annual Aircraft Statistics Query## Vulnerability Details **File Location**: `references/platform-script-templates.txt`, lines 2008–2025 **Vulnerability Type**: SQL injection **Risk Level**: High ### Vulnerable Code ```groovy def 年度飞机境内外比例 (飞机号,年度){ def sqL = """ SELECT FLTArea, COUNT(1) AS count FROM View_Flight_Legs WHERE ImTripID IS NULL AND Company_ID IN (1, 5) AND YEAR(FlightDate) = '${年度}' AND RN = '${飞机号}' AND Status = 'Closed' GROUP BY FLTArea """ sqlmap=[:] sqlmap.put("sql",sqL) sqlmap.put("attr",null) def 国内外飞行量 = ScriptUtils.runScriptByCode("查询 FOS 数据通用接口",sqlmap); } ``` ### Technical Analysis The function accepts aircraft and year values as parameters and embeds both directly into an SQL string. It then explicitly supplies `null` as the query attribute or parameter collection. Consequently, the function does not preserve a boundary between caller-controlled data and SQL syntax. A malicious caller can inject a quote and additional SQL expression through either function parameter. The resulting statement is executed by the general FOS query interface. ### Attack Path 1. An attacker reaches a form, script, workflow, or API that invokes the statistics function with controllable parameters. 2. The attacker provides a crafted aircraft identifier or year containing SQL syntax. 3. The function interpolates the payload into the `WHERE` clause. 4. The complete SQL string is sent to the general FOS query script with no bound parameters. 5. The FOS database executes the altered query under the query service account. 6. The attacker bypasses aircraft, year, company, or status restrictions and obtains unauthorized aggregate or row data. 7. More severe effects are possible if the downstream interface permits stacked statements or write operations. ### Impact Assessment The attacker can potentially query flight records outside the intended aircraft and ...[truncated 275 chars]
Remediation
## Remediation Suggestions - Change the FOS query interface to accept an SQL template and a separate parameter array. - Use placeholders for both the year and aircraft identifier. - Parse the year as an integer and enforce an expected operational range. - Validate aircraft identifiers against the platform's canonical identifier format or a trusted aircraft registry. - Run the FOS query service with read-only access to only the required views. - Disable multiple statements and non-query commands at the interface layer. - Reject execution when a query contains unbound caller-derived values.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (21)

Missing User Warnings

Critical
Confidence
99% confidence
Finding
The sample code silently resets user passwords in bulk, excludes only admin and guest, and provides no authorization gate, approval step, user confirmation, or rollback. A copy-pasted or slightly adapted version could be used to seize control of many accounts and disrupt business operations immediately.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The listener template contains logic to iterate over account records, read existing passwords, print them, and reset them to a fixed value for nearly all users. In a general-purpose script-template skill, providing credential-reset code materially expands the skill into dangerous administrative action and lowers the barrier to mass account compromise.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
This template demonstrates bulk password modification capability unrelated to ordinary coding guidance, effectively serving as a ready-made account takeover script. Because it hardcodes a trivial replacement password and applies it broadly, misuse could immediately compromise many user accounts.

Ssd 3

High
Confidence
99% confidence
Finding
The listener prints account identifiers and plaintext passwords during processing, creating immediate credential exposure in logs and consoles. Log systems are often broadly accessible and long-lived, so this can turn a single script execution into durable compromise of multiple accounts.

Missing User Warnings

High
Confidence
94% confidence
Finding
This section shows listener-driven cascading deletions across several related datasets using deleteCis calls. Although comments describe the linkage, there is no warning that the script will automatically remove multiple records when triggered, which is a safety-critical destructive operation.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill documentation explicitly advertises data creation, deletion, and modification capabilities, including delete APIs, but does not warn users that generated scripts may change or remove business data. For a markdown skill description, omission of a warning about data-affecting behavior is a safety concern because users may invoke the skill without understanding the impact.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
The skill states it supports data-modifying SQL via JDBCUtils.update, which can directly alter database contents, but the markdown provides no caution about validation, transaction safety, or production impact. This omits an important user-facing warning for behavior that could affect system integrity and user data.

Session Persistence

Medium
Category
Rogue Agent
Content
### 6. 工具函数
- 日期格式化 (SimpleDateFormat)
- 时间戳生成
- 列表排序 (sortMapList)
- 字符串处理 (removeTrailingZeros)

### 7. 业务特定脚本
Confidence
75% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
### 6. 工具函数
- 日期格式化 (SimpleDateFormat)
- 时间戳生成
- 列表排序 (sortMapList)
- 字符串处理 (removeTrailingZeros)

### 7. 业务特定脚本
Confidence
75% 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.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The package description is entirely in Chinese and presents the skill as a general development tool, but the manifest does not indicate that the skill is region-specific or that users may choose another language. Under the policy, a language-specific constraint without opt-in or justification is a natural-language policy concern.

Ssd 3

Medium
Confidence
82% confidence
Finding
The form initialization example copies every field from a queried record into the returned map with no field allowlist or minimization. If the source record contains sensitive or internal-only attributes, the client may receive more data than necessary, increasing exposure risk.

Description-Behavior Mismatch

Medium
Confidence
84% confidence
Finding
技能描述强调提供脚本模板、SQL 查询和附件处理等开发辅助内容,但该示例直接构造邮件对象并向外部邮箱地址发送通知。发送外部通知是主动对外通信能力,不是单纯的编码规范展示,语义上超出了清单声明的有限用途。

Context-Inappropriate Capability

Medium
Confidence
81% confidence
Finding
这里的代码不仅展示数据处理,还执行实际通知分发,接收方包含具体邮箱地址。对于一个主要提供脚本模板和编码规范的技能,主动外发邮件并非显然必需能力,尤其当示例接近可直接用于生产发送时。

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
函数在 prod 分支仅打印“邮件已成功发送至...”日志,却没有像前面的单发示例那样调用 sendNotification(邮件对象) 或其他实际发送方法。该注释/日志会让使用者误以为代码已经完成发送,属于文档化意图与实际行为相矛盾。

Session Persistence

Medium
Category
Rogue Agent
Content
// 3. 渲染行数据
数据格式:
[
    "maplist": 
        [
            {"序号": 1, "项目": "飞机的管理费"},
            {"序号": 2, "项目": "维修管理费"}
Confidence
75% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
// 3. 渲染行数据
数据格式:
[
    "maplist": 
        [
            {"序号": 1, "项目": "飞机的管理费"},
            {"序号": 2, "项目": "维修管理费"}
Confidence
75% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
// 3. 渲染行数据
数据格式:
[
    "maplist": 
        [
            {"序号": 1, "项目": "飞机的管理费"},
            {"序号": 2, "项目": "维修管理费"}
Confidence
75% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
// 3. 渲染行数据
数据格式:
[
    "maplist": 
        [
            {"序号": 1, "项目": "飞机的管理费"},
            {"序号": 2, "项目": "维修管理费"}
Confidence
75% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
// 3. 渲染行数据
数据格式:
[
    "maplist": 
        [
            {"序号": 1, "项目": "飞机的管理费"},
            {"序号": 2, "项目": "维修管理费"}
Confidence
75% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
// 3. 渲染行数据
数据格式:
[
    "maplist": 
        [
            {"序号": 1, "项目": "飞机的管理费"},
            {"序号": 2, "项目": "维修管理费"}
Confidence
75% 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.

Missing User Warnings

Low
Confidence
76% confidence
Finding
The skill can export documents and process attachments, including PDF/Word merges and archive generation, but there is no warning that these actions may handle sensitive user or business documents. For markdown descriptions, user disclosure should mention privacy and data-handling considerations when operating on attachments or exported files.

Static analysis

No suspicious patterns detected.