Back to skill

Security audit

IMC Publish

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but it needs Review because it can affect real social accounts and includes risky update and credential-routing behavior.

Install only if you trust the publisher and the InstallMyClaw workspace key permissions. Keep IMC_PUBLISH_BASE unset unless you fully trust the endpoint, avoid the built-in update command in favor of a managed ClawHub/OpenClaw updater, and verify every preview before confirming any post.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/imc_publish.py:27
Finding

Mutable, Unverified Remote Source Can Replace Installed Skill Code and Instructions

Content
View full analysis
None: installed = _skill_version(SKILL_DIR) if not installed: _die(f"{SKILL_DIR} does not look like an imc-publish install (no SKILL.md)") with tempfile.TemporaryDirectory() as tmp: archive_path = os.path.join(tmp, "source.tar.gz") try: with urllib.request.urlopen(SOURCE_TARBALL, timeout=120) as response: with open(archive_path, "wb") as out: shutil.copyfileobj(response, out) except (urllib.error.HTTPError, urllib.error.URLError) as exc: _die(f"cannot download the update: {exc}", 3) source = _extract_verified(archive_path, os.path.join(tmp, "unpacked")) latest = _skill_version(source) if not latest or not os.path.isfile(os.path.join(source, "scripts", "imc_publish.py")): _die("downloaded archive is not a valid imc-publish release") if _version_tuple(latest) <= _version_tuple(installed): print(f"Already up to date (v{installed}).") return for extra in ("install.sh", "uninstall.sh"): path = os.path.join(source, extra) if os.path.exists(path): os.remove(path) shutil.copytree(source, SKILL_DIR, dirs_exist_ok=True) print(f"Updated imc-publish {installed} -> {latest} in {SKILL_DIR}") print("Your API key was not touched.") ``` ### Technical Analysis The update command retrieves an archive from the mutable GitHub `main` branch and copies its contents over the installed Skill directory. It validates archive paths and checks for expected files, but it does not verify a cryptograp ...[truncated 1978 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/imc_publish.py:26
Finding

Publishing API Credential Can Be Transmitted to an Arbitrary or Plaintext Endpoint

Content
View full analysis
str: key = os.environ.get("IMC_PUBLISH_API_KEY", "").strip() if key: return key path = os.path.expanduser("~/.config/imc-publish/key") try: with open(path) as handle: return handle.read().strip() except OSError: return "" KEY = _load_key() ``` ```python def _request(method: str, path: str, *, body: bytes | None = None, headers: dict | None = None): if not KEY: _die("IMC_PUBLISH_API_KEY is not set. Ask your workspace owner for a publishing key.") request = urllib.request.Request( BASE + path, data=body, method=method, headers={ "Authorization": f"Bearer {KEY}", "Accept": "application/json", "User-Agent": f"imc-publish-skill/{__version__}", "X-IMC-Client-Version": __version__, **(headers or {}), }, ) global _latest_seen try: with urllib.request.urlopen(request, timeout=180) as response: _latest_seen = response.headers.get("X-IMC-Latest-Version") return json.loads(response.read().decode("utf-8")) except urllib.error.HTTPError as exc: _latest_seen = exc.headers.get("X-IMC-Latest-Version") if exc.headers else None raw = exc.read().decode("utf-8", "replace") try: detail = json.dumps(json.loads(raw), ensure_ascii=False, indent=2) except ValueError: detail = raw[:2000] _die(f"HTTP {exc.code} {path}\n{detail}", 2) except urllib.error.URLError as exc: _die(f"cannot reach publishing service: {exc.reason}", 3) ``` ### Technical Analysis Every ...[truncated 2228 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Warning
Location
SKILL.md:82
Finding

Remote Publishing Profile Is Designated as Agent Instructions Without Explicit Trust-Boundary Restrictions

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (15)

Tainted flow: 'request' from os.environ.get (line 74, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The request destination is derived from IMC_PUBLISH_BASE, which comes from an environment variable and is used directly in urllib.request.urlopen along with the Bearer API key. If an attacker can influence that environment variable, they can redirect authenticated requests to an arbitrary host and capture the publishing credential or all uploaded content/metadata.

Content

Scanner excerpt · scripts/imc_publish.py (reported line 88)May include surrounding context.

python
)
    global _latest_seen
    try:
        with urllib.request.urlopen(request, timeout=180) as response:
            _latest_seen = response.headers.get("X-IMC-Latest-Version")
            return json.loads(response.read().decode("utf-8"))
    except urllib.error.HTTPError as exc:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · install.sh (reported line 13)May include surrounding context.

sh
mkdir -p "$HOME/.claude/skills"
rm -rf "$DEST"
cp -r "$SRC" "$DEST"
rm -f "$DEST/install.sh" "$DEST/uninstall.sh"
echo "Installed to $DEST"
echo
echo "Next: set your workspace publishing key (ask your InstallMyClaw workspace owner):"

Self-Modification

High
Category
Rogue Agent
Confidence
95% confidence
Finding

The skill explicitly advertises a self-update capability, and the implementation later downloads code from a remote tarball and copies it over the installed skill directory. Any compromise of the upstream repository, distribution path, or update channel would let remote code be introduced into the local environment on the next update.

