Back to skill

Security audit

质性主题分析

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate local thematic-analysis skill, but it needs review because it handles sensitive interview files and its helper scripts can expose raw content in logs and unsafe spreadsheet cells.

Install only if you are comfortable processing the selected research files locally and can control terminal or agent logs. De-identify interview data where possible, confirm participant consent for AI-assisted analysis, avoid opening generated XLSX files from untrusted content without formula protections, and treat the DOCX report exporter as currently broken until its syntax error is fixed.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/export_coding.py:56
Finding

Spreadsheet Formula Injection in XLSX Coding Export

Content
View full analysis

Vulnerability Details

File Location: scripts/export_coding.py, lines 56-72
Vulnerability Type: Untrusted data written to formula-capable spreadsheet cells
Risk Level: Medium

Complete Code Snippet

python
values = [
    code.get("theme", ""),
    code.get("code", ""),
    code.get("sub_code", ""),
    code.get("quote", ""),
    code.get("source", ""),
    code.get("line", ""),
    code.get("note", ""),
]
for col, val in enumerate(values, 1):
    cell = ws.cell(row=row_idx, column=col, value=val)
    cell.alignment = Alignment(wrap_text=True, vertical="top")
    cell.border = border
    if row_fill:
        cell.fill = row_fill
ws.row_dimensions[row_idx].height = 40

Technical Analysis

All values from the input coding JSON are assigned directly to openpyxl cells without validation or formula neutralization. This includes quotations and other fields that may originate from untrusted interview documents.

When openpyxl receives a string beginning with =, it can store the value as a spreadsheet formula rather than literal text. Other spreadsheet applications may also interpret values beginning with +, -, or @ as formulas. Consequently, attacker-controlled qualitative material can become executable spreadsheet content in the generated XLSX file.

A malicious input could use a formula that requests an external resource, constructs a deceptive hyperlink, or references other workbook cells. The exact behavior depends on the spreadsheet application and its security configuration.

Attack Path

  1. An attacker places a formula-prefixed value in an interview document or other analyzed source.
  2. The malicious text is copied into a coding JSON field such as quote, code, source, or note.
  3. The user runs export_coding.py against that JSON file.
  4. The script passes the value directly to ws.cell(..., value=val).
  5. openpyxl stores a value beginning wit ...[truncated 994 chars]
Remediation
View remediation

Remediation Suggestions

  • Treat every JSON-derived spreadsheet field as untrusted text.
  • Before assigning a string to a cell, detect values whose first non-whitespace character is =, +, -, or @.
  • Prefix dangerous values with an apostrophe or apply another spreadsheet-compatible text-neutralization mechanism.
  • Explicitly preserve exported values as text rather than formulas.
  • Validate that the top-level JSON value is a list and that each entry is an object containing values of expected types.
  • Add regression tests using payloads such as formula-prefixed quotations, leading whitespace followed by a formula marker, and formula content in every exported column.
  • Document that generated workbooks may contain participant-supplied data and should not contain active formulas unless explicitly required.

Example hardening logic:

python
def spreadsheet_safe_text(value):
    if value is None:
        return ""
    value = str(value)
    if value.lstrip().startswith(("=", "+", "-", "@")):
        return "'" + value
    return value

for col, val in enumerate(values, 1):
    cell = ws.cell(
        row=row_idx,
        column=col,
        value=spreadsheet_safe_text(val),
    )

T09 · Insecure Skill Coding Practices

Note
Location
scripts/extract_text.py:78
Finding

Sensitive Interview Content Is Unconditionally Written to Standard Output

Content
View full analysis

Vulnerability Details

File Location: scripts/extract_text.py, lines 78-82
Vulnerability Type: Plaintext disclosure of potentially sensitive research data through process logs
Risk Level: Low

Complete Code Snippet

python
combined = "\n".join(all_text)
print(f"\nTotal character count: {len(combined)}")
print(combined[:3000] + "\n...[display truncated to the first 3000 characters]" if len(combined) > 3000 else combined)

The displayed English literals correspond to the messages in the source; the data-flow behavior is unchanged.

Technical Analysis

After extracting TXT, DOCX, or PDF content, the script unconditionally writes up to 3,000 characters of the combined source material to standard output. The project explicitly recognizes that interview records commonly contain participant personal information.

