Back to skill

Security audit

Cookbook Forge

Security checks for vulnerabilities and agentic risk

Overview

This book-generation skill is coherent overall, but it needs Review because some conversion and rendering paths can leak diagram content or let untrusted project content influence file writes, shell commands, generated code, or delegated agents.

Install only if you are comfortable reviewing or constraining the build scripts. Use it on trusted source material, avoid confidential diagrams unless remote rendering is disabled or replaced with local rendering, sandbox Docker/npm/LLM sub-agent runs, and validate chapter slugs and scaffold arguments before building generated outputs.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (6)

T01 · Skill Instruction Hijacking

Error
Location
scripts/lbuild-epub.mjs:122
Finding

Untrusted MDX Content Can Hijack Delegated Conversion Agents

Content
View full analysis
.svg) 图片语法,请把这些图片转换为 ,不要保留 mermaid 源码。`; const promptFile = path.join(OEBPS, "Text", `._prompt_${slug}.txt`); await fs.writeFile(promptFile, prompt, "utf8"); ``` The LaTeX converter uses the same unsafe construction: ```javascript const prompt = `${PROMPT_TEMPLATE} --- ## 待转换的 MDX 文件(${f}): \`\`\`mdx ${mdxForLlm} \`\`\` --- 请立即开始转换。只输出 LaTeX 代码,不要任何解释。输出文件第一行必须是 \\chapter{...} 或 \\chapter*{...}。 注意:mermaid/plantuml 代码块已被预处理为 \\begin{figure}...\\end{figure} 引用,请保留这些 LaTeX 代码原样,不要再尝试渲染或处理 mermaid 源码。`; const promptFile = path.join(texDir, `._prompt_${slug}.txt`); await fs.writeFile(promptFile, prompt, "utf8"); ``` ### Technical Analysis The converters interpolate the complete MDX source directly into a prompt that is subsequently consumed by a delegated LLM agent. The source is surrounded by a Markdown fence, but that fence is not a security boundary. An attacker-controlled MDX document can include a closing fence followed by new instructions. Neither prompt clearly establishes that the embedded MDX is untrusted data whose instructions must never be followed. The generated conversion plan explicitly directs a Task or sub-agent to read the combined prompt file. If that agent has filesystem or tool permissions, malicious instructions in the MDX may influence more than the intended format conversion. ### Attack Path 1. An attacker supplies source material or an MDX chapter containing a fence-breaking payload. 2. T ...[truncated 1072 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/lmdx2tex.mjs:136
Finding

Frontmatter Slug Allows Path Traversal and Writes Outside Build Directories

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
assets/nextra-template/scripts/scaffold-nextra.mjs:119
Finding

Raw Template Substitution Enables TypeScript and JSX Code Injection

Content
View full analysis
null))) return; let text = await fs.readFile(file, "utf8"); for (const [k, v] of Object.entries(replacements)) { text = text.split(`{{${k}}}`).join(v); } await fs.writeFile(file, text, "utf8"); } const reps = { BOOK_SLUG: slug, BOOK_TITLE: title, GITHUB_REPO_URL: github, YEAR: year, }; const targets = [ "package.json", "theme.config.tsx", "docker-compose.yml", ]; for (const t of targets) await replaceInFile(path.join(siteDir, t), reps); ``` The replacement values are inserted into executable TypeScript/JSX contexts: ```tsx const config: DocsThemeConfig = { logo: {{BOOK_TITLE}}, project: { link: '{{GITHUB_REPO_URL}}' }, docsRepositoryBase: '{{GITHUB_REPO_URL}}/tree/main', darkMode: true, i18n: [ { locale: 'zh', name: '简体中文' }, { locale: 'en', name: 'English' } ], search: { placeholder: '搜索文档…' }, editLink: { content: '在 GitHub 上编辑此页 →' }, feedback: { content: '问题或建议?' }, footer: { content: '© {{YEAR}} {{BOOK_TITLE}} · 基于 Nextra 构建' }, toc: { backToTop: true } } ``` ### Technical Analysis Values supplied through `--title`, `--github`, `--year`, and `--slug` are copied verbatim into JSON, YAML, TypeScript string literals, and raw JSX text. These contexts require different escaping rules, but the scaffolder applies none. A repository URL containing a single quote can terminate the TypeScript string and inject an expression or statement. A title containing JSX delimiters can alter the generated component syntax. Similar values can inva ...[truncated 1223 chars]
Remediation
View remediation
{BOOK_TITLE_CONSTANT} ``` 5. Validate arguments: - Slug: strict lowercase package-name pattern. - GitHub URL: parse with `new URL()` and allow only expected protocols and hosts. - Year: exactly four decimal digits within a reasonable range. - Title: reject control characters and enforce a length limit. 6. Use a proper YAML library for Docker Compose generation. 7. Parse and type-check generated files before suggesting build commands. 8. Build generated sites in a restricted container without sensitive environment variables. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
assets/nextra-template/scripts/render-plantuml.mjs:17
Finding

