Back to skill

Security audit

Expertpack Export

Security checks for vulnerabilities and agentic risk

Overview

This skill is a plausible export tool, but it overstates its automatic secret protection and has an output path bug that can write outside the intended export folder.

Review this skill before installing. Use it only on workspaces you trust, choose a dedicated export directory, manually inspect the scan manifest and final export for secrets, and do not rely on its automatic redaction claims. Avoid using untrusted IDENTITY.md files or externally supplied scan manifests until slug validation and containment checks are fixed.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/distill.py:33
Finding

Secret Sanitization Is Not Applied During Distillation and Does Not Cover All Scanned Sources

Content
View full analysis
'), (re.compile(r'(sk-)[a-zA-Z0-9]{20,}'), r'\1'), (re.compile(r'(ghp_)[a-zA-Z0-9]{36,}'), r'\1'), (re.compile(r'(xoxb-)[a-zA-Z0-9\-]+'), r'\1'), ] def strip_secrets(text: str) -> str: """Replace known secret patterns with .""" for pattern, replacement in SECRET_PATTERNS: text = pattern.sub(replacement, text) return text ``` However, the function is never invoked. The script only creates scaffolding and delegates content processing to the calling agent: ```python # List source files for this pack from the scan source_files = [f for f in scan.get("files", []) if f.get("pack") == pack_slug] print(f"Source files to distill: {len(source_files)}") for sf in source_files: flag = " ⚠️ SECRETS" if sf.get("has_secret_patterns") else "" flag += " 🔍 NEEDS ANALYSIS" if sf.get("needs_content_analysis") else "" print(f" [{sf['confidence']:.1f}] {sf['path']} → {sf['section']}{flag}") print(f"\nNext: Agent reads source files and writes distilled content to {output_dir}/") ``` Secret checks are applied to a limited subset of files: ```python for fname, meta in AGENT_FILES.items(): fpath = ws / fname if fpath.exists(): entry = _make_file_entry(fpath, ws, agent_slug, meta["section"], meta["confidence"]) _check_secrets(fpath, entry, manifest) manifest["files"].append(entry) packs[agent_slug]["sources" ...[truncated 5483 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/compose.py:31
Finding

Workspace-Controlled Agent Slug Enables Arbitrary Path Traversal During Composite Generation

Content
View full analysis
Remediation
View remediation
str: if not SLUG_RE.fullmatch(value): raise ValueError(f"Invalid slug: {value!r}") return value ``` 2. Reject slugs containing `/`, `\`, `..`, drive prefixes, URI syntax, control characters, or absolute-path syntax. 3. Validate data again in `compose.py`; do not assume a supplied scan manifest was produced by the trusted scanner. 4. Resolve the destination and verify containment before creating directories or writing files: ```python base = (export / "composites").resolve() destination = (base / composite_slug).resolve() if destination.parent != base: raise ValueError("Composite destination escapes the export directory") ``` 5. Use a reusable safe-join function for all output paths, including pack output paths introduced in future revisions. 6. Refuse to overwrite an existing destination unless an explicit `--force` option is provided. 7. Write files atomically through temporary files created inside the verified destination, then rename them into place. 8. Add tests for relative traversal, absolute POSIX paths, Windows drive paths, backslashes, encoded separators, Unicode lookalikes, and malicious scan-manifest keys. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The code chunk is a narrow composer utility, not a full export pipeline. Its primary function is to consume a preexisting scan manifest (--scan) and write a composite ExpertPack manifest plus an overview markdown file under composites/<slug>. It wires references to packs based on metadata already present in the scan. There is no workspace scanning, no extraction or transformation of accumulated knowledge, no generation of constituent pack contents, and no general Obsidian-vault export beyond one markdown file and one YAML manifest. While this may be one sub-step of the described exporter, the declared description presents a broader capability set than this code actually performs, so this chunk is materially mismatched with the stated purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a full export pipeline: discovering constituent packs, distilling accumulated knowledge into structured EP content, and packaging a composite manifest with Obsidian-compatible files. The supplied code chunk is much narrower. It only reads a precomputed scan manifest, scaffolds directories and manifests for one pack type/slug, writes markdown stub files, and prints source file information. The docstring explicitly says content distillation is done by the AI agent that calls this script, not by the script itself. There is also no code for composite-manifest creation, multi-pack packaging, or workspace scanning. Finally, the markdown files are plain content stubs without YAML frontmatter, so the Obsidian-specific claim is not implemented here.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This is a clear description/behavior mismatch. The declared purpose centers on creating an ExpertPack export from agent state: auto-discovery of packs, distillation of raw state into EP files, and packaging into a composite manifest. The actual code does none of that. Instead, it validates the structure and contents of an existing export directory under --export-dir. Its primary function is post-export QA/compliance checking, including required-file checks, manifest parsing, agent-specific completeness checks, file size validation, and secret detection. Those behaviors are materially different from export/migration/backup generation, so the description does not accurately represent the code.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill instructs the agent to read from the live workspace and write an export directory, but it does not declare an explicit tool scope such as permissions or allowed-tools. That creates a real security control gap: an agent may be granted broader file access than users expect, increasing the chance of unintended data exposure during scanning and export of sensitive workspace content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code writes scaffold content directly to output files using write_text(), and similar writes also occur elsewhere in the script. Although the module docstring describes structural work, there is no user-facing warning, confirmation prompt, or explicit disclosure near the write operations that files will be created or replaced in the target directory.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code scans an entire workspace and later reads files such as IDENTITY.md, USER.md, memory files, logs, and project markdown to build an export manifest. Although it prints summary output, there is no user-facing disclosure that personal or sensitive workspace content may be inspected and included in the generated manifest.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The helper writes manifest data directly to the provided path, which modifies the filesystem. While the script's purpose is scaffolding, this write path lacks a direct confirmation prompt or explicit user-facing notice at the point of action describing that manifest files will be created or overwritten.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.