Back to skill

Security audit

Data Classification

Security checks for vulnerabilities and agentic risk

Overview

This is a local data-schema classification skill whose main behavior matches its stated purpose, though users should handle exported CSVs and schema metadata carefully.

Install only if you are comfortable sending schema metadata to this skill for local classification. Treat generated CSVs as sensitive, and avoid opening exported CSVs in spreadsheet software when the input schema may contain untrusted field names or comments.

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/classify_data.py:271
Finding

CSV Formula Injection in Exported Classification Results

Content
View full analysis

Vulnerability Details

File Location: scripts/classify_data.py:271-296
Vulnerability Type: CSV formula injection
Risk Level: Medium

Vulnerable Code

python
def output_row(r: Result, include_finance: bool) -> list[str]:
    type_comment = f"{r.dtype} {r.comment}".strip()
    row = [r.table, r.field, type_comment, r.general_category, r.general_level]
    if include_finance:
        row += [r.finance_category, str(r.finance_level or "待确认"), r.finance_candidates, r.dual_label]
    row += [f"{r.confidence:.2f}", ";".join(x for x in [r.basis, r.review] if x)]
    return row


def render_markdown(results: list[Result], include_finance: bool) -> str:
    headers = output_headers(include_finance)
    lines = ["|" + "|".join(headers) + "|", "|" + "|".join(["---"] * len(headers)) + "|"]
    for r in results:
        lines.append("|" + "|".join(str(c).replace("|", "/") for c in output_row(r, include_finance)) + "|")
    lines.append("")
    lines.append(f"覆盖校验:输入/解析字段 {len(results)} 个,已分类 {len(results)} 个,遗漏 0 个。")
    return "\n".join(lines)


def render_csv(results: list[Result], include_finance: bool) -> str:
    out = StringIO()
    headers = output_headers(include_finance)
    writer = csv.writer(out)
    writer.writerow(headers)
    for r in results:
        writer.writerow(output_row(r, include_finance))
    return out.getvalue()

Relevant user-controlled input reaches these rows through scripts/classify_data.py:303-318:

python
src.add_argument("--field", help="single field name")
src.add_argument("--fields", help="comma/newline separated field names or a path to a text file")
src.add_argument("--sql", help="path to SQL DDL file")

if args.field:
    items = [FieldItem(table="", name=args.field)]
elif args.fields:
    p = Path(args.fields)
    raw = p.read_text(encoding="utf-8") if p.exists() else args.fields
    names = [x.strip() for x in re.split(r"[,\n]", raw) if x.strip()]
    items = [FieldItem(table="", name=x) for x in names
...[truncated 2607 chars]
Remediation
View remediation

Remediation Suggestions

Apply spreadsheet-safe encoding to every potentially user-derived CSV cell before calling writer.writerow():

  1. Convert each value to a string.
  2. Detect the first non-whitespace character.
  3. If it is =, +, -, or @, prefix the value with an apostrophe.
  4. Consider tabs, carriage returns, line feeds, and Unicode whitespace that could precede a formula marker.
  5. Apply the protection to all exported cells rather than only field names, because table names, data types, and comments may also be attacker-controlled.
  6. Add regression tests covering each dangerous prefix, leading whitespace, SQL comments, and benign values.

Example hardening approach:

python
FORMULA_PREFIXES = ("=", "+", "-", "@")


def spreadsheet_safe(value: object) -> str:
    text = str(value)
    effective = text.lstrip()
    if effective.startswith(FORMULA_PREFIXES):
        return "'" + text
    return text


def render_csv(results: list[Result], include_finance: bool) -> str:
    out = StringIO()
    writer = csv.writer(out)
    writer.writerow([spreadsheet_safe(v) for v in output_headers(include_finance)])
    for result in results:
        writer.writerow([
            spreadsheet_safe(v)
            for v in output_row(result, include_finance)
        ])
    return out.getvalue()

For stronger separation of concerns, offer a documented spreadsheet-safe export mode and make it the default for files intended to be opened in office applications. Clearly warn consumers if a raw, unmodified CSV mode remains available.

Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (7)

Hidden Instructions

High
Category
Prompt Injection
Confidence
60% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · references/jrt0197-appendix-a-full.csv (reported line 1)May include surrounding context.

text
序号,一级子类,二级子类,三级子类,四级子类,内容,最低安全级别参考,备注
1,客户,个人,个人自然信息,个人基本概况信息,"指个人基本情况数据,如个人姓名、性别、国籍、《海外账户纳税法案》(FATCA)有关个人身份数据、民族、婚姻状况、证件类型、证件号码、证件生效日期、证件到期日期、家庭住址等。",3,
2,客户,个人,个人自然信息,个人财产信息,"指个人的财产数据,如个人收入状况、拥有的不动产状况、拥有的车辆状况、纳税额、公积金缴存金额、个人社保与医保存缴金额等。",3,
3,客户,个人,个人自然信息,个人联系信息,"指个人各类通信联系方式数据,如手机、固定电话、电子邮箱地址、微信号等。",3,

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill instructs the agent to read local SQL/DDL files and reference files, but it declares no explicit tool scope or permissions. That creates an authorization ambiguity: a host system may permit broader file access than the skill actually needs, increasing the risk of unintended local file reads or over-privileged execution.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest description is written as a Chinese-only instruction and the required output fields and coverage text elsewhere in the file are also specified in Chinese, indicating a fixed-language behavior. There is no explicit user opt-in, language choice, or documented reason that the skill must operate only in Chinese.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly tells the agent to create CSV files and expose them via MEDIA: using an absolute filesystem path. Revealing absolute local paths can leak host environment details, and writing files without a clear user-facing warning can create unintended persistence or disclosure of sensitive classification results.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This CSV is natural-language content and all visible headers and descriptions are written in Chinese. Under the language/locale policy rule, forcing a specific language without user opt-in or a clearly documented region-specific justification can be a policy violation; this file does not state any such opt-in or scope within the file itself.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The skill explicitly accepts SQL/DDL files and extracts table names, column names, types, and comments, which can contain sensitive business or personal-data indicators. The markdown explains how to process these inputs but does not warn users that schema contents may be sensitive and should only be provided when appropriate.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The file title and all instructional content are presented only in Chinese, which can constitute a language/locale policy issue when no user opt-in or justification is provided. The document does not indicate that the skill is region-specific or that Chinese is optional.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.