Standard output is not necessarily limited to a private interactive terminal. It may be retained by an Agent runtime, orchestration platform, CI job, notebook, shell capture, monitoring service, or centralized logging system. This creates an additional plaintext copy of sensitive source material outside the intended research files.

The issue is a local secondary-disclosure risk. The reviewed code contains no direct network transmission or external exfiltration mechanism.

Attack Path

  1. A researcher processes interview records containing names, contact information, health information, opinions, or other confidential statements.
  2. extract_text.py reads and combines the source content.
  3. The script prints the first 3,000 characters to standard output without obtaining confirmation or applying redaction.
  4. The execution environment captures or retains standard output.
  5. A person or service with access to those logs can read the disclosed interview content, even if that party cannot access the original research files.

Impact Assessment

The exposed scope is limited to th ...[truncated 501 chars]

Remediation
View remediation

Remediation Suggestions

  • Do not print extracted source content by default.
  • Limit normal output to filenames, file counts, extraction status, and aggregate character counts.
  • Add an explicit --preview option if content previews are operationally necessary.
  • Display a confidentiality warning and require affirmative user intent before previewing raw text.
  • Allow users to configure a preview length, with zero as the secure default.
  • Apply identifier redaction before displaying previews where practical.
  • Ensure Agent runtimes and automation systems do not retain sensitive stdout, or configure short retention periods and restrictive log permissions.
  • Add tests confirming that default execution never emits extracted document content.

A safer default is:

python
combined = "\n".join(all_text)
print(f"Total character count: {len(combined)}")
print("Extraction completed. Content preview is disabled by default.")
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (12)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill is designed to analyze local qualitative materials such as interviews and observation notes, which commonly contain personal, confidential, or regulated data. Without an explicit privacy warning and consent-oriented handling guidance, users may expose sensitive participant information or research data without understanding the risk.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The activation criteria are broad enough that the skill could trigger on loosely related requests involving interviews, coding, or qualitative analysis. In context, this increases the chance the agent solicits local file paths and processes sensitive research materials without clear user intent, creating privacy and data-handling risk.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Lines L041-L060 describe a systematic process that reads all files and produces initial coding as part of Braun & Clarke's method. However, L133-L149 explicitly states the current implementation only reads excerpts, jumps directly to themes, and may not call the coding export script, which contradicts the earlier operational instructions rather than merely omitting detail.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This markdown file is written entirely in Chinese and presents the guidance as the required operating format, with no indication that other languages are supported or that Chinese is optional. Under the policy, language constraints should either be opt-in or clearly documented and justified; neither is present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This markdown file contains instructional content solely in Chinese, and there is no indication that users may choose another language or that the skill is intentionally restricted to a Chinese-language audience. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring presents the tool description and usage only in Chinese, and the script continues to emit Chinese-only user-facing text. For a general-purpose export utility, this imposes a specific language on users without opt-in or justification, matching the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The dependency error message is emitted only in Chinese, and users are not given any language choice. This is a natural-language policy issue because the script forces one locale in operational output without opt-in or documented regional limitation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Both the success message and CLI usage guidance are presented only in Chinese. Because this is a general script interface rather than a clearly region-specific compliance tool, hard-coding one language violates the stated language/locale policy criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code file contains natural-language strings exclusively in Chinese in the module docstring and CLI usage text, which imposes a specific language on users. The policy allows locale constraints only when users are given a choice or the restriction is clearly justified, neither of which is present here.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This is a code file, so SQP-2 applies to safety-relevant operations lacking user disclosure. The script extracts text from user-supplied files and outputs up to 3000 characters directly to the terminal, but there is no warning in the docstring, usage text, or nearby output that sensitive document contents may be exposed on screen or in terminal logs.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The entire skill guidance is presented only in Chinese, with no indication that users may choose another language or locale. Under the policy for natural-language violations, forcing a specific language without opt-in can be a locale-policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

SQP-3 applies to all file types and includes language or locale policy violations. The docstring and all user-facing messages are in Chinese, with no indication that the tool is intended only for Chinese-speaking users and no opt-in or alternative locale support.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.