Back to skill

Security audit

code-to-images

Security checks for vulnerabilities and agentic risk

Overview

The main skill does what it claims, but the package also includes undeclared scripts that can rewrite skill documentation and an installed skill file.

Review this package before installing because it includes extra maintenance scripts that can rewrite skill files and are not part of the documented converter workflow. If you use it, run only gen_code_pdfs.py, verify NODE_EXE points to a trusted Node binary, and install the npm/pip dependencies from trusted sources.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (15)

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · README.md (reported line 25)May include surrounding context.

md
- ✅ **49 种语言自动识别** — 按扩展名 / 文件名 / 内容自动选择语法规则(含 `.m` 内容嗅探与 `Makefile`/`Dockerfile`/`CMakeLists.txt` 文件名识别)
- ✅ **行号** — 自适应装订线宽度(千行文件自动加宽)
- ✅ **语法高亮** — 关键字、寄存器/特殊标识符、宏、数字、字符串、变量、标签、注释分别着色
- ✅ **多行注释** — `/* */`、`<!-- -->`、`--[[ ]]`、`{- -}`、`#= =#`、`(* *)`、`{ }` 等跨行注释完整灰显
- ✅ **三引号字符串** — Python / Julia / 仓颉的 `"""` `'''` 跨行字符串
- ✅ **语言特性高亮** — HTML/XML 标签、`@` 注解与指令、`$` 变量(含 `${}`/`$()`)、Makefile 目标行、YAML 键、Markdown 标题
- ✅ **忠实缩进** — 直接保留源码的实际前导空格 / Tab,C 风格大括号与 Python 风格空格缩进都正确呈现

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · README.md (reported line 25)May include surrounding context.

md
- ✅ **49 种语言自动识别** — 按扩展名 / 文件名 / 内容自动选择语法规则(含 `.m` 内容嗅探与 `Makefile`/`Dockerfile`/`CMakeLists.txt` 文件名识别)
- ✅ **行号** — 自适应装订线宽度(千行文件自动加宽)
- ✅ **语法高亮** — 关键字、寄存器/特殊标识符、宏、数字、字符串、变量、标签、注释分别着色
- ✅ **多行注释** — `/* */`、`<!-- -->`、`--[[ ]]`、`{- -}`、`#= =#`、`(* *)`、`{ }` 等跨行注释完整灰显
- ✅ **三引号字符串** — Python / Julia / 仓颉的 `"""` `'''` 跨行字符串
- ✅ **语言特性高亮** — HTML/XML 标签、`@` 注解与指令、`$` 变量(含 `${}`/`$()`)、Makefile 目标行、YAML 键、Markdown 标题
- ✅ **忠实缩进** — 直接保留源码的实际前导空格 / Tab,C 风格大括号与 Python 风格空格缩进都正确呈现

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is for a code-to-images/PDF conversion skill, but the supplied code chunk is a maintenance script for fixing anchor links in Markdown documentation. It does not process code files for rendering, does not generate PNG/SVG/PDF output, and instead reads and rewrites README/skill metadata files. This is a materially different primary purpose, so it is a clear mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared purpose is a code-to-image/PDF conversion utility with formatting features like line numbers and syntax highlighting. The supplied code does none of that. Its sole behavior is editing SKILL.md to convert certain HTML links into Markdown links for Chinese/English headings. This is a materially different primary purpose and an undeclared capability unrelated to the described conversion workflow. Therefore, this is a clear description-behavior mismatch.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 49)May include surrounding context.

md
1. 编辑 `gen_code_pdfs.py` 顶部的 `FILES` 列表,填入源文件名

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 100)May include surrounding context.

md
1. 编辑 `gen_code_pdfs.py` 顶部的 `FILES` 列表,填入源文件名

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 120)May include surrounding context.

md
1. 编辑 `gen_code_pdfs.py` 顶部的 `FILES` 列表,填入源文件名

Self-Modification

High
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · _fix_sk.py (reported line 6)May include surrounding context.

python
c = c.replace('<a href="#chinese">\u4e2d\u6587</a> \u00b7 <a href="#english">English</a>', '[\u4e2d\u6587](#chinese)')
c = c.replace('<a href="#chinese">\u4e2d\u6587</a>', '[\u4e2d\u6587](#chinese)')
c = c.replace('<a href="#english">English</a>', '[English](#english)')
with open('SKILL.md', 'w', encoding='utf-8') as f:
    f.write(c)
print('OK')

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill presents code and workflow that require shell execution, environment access, and reading/writing local files, but the manifest does not declare any tool scope such as allowed-tools or permissions. This creates an authorization transparency gap: an agent or reviewer cannot reliably determine the operational boundaries of the skill, increasing the risk of overbroad execution in environments where tool access is available.

Content

No source excerpt is available for this finding.

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · _fix_anchors.py (reported line 2)May include surrounding context.

python
import glob, os
for path in ['README.md', '../skills/code-to-images/SKILL.md']:
    with open(path, 'r', encoding='utf-8') as f:
        c = f.read()
    # Remove raw HTML anchor tags

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This Python code creates an output directory, writes multiple SVG files, and writes a final PDF file to disk as part of its execution. Although these writes are central to the script's purpose, the file itself provides no prior user disclosure or confirmation before modifying the filesystem; the status prints occur only after or during execution rather than warning beforehand.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The stated purpose is converting code files into images/PDFs with syntax highlighting, but the implementation achieves part of that by dynamically constructing JavaScript and launching a Node.js process. Spawning an external interpreter is a broader execution capability than the manifest suggests and is not inherently implied by a code-to-images skill description.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The code dynamically builds JavaScript and executes it via Node.js using subprocess.run, which is a safety-relevant operation because it launches an external interpreter from the host environment. There is no explicit pre-execution disclosure or confirmation informing the user that running this script depends on and executes Node with generated code.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
93% confidence
Finding

The script launches an external executable via subprocess.run, which creates a code-execution boundary outside Python's control. In this file that risk is materially relevant because the executable path is not hardcoded and the process is used automatically during normal operation, so a substituted binary or unexpected runtime environment could execute arbitrary code.

Content

Scanner excerpt · gen_code_pdfs.py (reported line 952)May include surrounding context.

python
'try{const d=fs.readFileSync(s,"utf8");const r=new Resvg(d,{background:"#ffffff"});'
          'const b=r.render();fs.writeFileSync(pn,b.asPng())}'
          'catch(e){console.log("  ERR:"+p+" "+e.message)}}')
    subprocess.run([NODE_EXE, '-e', js], check=True)
    print(f'{fname}: PNG OK')

    import img2pdf

Tainted flow: 'NODE_EXE' from os.environ.get (line 22, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
99% confidence
Finding

NODE_EXE is sourced from an environment variable and passed directly as the program to execute, allowing an attacker who controls the environment to replace the intended Node binary with any executable. That results in arbitrary code execution under the privileges of the script, which is more severe than a generic subprocess finding.

Content

Scanner excerpt · gen_code_pdfs.py (reported line 952)May include surrounding context.

python
'try{const d=fs.readFileSync(s,"utf8");const r=new Resvg(d,{background:"#ffffff"});'
          'const b=r.render();fs.writeFileSync(pn,b.asPng())}'
          'catch(e){console.log("  ERR:"+p+" "+e.message)}}')
    subprocess.run([NODE_EXE, '-e', js], check=True)
    print(f'{fname}: PNG OK')

    import img2pdf

Static analysis

No suspicious patterns detected.