Back to skill

Security audit

Anchor Sheet

Security checks for vulnerabilities and agentic risk

Overview

The skill's main script fits anchor-sheet generation, but the package also ships broad workflow code and accepts unchecked file paths that could read or overwrite files outside the chosen workspace.

Review before installing. Use this only in a contained workspace, avoid untrusted UNITS.csv or command-line inputs, and do not pass absolute paths or ../ paths to --inputs or --outputs. The package should be tightened to the anchor-sheet script and workspace-relative declared files before broad use.

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/run.py:48
Finding

Unrestricted Input and Output Paths Permit Workspace Escape

Content
View full analysis
Remediation
View remediation
Path: workspace_root = workspace.resolve(strict=True) relative = Path(raw_path) if relative.is_absolute(): raise ValueError(f"Absolute paths are not allowed: {raw_path}") candidate = (workspace_root / relative).resolve(strict=False) if not candidate.is_relative_to(workspace_root): raise ValueError(f"Path escapes workspace: {raw_path}") return candidate ``` 3. Apply the helper independently to every input and output: ```python packs_path = resolve_workspace_path(workspace, inputs[0]) bib_path = resolve_workspace_path(workspace, inputs[1]) out_path = resolve_workspace_path(workspace, outputs[0]) ``` 4. Restrict this exported Skill to its declared files where configurable paths are unnecessary: ```python packs_path = workspace / "outline/evidence_drafts.jsonl" bib_path = workspace / "citations/ref.bib" out_path = workspace / "outline/anchor_sheet.jsonl" ``` 5. Defend against symlink escapes. For existing inputs, resolve the complete path with `strict=True` and verify that it remains under the canonical workspace root. For outputs, validate the nearest existing parent after resolving symlinks, then open or replace the destination using APIs that prevent symlink following where supported. 6. Validate expected file types and names. Inputs should be regular files with the expected `.jsonl` and `.bib` extensions, and the output should be limited to the expected `.jsonl` location. 7. Perform the same validation in `tooling/executor.py` before forwarding paths from `UNITS.csv`. Validation in both the caller and callee provides defense in depth. 8. Add regression tests covering: - Relative paths wit ...[truncated 220 chars]
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (31)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is narrowly about extracting numeric/evidence-backed anchor facts from existing evidence packs for subsection writing, with guardrails against prose and invention. The supplied code does not implement that behavior. Instead, it is a shared utility module for filesystem operations, serialization, text normalization, workspace status updates, decisions approval workflows, and query seeding. The most substantial functional behavior present—editing queries files and workflow/approval logs—is unrelated to anchor-fact extraction. While some generic helpers could support many skills, this chunk’s primary purpose is materially different from the declared one, so this 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 skill is a content-processing tool for extracting factual anchors from evidence packs under strict no-prose constraints. The supplied code does not process evidence packs, extract facts, or generate anchor sheets. Instead, it is an orchestration/runtime component for executing pipeline units, managing dependencies and approvals, running subprocesses, checking outputs, and updating workflow state. Although it does not use the network, its primary purpose and capabilities are materially different from the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The mismatch is strong. The declared skill is narrowly about selecting existing numeric/benchmark/limitation facts from evidence packs for writing support, explicitly with NO PROSE and no invention. The code instead powers an ideation system: it synthesizes literature notes into research signals, direction cards, rankings, shortlist memos, appendix notes, and discussion questions for PI/PhD research planning. Its primary behavior is analytic generation and prioritization of research ideas, not extraction of subsection anchor facts. The code also emits long-form prose markdown reports, which directly contradicts the declared 'NO PROSE' guardrail. While both touch literature/evidence, the actual function, inputs, and outputs are materially different.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is about extracting factual writing anchors from existing evidence snippets in outline/evidence_drafts.jsonl to strengthen section drafting. The supplied code does nothing related to evidence extraction, subsection analysis, selecting numeric facts, or enforcing 'NO PROSE'. Instead, it is infrastructure code for loading and validating pipeline definitions from YAML front matter in .pipeline.md files, including variant inheritance and stage parsing. While there is no network activity, the primary purpose and capabilities are materially different from the declared skill behavior, so this is a clear mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The supplied code chunk does not implement the described primary function of selecting anchor facts from evidence packs. Instead, it consists of reusable helper functions for parsing outlines, markdown headings, JSONL records, bibliography keys, text cleanup, and citation formatting. While some pieces could support a larger evidence-writing pipeline, this chunk alone does not extract subsection-level anchor facts or enforce selection only from evidence snippets. It also contains functions that generate natural-language citation phrases, which is at odds with the stated 'NO PROSE' constraint. Network behavior is consistent with the declaration ('none'), but the primary purpose and behavior do not match closely enough.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is narrow: extract anchor facts from evidence packs for writing support, with no prose generation and no invention. The actual code does not implement anchor-fact extraction at all. Instead, it is a centralized quality assurance/contract enforcement module covering many different skills and artifacts in the workspace. While the dispatcher includes an anchor-sheet branch, the supplied code chunk’s observable behavior is overwhelmingly about validation, gating, and report writing, not extracting numeric anchors from evidence snippets. Resource use is also broader than implied, since it reads many files across the workspace and writes reports. This is a clear description-behavior mismatch with a materially different primary purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The description is for a generation/extraction skill: take evidence packs and produce per-subsection anchor facts with strict guardrails (no prose, no invention, select only existing evidence). The supplied code does not do that. The relevant _check_anchor_sheet function merely validates that outline/anchor_sheet.jsonl exists, is non-empty, has JSON objects, and contains enough cite-backed anchors per subsection. More importantly, the code chunk is clearly part of a much larger quality_gate.py file whose primary behavior is comprehensive artifact validation across the entire writing pipeline, including subsection briefs, chapter briefs, evidence drafts, writer context packs, evidence bindings, visuals, tables, transitions, section markdown, merge reports, audit reports, and the final draft. That is a materially different primary purpose and a substantial undeclared capability surface. Network behavior is consistent with 'none', but the main description-behavior mismatch is that this is not an anchor-fact extractor; it is a broad quality gate / validator.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is about extracting anchor facts from evidence packs for writing support, with no prose and no network. The supplied code does not perform extraction from evidence packs at all. Instead, it audits generated draft documents and other pipeline artifacts, producing QualityIssue reports about citations, section structure, repetition, synthesis quality, and LaTeX build health. This is a materially different primary purpose and includes several undeclared capabilities unrelated to anchor-fact extraction.

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

md
- `python scripts/run.py --help`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `python scripts/run.py --help`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `python scripts/run.py --help`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `python scripts/run.py --help`

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This file implements large-scale research ideation, scoring, ranking, and memo/report generation rather than the declared anchor-sheet behavior of extracting terse, evidence-grounded anchor facts. That scope mismatch is dangerous because a caller invoking a supposedly constrained 'NO PROSE' evidence-extraction skill can instead trigger broad content synthesis and opinionated output generation, undermining workflow guarantees and enabling silent policy bypass or unintended downstream decisions.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The inline labels and emitted artifacts explicitly describe 'Research Idea Brainstorm Memo', prioritized directions, discussion questions, and appendix material, directly contradicting the skill's declared no-prose anchor-sheet purpose. This makes the mismatch concrete and operational: downstream users and agents may trust the metadata while the code actually produces expansive narrative content, which can contaminate evidence pipelines and defeat safeguards intended to prevent invention or over-synthesis.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
82% confidence
Finding

The skill declares no explicit tool scope, yet its documented usage invokes Python and writes output files, implying file read/write and shell-adjacent execution capability without a least-privilege boundary. In an agent setting, missing permission declarations can allow broader-than-expected workspace access and make review/enforcement of allowed actions much weaker.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The pipeline is marked as the default router target and uses broad routing hints such as 'survey', 'review', and generic multilingual terms. That can cause unintended invocation in loosely related contexts, which is dangerous because this pipeline is large, stateful, and may trigger downstream retrieval and writing stages with substantial side effects on workspace artifacts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The title and core goal explicitly define the pipeline as a Chinese thesis workflow, and later stages repeatedly require Chinese writing and polishing. The file does not offer a language choice or state that the locale restriction is an intentional region-specific constraint, so it appears to impose a language policy by default.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The routing hints include very broad natural-language triggers such as "snapshot," "one-page," and "one page," which are common phrases that may appear in unrelated user requests. This can cause unintended invocation of the pipeline, leading the agent to run the wrong workflow, generate incorrect artifacts, or bypass the more appropriate skill-selection path.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The routing hint list includes very generic English triggers such as "peer review" and especially "review report," which can match many unrelated user requests and cause this pipeline to be selected outside its intended manuscript-referee context. Misrouting is dangerous because it can direct the agent to operate on the wrong artifacts and generate authoritative-sounding review outputs for requests that did not intend this workflow.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
88% confidence
Finding

The function accepts an auto_approve set that can override HUMAN-gated checkpoints and mark units as approved without an actual human review. In a workflow engine, this weakens separation of duties and can allow sensitive or risky pipeline stages to proceed automatically if a caller can influence that parameter.

Content

Scanner excerpt · tooling/executor.py (reported line 105)May include surrounding context.

python
workspace: Path,
    repo_root: Path,
    strict: bool = False,
    auto_approve: set[str] | None = None,
) -> RunResult:
    units_path = workspace / "UNITS.csv"
    status_path = workspace / "STATUS.md"

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
92% confidence
Finding

This line normalizes caller-supplied auto_approve values into an approval set later used to bypass manual checkpoint review. If an attacker or untrusted automation can supply these values, they can pre-authorize guarded steps and cause the system to write approval state into DECISIONS.md without human validation.

Content

Scanner excerpt · tooling/executor.py (reported line 126)May include surrounding context.

python
table.save(units_path)
    update_status_log(status_path, f"{now_iso_seconds()} {unit_id} DOING {skill}")

    auto_approve_set = {str(x or "").strip().upper() for x in (auto_approve or set()) if str(x or "").strip()}

    if owner == "HUMAN":
        checkpoint = row.get("checkpoint", "").strip()

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
96% confidence
Finding

This branch performs the actual bypass: when a checkpoint matches auto_approve_set, it writes an approval record and marks the HUMAN-owned unit DONE. That is a direct authorization bypass of a manual control, and in agent/pipeline systems it can let unreviewed content, actions, or downstream executions proceed as though they had human signoff.

Content

Scanner excerpt · tooling/executor.py (reported line 137)May include surrounding context.

python
_refresh_status_checkpoint(status_path, table)
            return RunResult(unit_id=unit_id, status="DONE", message=f"HUMAN approved {checkpoint}")

        if checkpoint and checkpoint.upper() in auto_approve_set:
            set_decisions_approval(workspace / "DECISIONS.md", checkpoint, approved=True)
            row["status"] = "DONE"
            table.save(units_path)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · tooling/executor.py (reported line 199)May include surrounding context.

python
log_path = workspace / log_rel

    try:
        completed = subprocess.run(cmd, check=False, capture_output=True, text=True)
        if completed.stdout or completed.stderr or completed.returncode != 0:
            ensure_dir(log_path.parent)
            body = [

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This file defines helpers that write JSONL, JSON, and Markdown output using atomic file writes, which can modify workspace files. In this code file there is no confirmation prompt, logging/print statement, or inline comment/docstring warning users that these functions persist generated content to disk.

Content

No source excerpt is available for this finding.

Unbounded Output

Medium
Category
Output Handling
Confidence
60% confidence
Finding

Output size or generation rate is not bounded. Unbounded output enables denial-of-service through resource exhaustion, log flooding, or context-window stuffing.

Content

Scanner excerpt · tooling/quality_gate.py (reported line 4148)May include surrounding context.

python
return [
            QualityIssue(
                code="writer_selfloop_contains_ellipsis",
                message=f"`{out_rel}` contains unicode ellipsis (`…`); regenerate the report without truncation markers.",
            )
        ]

Static analysis

No suspicious patterns detected.