Content

Scanner excerpt · scripts/imc_publish.py (reported line 16)May include surrounding context.

python
post --caption C --platforms a,b [...]   One-call publish (trusted keys only)
  status <post_id>                         Check publish status (per-platform results)
  list [--limit N]                         Recent posts from this workspace
  update                                   Update this skill to the latest version
"""
from __future__ import annotations

Self-Modification

High
Category
Rogue Agent
Confidence
97% confidence
Finding

The self-update subsystem performs self-modification by downloading an archive from GitHub, extracting it, and copying its contents over the existing installation. Although it does some archive path checks, it does not verify publisher identity or artifact integrity, so trust is delegated entirely to the transport and upstream source.

Content

Scanner excerpt · scripts/imc_publish.py (reported line 116)May include surrounding context.

python
print(json.dumps(data, ensure_ascii=False, indent=2))


# --- self-update --------------------------------------------------------------

SKILL_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

Self-Modification

High
Category
Rogue Agent
Confidence
96% confidence
Finding

This command exposes the self-update path directly to users, making remote code replacement an accessible built-in feature rather than an administrative deployment step. In a skill context, that increases danger because a user or agent can be induced to run the updater and pull new code from an external source outside normal review controls.

Content

Scanner excerpt · scripts/imc_publish.py (reported line 320)May include surrounding context.

python
listing.add_argument("--limit", default=20)
    listing.set_defaults(fn=cmd_list)

    sub.add_parser("update", help="update this skill to the latest version").set_defaults(fn=cmd_update)

    parser.add_argument("--version", action="version", version=f"imc-publish {__version__}")

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · uninstall.sh (reported line 4)May include surrounding context.

sh
#!/usr/bin/env bash
# Removes ~/.claude/skills/imc-publish. Does not touch anything else.
set -euo pipefail
rm -rf "$HOME/.claude/skills/imc-publish"
echo "Removed ~/.claude/skills/imc-publish"

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README states the skill triggers automatically on broad publish-related requests, which can cause the agent to invoke a capability that sends content to external social platforms when the user only intended discussion, drafting, or analysis. In a publishing skill, overly broad activation increases the chance of unintended data disclosure or accidental posting because the action targets real connected accounts.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The trigger list is broad enough to match common conversational phrases like 'publish', 'post to', 'schedule a post', and generic platform names, which can cause the skill to activate in contexts where the user did not intend to invoke a social publishing tool. In this skill, accidental activation is more dangerous because the tool can upload media, create drafts, and potentially publish to real connected social accounts after a short confirmation flow.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
write it into files in a repo.
- `IMC_PUBLISH_BASE` — optional, defaults to `https://dashboard.installmyclaw.com`.

If the key is missing, stop and ask the user to set it. Never ask the user to
paste the key into the chat.

## Staying up to date

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The header states the script does 'nothing else' beyond copying the skill folder and printing a snippet, and explicitly says it does not touch 'any other file.' In reality, it removes any existing destination directory at L11 and deletes install.sh and uninstall.sh inside the destination at L13, which are additional filesystem modifications beyond a simple copy/print operation.

Content

No source excerpt is available for this finding.

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
85% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · install.sh (reported line 10)May include surrounding context.

sh
set -euo pipefail
SRC="$(cd "$(dirname "$0")" && pwd)"
DEST="$HOME/.claude/skills/imc-publish"
mkdir -p "$HOME/.claude/skills"
rm -rf "$DEST"
cp -r "$SRC" "$DEST"
rm -f "$DEST/install.sh" "$DEST/uninstall.sh"

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · install.sh (reported line 10)May include surrounding context.

sh
set -euo pipefail
SRC="$(cd "$(dirname "$0")" && pwd)"
DEST="$HOME/.claude/skills/imc-publish"
mkdir -p "$HOME/.claude/skills"
rm -rf "$DEST"
cp -r "$SRC" "$DEST"
rm -f "$DEST/install.sh" "$DEST/uninstall.sh"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script unconditionally runs rm -rf on the destination directory before copying, which can destroy an existing installation and any local modifications or data stored there without warning. While the path is fixed and user-scoped, destructive replacement without confirmation increases the risk of accidental data loss.

Content

No source excerpt is available for this finding.

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · README.md (reported line 26)May include surrounding context.

md
echo "  export IMC_PUBLISH_API_KEY=...   # add to your shell profile or secrets manager"
echo
echo "Codex users — add to AGENTS.md:"
echo "  To publish to social channels, follow ~/.claude/skills/imc-publish/SKILL.md"
echo
echo "Test: python3 $DEST/scripts/imc_publish.py accounts"

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · install.sh (reported line 20)May include surrounding context.

sh
echo "  export IMC_PUBLISH_API_KEY=...   # add to your shell profile or secrets manager"
echo
echo "Codex users — add to AGENTS.md:"
echo "  To publish to social channels, follow ~/.claude/skills/imc-publish/SKILL.md"
echo
echo "Test: python3 $DEST/scripts/imc_publish.py accounts"

Static analysis

No suspicious patterns detected.