Back to skill

Security audit

Phy Content Calendar

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but its optional library feature can silently execute Python code from predictable user-writable locations without verification.

Review this carefully before installing if you plan to use --library. The basic calendar generator is low risk, but the content-library integration should only be used when you trust the local phy-content-compound file at the hardcoded path and the directory has not been modified by another package or user.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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)

T07 · Tool Hijacking and Spoofing

Warning
Location
scripts/content_calendar.py:129
Finding

Untrusted Dynamic Module Execution from Predictable User-Writable Paths

Content
View full analysis

Vulnerability Details

File Location: scripts/content_calendar.py:129-151
Vulnerability Type: Arbitrary local Python module loading without origin or integrity validation
Risk Level: Medium

Vulnerable Code

python
if library_path:
    compound_path = None
    for candidate in [
        Path.home() / ".claude" / "skills" / "phy-content-compound" / "scripts" / "content_compound.py",
        Path.home() / "Desktop" / "openclaw-skills-publish" / "phy-content-compound" / "scripts" / "content_compound.py",
    ]:
        if candidate.exists():
            compound_path = str(candidate)
            break

    if compound_path:
        try:
            spec = importlib.util.spec_from_file_location("content_compound", compound_path)
            if spec and spec.loader:
                mod = importlib.util.module_from_spec(spec)
                spec.loader.exec_module(mod)
                library = mod.scan_directory(library_path)
                for pillar in pillars:
                    results = mod.retrieve_atoms(library, pillar, top_n=3)
                    if results:
                        atoms_by_topic[pillar] = [
                            f"[{a.atom_type}] {a.text[:80]}... ({a.source_file})"
                            for a, _ in results
                        ]
        except Exception:
            pass

Technical Analysis

When the optional --library argument is provided, the script searches two predictable locations under the user's home directory for content_compound.py. It then loads the first existing file with importlib.util.spec_from_file_location() and executes its top-level code through spec.loader.exec_module(mod).

The loader does not verify the module's expected cryptographic hash, package identity, canonical path, owner, or filesystem permissions. Consequently, the existence check is treated as sufficient evidence that the discovered Pyt ...[truncated 1950 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove source-file discovery and direct execution from predictable home-directory paths.
  2. Move the required functionality into reviewed code shipped with this project, or consume a properly installed and version-pinned package through the normal Python import system.
  3. If optional integration must remain, require the user to provide an explicit module path rather than silently selecting the first existing candidate.
  4. Establish a trust policy before loading any explicit module:
    • Resolve and validate the canonical path.
    • Restrict loading to an approved directory.
    • Verify expected file ownership and reject group-writable or world-writable files and parent directories.
    • Verify the module against a pinned cryptographic digest or signed manifest.
  5. Prefer a data-only interoperability format such as JSON over importing executable Python. Run a separately trusted helper with a constrained interface if code-based integration is unavoidable.
  6. Replace the silent exception handler with clear error reporting and audit logging. Avoid suppressing module-loading failures because they may indicate tampering.
  7. Apply least-privilege execution and sandboxing so the calendar process cannot access unrelated user files, credentials, or network resources.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
Findings (1)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script dynamically imports and executes a Python file from hardcoded user-writable locations under the home directory, then invokes functions from that module. If an attacker can place or replace content_compound.py in one of those locations, arbitrary code will run when --library is used, with no integrity check, trust boundary validation, or user warning. In skill context, this is more dangerous because the tool advertises 'zero external dependencies' but silently executes another local skill module, which may cause users to trust it more than they should.

Content

No source excerpt is available for this finding.