Back to skill

Security audit

bluesky-skill

Security checks for vulnerabilities and agentic risk

Overview

This Bluesky tool is mostly transparent, but it gives an agent broad control over an account and private DMs while caching a reusable session token in a weakly protected local file.

Install only if you want an agent to have broad Bluesky account authority, including reading and sending DMs, posting, deleting posts, changing profile details, and changing social relationships. Prefer a dedicated app password, avoid enabling DM access unless needed, run the tool in an isolated environment with pinned dependencies, and protect or delete ~/.bsky_session.json when done or after revoking access.

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

Warning
Location
SKILL.md:17
Finding

Unpinned Third-Party Dependencies Create a Supply-Chain Risk

Content
View full analysis
Remediation
View remediation
python-dotenv== ``` 2. Generate and commit a lockfile containing resolved transitive dependencies and cryptographic hashes. 3. Install with hash verification, such as `pip install --require-hashes -r requirements.txt`. 4. Use an explicitly configured, trusted Python package index and disable unintended extra indexes. 5. Run dependency vulnerability and provenance checks in CI. 6. Review dependency updates before modifying pinned versions. 7. Prefer an isolated virtual environment with only the packages required by this Skill. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/bsky.py:35
Finding

Reusable Authentication Session Is Stored Without Enforced Access Controls

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (12)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% 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 · SKILL.md (reported line 343)May include surrounding context.

md
Auth errors: `{"error": "AUTH_ERROR", "type": "<TYPE>", "message": "..."}` with exit code 1.

1. **SESSION_CORRUPT** → `rm ~/.bsky_session.json` and retry
2. **MISSING_ENV** → Ensure `.env` has `BLUESKY_HANDLE` and `BLUESKY_APP_PASSWORD`
3. **INVALID_CREDENTIALS** → Handle: `user.bsky.social`, App password: `xxxx-xxxx-xxxx-xxxx` (19 chars)
4. **NETWORK** → Retry up to 3 times with 10s delay

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'env' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/bsky.py (reported line 45)May include surrounding context.

python
password = os.environ.get("BLUESKY_APP_PASSWORD")

    if not handle or not password:
        error_json("AUTH_ERROR", "Set BLUESKY_HANDLE and BLUESKY_APP_PASSWORD in .env", "MISSING_ENV")

    client = Client()

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 · SKILL.md (reported line 7)May include surrounding context.

md
Manage a Bluesky (bsky) account — posting, replies, likes, reposts, follows,
  blocks, mutes, search, timeline, threads, notifications, DMs, and profile
  updates via the AT Protocol.
allowed-tools: Bash Read Edit Write Glob Grep
metadata:
  openclaw:
    requires:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The documented commands include destructive or state-changing actions such as delete, block, mute, and marking notifications as read, but there is no warning that these actions are irreversible or can materially alter account state and social relationships. In an autonomous or semi-autonomous workflow, this increases the risk of accidental account changes, data loss, or user-impacting actions without adequate confirmation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill explicitly supports reading and sending direct messages but provides no privacy warning, consent requirement, or guidance to limit access to only what is necessary. In an agent setting, this can normalize access to private communications and lead to unnecessary exposure, processing, or disclosure of sensitive personal or business information.

Content

No source excerpt is available for this finding.

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 · SKILL.md (reported line 334)May include surrounding context.

md
- **Handles**: Always pass handles **without** the `@` prefix — use `user.bsky.social`, not `@user.bsky.social`.
- **URIs**: Every post has an AT Protocol URI (`at://did:plc:abc/app.bsky.feed.post/xyz`). Extract from the `uri` field in JSON. Used as arguments for like, reply, repost, thread, get, delete.
- **Rich text**: @mentions, #hashtags, URLs in post text are auto-converted to links. Write naturally.
- **Character limit**: 300 graphemes per post.
- **Unlike/unrepost**: Pass the **post URI**, not the like/repost record URI. Auto-resolved internally.
- **Reply threading**: `--reply-to <uri>` auto-resolves the thread root.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The code persists an exported session string to ~/.bsky_session.json without setting restrictive file permissions or warning the user. If another local user, backup system, or adjacent process can read that file, they may be able to hijack the authenticated Bluesky session and act as the user.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
91% confidence
Finding

The tool intentionally persists login session material to disk for reuse, which increases the attack surface beyond in-memory authentication. A stolen or improperly protected session file can enable account access without needing the original password, especially in shared or compromised environments.

Content

Scanner excerpt · scripts/bsky.py (reported line 50)May include surrounding context.

python
client = Client()

    def _save_session(event, session):
        """Save session to disk on change."""
        try:
            SESSION_FILE.write_text(json.dumps({"session_string": session.export()}))
        except Exception:

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
55% confidence
Finding

Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Content

Scanner excerpt · scripts/bsky.py (reported line 309)May include surrounding context.

python
img_path = Path(img_file)
            if not img_path.exists():
                error_json("FILE_NOT_FOUND", f"Image not found: {img_file}")
            upload = client.upload_blob(img_path.read_bytes())
            alt = alts[i] if i < len(alts) else ""
            images.append(models.AppBskyEmbedImages.Image(alt=alt, image=upload.blob))
        img_embed = models.AppBskyEmbedImages.Main(images=images)

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
55% confidence
Finding

Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Content

Scanner excerpt · scripts/bsky.py (reported line 709)May include surrounding context.

python
img_path = Path(img_file)
            if not img_path.exists():
                error_json("FILE_NOT_FOUND", f"Image not found: {img_file}")
            upload = client.upload_blob(img_path.read_bytes())
            alt = alts[i] if i < len(alts) else ""
            images.append(models.AppBskyEmbedImages.Image(alt=alt, image=upload.blob))
        img_embed = models.AppBskyEmbedImages.Main(images=images)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
80% confidence
Finding

The dm-send command sends user-provided message text to the Bluesky chat service, which is a network operation involving private communication data. While sending is the command's purpose, the file provides no user-facing warning or disclosure about the privacy-sensitive nature of DM transmission or handling.

Content

No source excerpt is available for this finding.