Back to skill

Security audit

PDF 翻译

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent local academic PDF translation skill, but one cleanup path can delete files outside the job folder if a job subdirectory is replaced with a symlink.

Review before installing. Use only trusted job directories, do not run candidate registration on a workspace another party can modify, and avoid symlinks inside job render/comparison directories until the cleanup routine is fixed. Prefer pinned, hash-verified dependency installation if available.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/register_candidate.py:69
Finding

Symlink-Following Cleanup Can Delete Files Outside the Job Directory

Content
View full analysis
None: if not directory.is_dir(): return for path in directory.iterdir(): if path.is_dir() and not path.is_symlink(): shutil.rmtree(path) else: path.unlink() ``` The helper is invoked on predictable directories inside a supplied job directory: ```python for directory in ( job_dir / "renders" / "source", job_dir / "renders" / "candidate", job_dir / "comparisons", ): _clear_directory_contents(directory) ``` ### Technical Analysis The cleanup function checks `directory.is_dir()` but does not reject a top-level cleanup directory that is itself a symbolic link. In Python, `Path.is_dir()` follows symbolic links. Likewise, `directory.iterdir()` enumerates the contents of the symlink target. Consequently, if `comparisons`, `renders/source`, or `renders/candidate` is replaced with a symbolic link to another writable directory, the function operates on the contents of that external directory: - External regular files and symbolic links are deleted with `unlink()`. - External real subdirectories are recursively deleted with `shutil.rmtree()`. - No resolved-path containment check verifies that the cleanup target remains beneath `job_dir`. - No ownership or trusted-directory validation is performed before destructive operations. The child-level `not path.is_symlink()` check prevents recursively following a child directory symlink, but it does not protect against the top-level cleanup directory being a symlink. ### Attack Path 1. An attacker supplies a pre-existing job directory or gains the ability to modify a job directory before candidate registration. 2. The attacker repla ...[truncated 1281 chars]
Remediation
View remediation
None: job_root = job_dir.resolve() if directory.is_symlink(): raise SkillError(f"Refusing to clean a symbolic link: {directory}") resolved = directory.resolve(strict=True) try: resolved.relative_to(job_root) except ValueError as exc: raise SkillError( f"Cleanup directory is outside the job directory: {resolved}" ) from exc if resolved == job_root or not resolved.is_dir(): raise SkillError(f"Invalid cleanup directory: {resolved}") for path in resolved.iterdir(): if path.is_symlink(): path.unlink() elif path.is_dir(): shutil.rmtree(path) else: path.unlink() ``` 2. Validate every parent component with `lstat()` or equivalent logic so that no parent directory in the cleanup path is a symlink. 3. Restrict cleanup to directories created and recorded by the application rather than accepting arbitrary existing directory structures. 4. Consider deleting and safely recreating the managed directory itself, after proving that its resolved parent is inside the job root. 5. Reduce time-of-check/time-of-use exposure by using directory-file-descriptor-based operations where supported. On Unix-like systems, relative operations through trusted directory descriptors can provide stronger resistance to symlink races. 6. Add regression tests covering: - A top-level `comparisons` symlink to an external directory. - Symlinks in `renders/source` and `renders/candidate`. - Symlinked parent components. - Replacement of a validated directory with a symlink during cleanup. - Verification that files outside the job root are never modified. ]]>

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Mutable Third-Party Dependencies Are Installed Without Integrity Verification

