Back to skill

Security audit

Phy Social Suite

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent social-media review purpose, but it runs unverified local component scripts and can report “all clear” even when checks fail or are skipped.

Review this carefully before installing. It is not malicious on its face, but only run it with component skills you trust, remove or avoid the Desktop fallback path, and do not rely on the final “all clear” line as a hard publishing gate unless the missing-check and exception behavior is fixed.

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

T08 · Insecure Dependencies

Error
Location
scripts/social_suite.py:30
Finding
Unverified Dynamic Loading and Execution of External Skill Components<![CDATA[ ## Vulnerability Details **File Location**: `scripts/social_suite.py`, lines 30-45 **Vulnerability Type**: Untrusted local dependency loading **Risk Level**: High ### Vulnerable Code ```python def _import_from_path(module_name: str, file_path: str): """Import a Python module from an absolute path.""" spec = importlib.util.spec_from_file_location(module_name, file_path) if spec is None or spec.loader is None: return None module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module def _find_skill_script(skill_dir_name: str, script_name: str) -> str | None: """Find a skill script in standard locations.""" candidates = [ Path.home() / ".claude" / "skills" / skill_dir_name / "scripts" / script_name, Path.home() / "Desktop" / "openclaw-skills-publish" / skill_dir_name / "scripts" / script_name, ] for c in candidates: if c.exists(): return str(c) return None ``` The returned paths are subsequently loaded at lines 72-76, 103-106, and 135-138: ```python compound_path = _find_skill_script("phy-content-compound", "content_compound.py") if compound_path: try: compound = _import_from_path("content_compound", compound_path) ``` ```python humanizer_path = _find_skill_script("phy-content-humanizer-audit", "content_humanizer_audit.py") if humanizer_path: try: humanizer = _import_from_path("content_humanizer_audit", humanizer_path) ``` ```python rules_path = _find_skill_script("phy-platform-rules-engine", "platform_rules.py") if rules_path: try: rules = _import_from_path("platform_rules", rules_path) ``` ### Technical Analysis The application discovers Python components in predictable directories and executes them through `exec_module()` without validating their origin, version, integrity, ownership, or permissions. Importing a Python module executes all of its top-level code before any expected function i ...[truncated 1906 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Package reviewed component implementations as pinned dependencies rather than discovering arbitrary scripts in user-controlled directories. 2. Pin each component to an approved version and verify a cryptographic digest or publisher signature before importing it. 3. Maintain an explicit installation manifest containing the canonical path, expected version, and digest of every component. 4. Resolve each candidate with `Path.resolve()` and reject symlinks, unexpected path traversal, or files outside an approved installation root. 5. Check file ownership and permissions. Reject component files or parent directories writable by untrusted users. 6. Remove the development/Desktop fallback from production releases, or require an explicit command-line option and security warning before using it. 7. Obtain explicit user approval before first executing an external Skill component. 8. Where practical, execute third-party analysis components in a restricted subprocess with minimal filesystem access, a sanitized environment, resource limits, and network access disabled. 9. Do not pass draft or library data to a component until its integrity and trust status have been established. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/social_suite.py:168
Finding
Fail-Open Final Verdict Reports “All Clear” When Security Checks Fail or Are Skipped<![CDATA[ ## Vulnerability Details **File Location**: `scripts/social_suite.py`, lines 168-206 **Vulnerability Type**: Fail-open error handling and misleading approval state **Risk Level**: Medium ### Vulnerable Code ```python # Collect verdicts all_clear = True if humanizer_path: try: humanizer = _import_from_path("content_humanizer_audit", humanizer_path) h_result = humanizer.audit_content(text, platform) if h_result.verdict == "FAIL": w(" 🔴 AI signature too high — fix before posting") all_clear = False elif h_result.verdict == "WARN": w(" 🟡 AI signature borderline — consider fixes") all_clear = False except Exception: pass if rules_path: try: rules = _import_from_path("platform_rules", rules_path) r_results = rules.check_post(text, platform) r_fails = [r for r in r_results if r.status == "FAIL"] if r_fails: w(f" 🔴 {len(r_fails)} platform rule(s) violated — must fix") all_clear = False except Exception: pass if all_clear: w(" ✅ All clear — ready to post!") w("") return "\n".join(lines) ``` ### Technical Analysis The final verdict initializes `all_clear` to `True` and changes it only when a successfully completed component returns a recognized warning or failure. Missing components do not change this state because their respective blocks are skipped. Exceptions during module import or check execution are silently suppressed with `except Exception: pass`. As a result, the absence or failure of every substantive check can leave `all_clear` unchanged and produce the affirmative message `All clear — ready to post!`. This conflates “no violations were detected by completed checks” with “the checks did not run.” Although earlier stages may print a warning about a missing o ...[truncated 1433 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Represent every stage with an explicit state such as `PASS`, `WARN`, `FAIL`, `ERROR`, or `SKIPPED`. 2. Initialize the combined result to an incomplete or unknown state rather than assuming success. 3. Emit `All clear` only when every required stage has completed successfully and returned an acceptable result. 4. Return an `INCOMPLETE` or `ERROR` verdict whenever a required component is missing, cannot be imported, or raises an exception. 5. Replace silent broad exception handlers with explicit error reporting and logging: ```python except Exception as exc: stage_status["humanizer"] = "ERROR" w(f" 🔴 Humanizer audit failed: {exc}") ``` 6. Reuse the results calculated during the displayed stages instead of importing and executing each dependency a second time for the summary. This avoids inconsistent results and additional failure points. 7. Return a nonzero process exit code for incomplete or failed checks so downstream automation cannot interpret the run as successful. 8. Clearly distinguish optional stages, such as content-library retrieval, from checks required for the final approval. 9. Add tests covering missing dependencies, import exceptions, runtime exceptions, malformed component results, and runs where all components are absent. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (2)

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The script dynamically locates and imports Python modules from writable user-controlled locations such as the home directory and Desktop, then executes them via exec_module. If an attacker can place or modify files in those locations, running this skill will execute arbitrary code with the user's privileges, which is far more capability than needed for a content-audit orchestrator.

Description-Behavior Mismatch

Medium
Confidence
84% confidence
Finding
The manifest and module docstring describe a single command that outputs a combined PASS/FAIL verdict as a gate. In code, `run_pipeline` builds a human-readable report and may print 'All clear' or warning lines, but it returns only a string and `main()` always prints it without exposing a machine-enforced pass/fail result or exit status.

Static analysis

No suspicious patterns detected.