Back to skill

Security audit

Agentic Proposal Skill

Security checks for vulnerabilities and agentic risk

Overview

This is a local proposal and PDF drafting skill with disclosed file-output and dependency-install behavior, and I found no hidden network, credential, persistence, or destructive behavior.

Install this as a local document-generation skill, not as an autonomous business-action tool. Consider using a locked environment or pinned dependencies before running the PDF/PNG renderer or quality validator, and review generated proposal/SOW text before sending because it may include placeholders and commercial terms.

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

T08 · Insecure Dependencies

Warning
Location
requirements.txt:2
Finding
Unpinned Third-Party Dependencies Permit Unreviewed Package Execution<![CDATA[ ## Vulnerability Details **File Locations**: - `SKILL.md:13-17` - `SKILL.md:102` - `requirements.txt:2-5` - `scripts/validate_quality.py:62-66` **Vulnerability Type**: Dependency versions are constrained only by minimum versions, while the quality validator may dynamically resolve and execute Ruff through `uvx`. **Risk Level**: Medium ### Vulnerable Code `SKILL.md:13-17`: ```yaml install: - kind: uv package: reportlab>=4.0 - kind: uv package: pyyaml>=6.0 ``` `SKILL.md:102`: ```bash pip install -r requirements.txt ``` `requirements.txt:2-5`: ```text reportlab>=4.0 # Optional: only needed to also emit a PNG preview montage (scripts/render_pdf.py --png) pypdfium2>=4.30 pillow>=10.0 ``` `scripts/validate_quality.py:62-66`: ```python if shutil.which("uvx"): run(["uvx", "ruff", "check", "."]) return run([sys.executable, "-m", "ruff", "check", "."]) ``` ### Technical Analysis The project specifies lower version bounds without upper bounds, exact version pins, a lockfile, or package hashes. Consequently, future releases satisfying these constraints may be installed without having been reviewed with the audited source code. The validation script also invokes `uvx ruff` when `ruff` is not installed locally. Unless separately constrained by the environment, this can resolve and execute a package version that is not declared or locked by the project. No evidence was found that the currently named dependencies are malicious, typo-squatted, or retrieved from an explicitly unsafe source. The risk arises from permitting mutable, unreviewed third-party releases to enter executable installation and runtime paths. ### Attack Path 1. An attacker compromises the publishing account, build pipeline, or distribution infrastructure of an allowed dependency, or causes a malicious future release to be published under the expected package name. 2. The malicious release retains a version satisfying a constraint such as `reportlab>=4.0`, `pypdfium2 ...[truncated 1264 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace lower-bound-only constraints with exact, reviewed versions, for example: ```text reportlab==<reviewed-version> pypdfium2==<reviewed-version> pillow==<reviewed-version> ``` 2. Generate and commit a dependency lockfile that includes transitive dependencies and cryptographic hashes. 3. Install dependencies using hash verification, such as: ```bash python3 -m pip install --require-hashes -r requirements.lock ``` 4. Pin Ruff as a development dependency and invoke the locked environment instead of allowing `uvx ruff` to resolve an unspecified release dynamically. 5. Keep the dependency declarations in `SKILL.md`, `requirements.txt`, and the lockfile synchronized so all installation paths use the same reviewed versions. 6. Use automated dependency scanning and controlled update pull requests. Review release notes and regenerate hashes before accepting upgrades. 7. In CI and other sensitive environments, restrict outbound package access to an approved registry mirror containing vetted artifacts. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared purpose says this skill drafts proposal and SOW-style client documents. However, the provided code chunk does not generate those artifacts or perform document-authoring logic as its primary function. Instead, it acts as a CI/quality gate script for a skill repository: checking syntax, lint, config parsing, Mermaid renderability, smoke-running a renderer, and validating ClawHub metadata and publishable bundle contents. While one smoke test references a proposal renderer, that is only incidental validation of another script, not the main behavior here. This is therefore a clear description-behavior mismatch.

Ae1

High
Category
analysis-evasion
Content
- Already drafted the Markdown yourself? Render it directly: `python3 scripts/render_pdf.py --markdown artifact.md --out artifact.pdf --logo assets/logo.png --t
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Credential Access

High
Category
Privilege Escalation
Content
DEFAULT_CLAWHUBIGNORE_PATTERNS = [
    "*.png", "*.jpg", "*.jpeg", "*.gif", "*.ico", "*.pdf", "*.docx", "*.ipynb", "*.ttf", "*.otf", "*.woff", "*.woff2",
    "preview/", "output/", "__pycache__/", "*.py[cod]", "*$py.class", ".mypy_cache/", ".pytest_cache/", ".ruff_cache/",
    ".venv/", "venv/", "env/", "ENV/", ".env", ".env.*", "secrets.json", "*_secret.ini", "*_local.ini", "*.tmp",
    ".DS_Store", "Thumbs.db", "desktop.ini",
]
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
DEFAULT_CLAWHUBIGNORE_PATTERNS = [
    "*.png", "*.jpg", "*.jpeg", "*.gif", "*.ico", "*.pdf", "*.docx", "*.ipynb", "*.ttf", "*.otf", "*.woff", "*.woff2",
    "preview/", "output/", "__pycache__/", "*.py[cod]", "*$py.class", ".mypy_cache/", ".pytest_cache/", ".ruff_cache/",
    ".venv/", "venv/", "env/", "ENV/", ".env", ".env.*", "secrets.json", "*_secret.ini", "*_local.ini", "*.tmp",
    ".DS_Store", "Thumbs.db", "desktop.ini",
]
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
DEFAULT_CLAWHUBIGNORE_PATTERNS = [
    "*.png", "*.jpg", "*.jpeg", "*.gif", "*.ico", "*.pdf", "*.docx", "*.ipynb", "*.ttf", "*.otf", "*.woff", "*.woff2",
    "preview/", "output/", "__pycache__/", "*.py[cod]", "*$py.class", ".mypy_cache/", ".pytest_cache/", ".ruff_cache/",
    ".venv/", "venv/", "env/", "ENV/", ".env", ".env.*", "secrets.json", "*_secret.ini", "*_local.ini", "*.tmp",
    ".DS_Store", "Thumbs.db", "desktop.ini",
]
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill invokes local shell commands and can read/write files via its documented renderer workflow, but it declares no explicit tool restrictions or allowed-tools boundary. In an agent environment, that omission broadens what the model may attempt and weakens enforcement, increasing the chance of unintended command execution or filesystem access beyond proposal rendering.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The manifest frames the skill as a document-drafting aid, but this file runs Ruff, Pyright, and Mermaid CLI commands through subprocesses. Those are software-development QA capabilities and are not directly justified by the stated purpose of producing proposal/SOW documents.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def run(cmd: list[str], cwd: Path = ROOT) -> None:
    print("$", " ".join(cmd))
    subprocess.run(cmd, cwd=cwd, check=True)


def run_ruff() -> None:
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The skill is described as generating buyer-facing proposal and SOW-style documents, but this script invokes a separate renderer script in smoke-test mode via subprocess. Executing local tooling to validate package quality is a build/release capability, not an obvious requirement of the skill's end-user proposal-authoring purpose.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# Branded PDF artifact rendering (scripts/render_pdf.py)
reportlab>=4.0
# Optional: only needed to also emit a PNG preview montage (scripts/render_pdf.py --png)
pypdfium2>=4.30
pillow>=10.0
Confidence
93% confidence
Finding
The dependency is specified with a lower bound only, so builds may resolve to different versions over time and can unintentionally pull in vulnerable or incompatible releases. In a proposal-generation skill that renders branded PDFs, this increases supply-chain and reproducibility risk, especially because reportlab has a history of security advisories affecting document parsing/rendering features.

Unverifiable Dependency: reportlab has 8 known advisory(ies) (CVE-2023-33733 (Reportlab vulnerable to remote code execution); CVE-2020-28463 (Server-side Request Forgery (SSRF) via img tags in reportlab); CVE-2019-19450 (ReportLab vulnerable to remote code execution via paraparser) +5 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
91% confidence
Finding
Reportlab has multiple known advisories, including past RCE and SSRF issues, and the manifest does not pin a version, so there is no assurance deployments avoid affected releases. In a skill that generates buyer-facing PDFs, this is more concerning because document-generation libraries may process rich content and historically vulnerable parser features can be reachable if any input is incorporated into rendered documents.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# Branded PDF artifact rendering (scripts/render_pdf.py)
reportlab>=4.0
# Optional: only needed to also emit a PNG preview montage (scripts/render_pdf.py --png)
pypdfium2>=4.30
pillow>=10.0
Confidence
89% confidence
Finding
Using an unpinned pypdfium2 version makes installations non-reproducible and can introduce newly published vulnerable releases or breaking changes without review. Because this package is used for PDF-to-image preview generation, any dependency compromise or vulnerable parser behavior could affect systems processing untrusted PDF content.

Unpinned Dependencies

Low
Category
Supply Chain
Content
reportlab>=4.0
# Optional: only needed to also emit a PNG preview montage (scripts/render_pdf.py --png)
pypdfium2>=4.30
pillow>=10.0
Confidence
94% confidence
Finding
The pillow requirement is also unpinned, so future installs may consume a vulnerable release or silently change behavior. This matters in a document-rendering workflow because image libraries are frequent targets for malformed-file exploitation and denial-of-service issues.

Unverifiable Dependency: pillow has 16 known advisory(ies) (CVE-2016-2533 (Pillow buffer overflow in ImagingPcdDecode); CVE-2023-50447 (Arbitrary Code Execution in Pillow); CVE-2021-27922 (Pillow Uncontrolled Resource Consumption) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
92% confidence
Finding
Pillow has many historical advisories, including memory-safety, resource-consumption, and code-execution issues, and the unpinned dependency prevents verification that a safe release will be installed. Given the skill's optional PNG preview generation, image decoding/manipulation is part of the runtime path, so malformed image or document-derived content could increase exposure to vulnerable code paths.

Static analysis

No suspicious patterns detected.