Content
View full analysis
=1.26.7,<2 Pillow>=12.3,<13 reportlab>=4.5.1,<6 ``` The documented installation procedure resolves these mutable dependencies at installation time: ```bash ./.venv/bin/python -m pip install -r requirements.txt ``` The alternative Skills CLI installation command also does not specify a reviewed CLI or Skill release version: ```bash npx skills add Ezra-Y/academic-pdf-translation ``` ### Technical Analysis The Python dependencies are constrained only by minimum and maximum versions. A future release satisfying those ranges can therefore be installed even though it was not part of the audited artifact. The requirements file does not provide hashes suitable for pip's `--require-hashes` mode, and no lock file establishes a reproducible dependency set. The `npx` command similarly leaves package resolution dependent on the current registry state and local npm configuration. The referenced Skill repository is not pinned to a commit hash or immutable release in the documented command. This does not demonstrate that any currently named dependency is malicious. The weakness is that installation trust is delegated to mutable package registries and future releases, so the code ultimately installed and executed may differ from the code reviewed during this audit. ### Attack Path A supply-chain compromise could proceed as follows: 1. A user follows the documented installation instructions. 2. `pip` resolves the newest versions satisfying the broad ranges, or `npx` resolves a mutable CLI package version. 3. A dependency publisher account, package registry, configured package i ...[truncated 1262 chars]
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (213)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The supplied code chunk is an internal data-migration utility for legacy job records, not a PDF translation pipeline. Its primary behavior is reading and updating job.json, inferring quality/review settings, versioning migrations, and saving snapshots. These actions are materially different from the declared end-user purpose of translating and rebuilding academic PDFs and related review/localization workflows. While such migration could be a supporting subsystem within a larger skill, this chunk itself exposes an undeclared capability—persistent job metadata migration—and does not implement the declared functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

声明描述的是一个面向学术 PDF 翻译与重建的完整处理技能,而该代码片段仅是一个底层交付证据管理模块,负责区分不同 run/attempt、写入当前运行指针,以及验证证据是否过期。虽然这类逻辑可能作为大型翻译流水线的配套实现细节存在,但就该代码块本身而言,其主要行为与声明的用户可见用途并不一致,且没有体现任何翻译、重建或本地化处理能力,因此应判定为描述与代码行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

代码文件 academic_pdf_translation/delivery/first_delivery.py 的职责非常明确:它是统一的首次交付入口,围绕已有候选 PDF 运行 build gate、mapping、structural audit、visual review/visual gate、repair plan、rebuild、证据落盘和恢复/绑定校验,最后给出 delivered/handover/blocked 三态结论。这与声明中“将学术 PDF 翻译并重建”为核心能力不一致。虽然模块路径属于 academic_pdf_translation,且会处理 candidate/source PDF、渲染计划、公式裁切等与该产品域相关的对象,但本代码块本身并不进行翻译生成或文本本地化,而是质量控制与交付决策层。根据评估标准,这属于主要目的与宣称能力的实质性不一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

描述呈现的是一个覆盖学术 PDF 翻译、重排、本地化、审校和文献管理的综合技能;而给出的代码片段是一个非常狭窄的渲染子模块。它不访问 PDF、不进行翻译、不生成对照图、不处理 Zotero,也没有批量文献画像能力。其核心行为是:根据绑定元数据而非排版启发式判定标题角色、设置不同角色的字号,并对标题译文做尾部重复检测。这些行为可被视为整体系统中的支持性实现细节,但单看该代码,与声明的主要用途相比范围明显更窄,且未体现多数宣称能力。因此描述与此代码片段的实际行为不相符。

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 40)May include surrounding context.

md
python3 scripts/workspace.py create \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/init_job.py \

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
python3 scripts/set_complex_content.py /path/to/job \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/set_complex_content.py /path/to/job \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/set_complex_content.py /path/to/job \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/build_render_plan.py /path/to/job

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/build_render_plan.py /path/to/job

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/build_render_plan.py /path/to/job

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/build_render_plan.py /path/to/job

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/build_render_plan.py /path/to/job

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/set_element_override.py /path/to/job \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/set_complex_payload.py /path/to/job \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/set_terminology.py /path/to/job \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/plan_translation_batches.py /path/to/job --model <实际模型标识>

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/plan_translation_batches.py /path/to/job --model <实际模型标识>

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/apply_translation_batch.py /path/to/job \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/apply_translation_batch.py /path/to/job \

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
python3 scripts/apply_translation_batch.py /path/to/job \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/run_translation_batches.py /path/to/job --verify-only

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/record_work_checkpoint.py /path/to/job \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/audit_translation_completeness.py /path/to/job