PlantUML Renderer Constructs a Shell Command from Untrusted Filenames

Content
View full analysis
Remediation
View remediation
", "-charset", "UTF-8", "-output", "/out", `-t${fmt}`, `/data/${file}` ], { shell: false, stdio: ["ignore", "ignore", "pipe"], windowsHide: true }); ``` 2. Validate filenames against a conservative pattern such as `^[A-Za-z0-9._-]+\.puml$`. 3. Reject path separators, control characters, and shell metacharacters. 4. Pin the container image to a reviewed immutable digest. 5. Mount input data read-only where supported. 6. Run rendering with a restricted Docker security profile and without unnecessary host access. ]]>

other

Warning
Location
scripts/lib/diagram-renderer.mjs:81
Finding

Confidential Diagram Source Is Automatically Transmitted to Kroki

Content
View full analysis
{ const req = https.request(url, { method: "GET", headers: { "User-Agent": "cookbook-forge" } }, (res) => { if (res.statusCode !== 200) { let body = ""; res.on("data", (c) => (body += c)); res.on("end", () => reject(new Error(`kroki HTTP ${res.statusCode}: ${body.slice(0, 300)}`))); return; } const chunks = []; res.on("data", (c) => chunks.push(c)); res.on("end", () => resolve(Buffer.concat(chunks))); }); req.on("error", reject); req.setTimeout(30000, () => req.destroy(new Error("kroki request timeout"))); req.end(); }); } ``` ```javascript await fs.writeFile(srcAbsPath, b.body, "utf8"); try { let buf; try { buf = await fs.readFile(svgAbsPath); if (onProgress) onProgress(`cache ${svgFileName}`); } catch { const encoded = krokiEncode(b.body); buf = await krokiFetch(type, "svg", encoded); await fs.writeFile(svgAbsPath, buf); } ``` A normal conversion invokes the renderer automatically: ```javascript const results = await renderAll(path.resolve("."), blocks, { onProgress: (m) => console.log(" ", m), }); ``` ### Technical Analysis The renderer compresses and Base64URL-encodes the entire Mermaid or PlantUML source and places it in an HTTPS GET URL sent to `kroki.io`. Encoding is reversible and does not provide confidentiality. Although the Skill documentation describes Kroki as a remote, opt-in option and warns against using it for co ...[truncated 1185 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
assets/nextra-template/package.json:13
Finding

Generated Builds Use Mutable and Unpinned Third-Party Dependencies

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (56)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Yes, this is a mismatch. The declared purpose is a document-authoring and publishing skill for generating technical books and structured documentation from source materials. The actual code chunk does not implement any content ingestion, transformation, chapter generation, publishing pipeline, or export logic. Instead, it performs web middleware routing behavior for a Nextra/Next.js site, specifically redirecting the homepage to a Chinese-language path. While this may be part of a website that hosts generated content, this code chunk’s primary behavior is unrelated infrastructure for request handling and locale redirection, which is materially different from the declared skill purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This code does not implement or evidence the declared primary purpose of generating technical books or documentation from source materials. Instead, it is a small configuration file for Nextra page metadata, specifically language labels for Chinese and English pages. That behavior is materially narrower and unrelated to the described end-user capability, so this is a clear description-to-code 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 60)May include surrounding context.

md
- `scripts/epub-zip.mjs` — EPUB 合规打包(Node 内置 zlib 手写 ZIP,零依赖;保证 mimetype STORED 且为第一;打包后遍历 central directory 二次校验)。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/lmdx2tex.mjs` — **LLM 驱动**的 MDX → ElegantBook LaTeX 转换器。通过子 agent 逐章节调用 LLM 智能转换,避免正则的脆弱性。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/lmdx2tex.mjs` — **LLM 驱动**的 MDX → ElegantBook LaTeX 转换器。通过子 agent 逐章节调用 LLM 智能转换,避免正则的脆弱性。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/lmdx2tex.mjs` — **LLM 驱动**的 MDX → ElegantBook LaTeX 转换器。通过子 agent 逐章节调用 LLM 智能转换,避免正则的脆弱性。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/lbuild-epub.mjs` — **LLM 驱动**的 MDX → EPUB3 转换器。通过子 agent 逐章节调用 LLM 智能转换为 XHTML,然后组装为 EPUB。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/lbuild-epub.mjs` — **LLM 驱动**的 MDX → EPUB3 转换器。通过子 agent 逐章节调用 LLM 智能转换为 XHTML,然后组装为 EPUB。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `assets/nextra-template/scripts/scaffold-nextra.mjs` — 把模板里的 `{{BOOK_SLUG}}`/`{{BOOK_TITLE}}`/`{{GITHUB_REPO_URL}}`/`{{YEAR}}` 占位符替换为真实值,自动拷贝 mdx→pages/zh、fig

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- 把 `package.json`/`theme.config.tsx`/`docker-compose.yml` 里的 `{{XXX}}` 占位符替换为真实值

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `SKILL.md`(本文件,英文 description,中文正文)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill explicitly instructs the agent to read local files and user-provided materials, but it does not declare any tool scope such as allowed-tools or permissions. In an agent framework, missing tool scoping weakens least-privilege controls and can enable broader file access than the user intended, especially because the workflow encourages exhaustive ingestion of local content.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill specifies the main language as "中文(默认)/ 英文 / 双语", making Chinese the default behavior unless the user overrides it. This is a locale/language constraint that is not presented as opt-in and may violate policy requiring user choice for language preferences.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding

Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding

Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code unconditionally redirects users visiting the site root to the Chinese locale path '/zh'. This is a natural-language locale policy concern because it imposes a language/locale choice without any visible opt-in, negotiation, or alternative selection path in this file.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding

The script runs a container image using the mutable tag plantuml/plantuml:latest, which makes builds non-reproducible and allows silent upstream image changes to alter behavior or introduce malicious code. Because this skill ingests user-supplied materials and executes Docker locally during document generation, a compromised or replaced image could directly affect the host build environment and generated artifacts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The instruction requires the converter to be specialized for Chinese ebook typography, which imposes a specific language/locale behavior. The file does not offer any user opt-in or alternative locale handling, so it appears to enforce a locale preference unconditionally.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The required output template fixes both xml:lang and lang to zh-CN, which enforces a Chinese locale on all generated documents. No opt-in, fallback, or scope limitation is stated in this file, making this a natural-language locale policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The instruction explicitly requires the converter to be skilled in Chinese technical writing, which constrains language/locale behavior. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is clearly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The prompt specifies that the chapter title must be a Chinese title, which hard-codes a language expectation into the skill behavior. There is no user choice or documented justification for this locale restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The template consistently requires Chinese content, including Chinese titles, Chinese comments, and Chinese prose conventions, but does not indicate that this is optional or limited to a China-specific or Chinese-language publication context. Under the policy rule, 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
94% confidence
Finding

The code sets BOOK_LANG to zh-CN when no --lang argument is provided, which forces a specific language/locale in generated EPUB metadata by default. The policy allows locale constraints when users are offered a choice or the constraint is clearly justified, but this file applies the locale automatically unless overridden manually.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The builder writes full MDX chapter contents into prompt files on disk for later sub-agent consumption, which can persist sensitive source material in plaintext beyond the user's expectation. In this skill context, inputs may come from private PDFs, repositories, or proprietary docs, so silent disk persistence materially increases confidentiality and data-handling risk.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest describes a skill for generating long-form technical books from user materials and emitting formats like EPUB, but this implementation relies on launching a separate runtime via child_process.execSync. Spawning subprocesses is a materially broader capability than ordinary document transformation logic and is not declared in the stated purpose.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.install_untrusted_source

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
assets/nextra-template/scripts/render-plantuml.mjs:22

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/lbuild-epub.mjs:456

Install source points to URL shortener or raw IP.

Warn
Code
suspicious.install_untrusted_source
Location
assets/nextra-template/docker-compose.yml:17