Back to skill

Security audit

Writing Better Skills

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed skill-authoring guide with local validation examples, and I found no hidden data access, network activity, or persistence.

Install this if you want an agent to help author or improve skills and you are comfortable with it creating project.skill.md and running local validation scripts/tests in the target repository. Review any project.skill.md before use, keep secrets out of it, and run the example/reference workflow only where generated files and its example dist directory are safe to modify.

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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is about a meta-skill for designing or improving AI agent skills, especially around triggers, context, tests, and completion rules. The supplied code instead implements a release notes generator script. Its primary purpose, inputs, and outputs are materially different from the description. While file reading and writing are normal implementation details for this script, they are not aligned with the declared skill purpose. This is therefore a clear description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description suggests a meta-skill for designing or improving AI agent skills, including documentation, trigger design, tests, and self-healing guidance. The actual code does not provide any of that functionality. Instead, it performs a narrow filesystem action: ensuring an output directory exists by creating it if necessary. That is a materially different primary purpose and an undeclared capability involving filesystem modification. This is not merely a supporting implementation detail of the declared behavior; it is a standalone operational script unrelated to the description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description says this skill is for authoring or improving AI-agent skills and their guidance structure. The supplied code does something materially different: it is an automated test for a release notes generator. It writes input data, runs a script, reads generated output, and checks for expected markdown sections. Those behaviors are not aligned with the declared purpose, and the code's primary purpose is unrelated to skill creation/improvement guidance.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The declared description is about a meta-skill used to design or improve AI agent skills. The supplied code does not implement that purpose. Instead, it is an automated integration test for a release-notes project workflow: it removes an output directory, runs a generator expecting a specific failure, runs a healing script, reruns generation, and checks for the generated file. While the description mentions scripts, tests, self-healing rules, and completion gates, those are framed as components of a skill-authoring aid; this code is concretely operating on a release-notes project and executing local scripts. That makes the primary purpose materially different from the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description is about a meta-skill used to create or improve AI-agent skills. The supplied code does not implement guidance, trigger wording, self-healing rules, or completion-gate logic for skill authoring. Instead, it is a narrow test wrapper that invokes an existing validation script on the project root and reports its result. That is a materially different primary purpose, so this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

The declared description presents a general-purpose skill-authoring or skill-improvement aid for AI agents. The supplied code, however, is a narrow automation script for running validation and tests on a specific reference skill (reference-skills/release-notes-generator). Its primary function is subprocess-based test orchestration, not providing trigger wording, project-local context, self-healing rules, or completion-gate instructions to another agent. While testing is mentioned in the description, this code does not implement that broader described purpose; it performs a materially different, concrete CI-style task.

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

md
- what belongs in `SKILL.md`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- what belongs in `SKILL.md`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- what belongs in `SKILL.md`

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
- what belongs in `SKILL.md`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- what belongs in `SKILL.md`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- what belongs in `SKILL.md`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- what belongs in `SKILL.md`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- what belongs in `SKILL.md`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- what belongs in `SKILL.md`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- what belongs in `SKILL.md`

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill text explicitly instructs agents to read project files, create project.skill.md, and use shipped scripts such as scripts/quick_validate.py, which implies file read/write and shell-like execution capabilities. Because the frontmatter declares no permissions or allowed-tools, an agent may invoke broader tools than intended without an explicit trust boundary, increasing the chance of unnecessary filesystem changes or command execution in downstream use.

Content

No source excerpt is available for this finding.

Tainted flow: 'version' from pathlib.Path.read_text (line 34, file read) → pathlib.Path.write_text (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · reference-skills/release-notes-generator/scripts/generate_release_notes.py (reported line 43)May include surrounding context.

python
print(f"Output directory does not exist: {output_path.parent}")
        return 2

    output_path.write_text(render_release_notes(version, highlights, changes, notes), encoding="utf-8")
    print(f"Wrote release notes to {output_path}")
    return 0

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 · reference-skills/release-notes-generator/tests/test_generate_release_notes.py (reported line 29)May include surrounding context.

python
"notes": ["No breaking changes"],
        }), encoding="utf-8")

        result = subprocess.run(
            [sys.executable, str(script), str(input_path), str(output_path)],
            capture_output=True,
            text=True,

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 · tests/test_project_workflow.py (reported line 11)May include surrounding context.

python
def run(cmd: list[str], cwd: Path) -> tuple[int, str, str]:
    result = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True, check=False)
    return result.returncode, result.stdout, result.stderr

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 · tests/test_reference_skill.py (reported line 10)May include surrounding context.

python
def run(cmd: list[str]) -> int:
    result = subprocess.run(cmd, capture_output=True, text=True, check=False)
    print(result.stdout, end="")
    if result.returncode != 0:
        print(result.stderr, end="")

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 · tests/test_quick_validate.py (reported line 13)May include surrounding context.

python
root = Path(__file__).resolve().parents[1]
    validator = root / "scripts" / "quick_validate.py"

    result = subprocess.run(
        [sys.executable, str(validator), str(root)],
        capture_output=True,
        text=True,

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 · tests/test_root_skill_package.py (reported line 13)May include surrounding context.

python
root = Path(__file__).resolve().parents[1]
    validator = root / "scripts" / "quick_validate.py"

    result = subprocess.run(
        [sys.executable, str(validator), str(root)],
        capture_output=True,
        text=True,