Back to skill

Security audit

Bluesky

Security checks for vulnerabilities and agentic risk

Overview

This Bluesky skill is purpose-aligned but needs review because it can authenticate and perform public account actions without clearly documented confirmation or tight endpoint/dependency controls.

Install only for a Bluesky account where an agent is allowed to post, reply, upload media, bookmark, and potentially change engagement state. Use a revocable app password, verify BSKY_PDS is a trusted HTTPS endpoint, add your own confirmation step before public writes, and consider pinning the atproto dependency before production use.

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:13
Finding

Unpinned AT Protocol Dependency Creates a Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:13-16
Vulnerability Type: Unpinned third-party dependency
Risk Level: Medium

Vulnerable Code:

json
{
  "id": "python-atproto",
  "kind": "pip",
  "package": "atproto",
  "label": "Install AT Protocol Python SDK"
}

The setup instructions at SKILL.md:35 also use an unpinned installation command:

bash
pip install atproto

Technical Analysis

The Skill installs atproto without specifying a reviewed version, lock file, or package integrity hash. Consequently, installation resolves whichever compatible package and transitive dependencies are available from the configured Python package index at installation time.

This does not establish that the current atproto package is malicious. However, it makes the audited artifact non-reproducible and allows its effective executable dependency set to change after review. A compromised future release, compromised package-index account, or malicious package served through an unsafe package-index configuration could execute installation or import-time code with the privileges of the Agent process.

Because lib/bluesky_agent.py imports this dependency directly, malicious code in the package could run when the module is imported:

python
from atproto import Client, client_utils, models

Attack Path

  1. An attacker compromises the upstream package, a transitive dependency, a package publisher account, or the package index used by the deployment.
  2. The attacker publishes or serves a malicious version that still satisfies the unrestricted atproto requirement.
  3. A user installs the Skill dependency with the declared installation configuration or pip install atproto.
  4. The malicious package executes during installation or when bluesky_agent.py imports it.
  5. The package acts with the permissions of the installation or Agent process and may access data available to t ...[truncated 530 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin atproto to a specifically reviewed version, such as an exact == version rather than an unrestricted package name.
  2. Generate and commit a lock file that fixes all transitive dependency versions.
  3. Require package hashes during installation, for example through a hash-locked requirements file and pip install --require-hashes.
  4. Install only from an explicitly configured, trusted package index.
  5. Use automated dependency monitoring, but review updates before modifying the pinned version.
  6. Run dependency installation and the Skill with least privilege in an isolated virtual environment or container.
  7. Record the reviewed package versions and hashes in the release documentation so installations are reproducible.

T09 · Insecure Skill Coding Practices

Warning
Location
lib/bluesky_agent.py:4
Finding

Authentication Credentials Can Be Sent to an Unvalidated PDS Endpoint

Content
View full analysis

Vulnerability Details

File Location: lib/bluesky_agent.py:4-9
Vulnerability Type: Insufficient validation of a credential-receiving network destination
Risk Level: Medium

Vulnerable Code:

python
class BlueskyAgent:
    def __init__(self, pds_url="https://bsky.social"):
        self.client = Client(base_url=pds_url)

    def login(self, identifier, app_password):
        """Authenticates using an App Password."""
        self.client.login(identifier, app_password)
        return self.client.get_profile(actor=identifier)

Technical Analysis

The constructor accepts an unrestricted pds_url and passes it directly to the third-party AT Protocol client. The login method subsequently supplies the account identifier and app password to that client. The Skill does not independently verify that the endpoint uses HTTPS, belongs to an intended PDS, or has been explicitly approved before authentication.

The documented default, https://bsky.social, is an expected HTTPS destination. Custom PDS support can also be legitimate. The vulnerability arises because configuration tampering or user error can change the destination without a scheme restriction, host allowlist, or confirmation boundary. If the underlying SDK accepts a cleartext or attacker-controlled URL, credentials could be disclosed to that endpoint.

No hardcoded credential or direct credential logging was found. The risk is specifically the absence of destination validation before forwarding authentication material.

Attack Path

  1. An attacker gains influence over the value passed as pds_url, such as by modifying deployment configuration or persuading an operator to use a malicious custom PDS.
  2. The Agent constructs BlueskyAgent with the attacker-controlled endpoint.
  3. The user or orchestration layer calls login(identifier, app_password).
  4. The AT Protocol client sends an authentication request to the configured destinat ...[truncated 858 chars]
Remediation
View remediation

Remediation Suggestions

  1. Parse pds_url before constructing the client and reject every scheme other than https.
  2. Reject URLs containing embedded user information, malformed hostnames, unexpected fragments, or ambiguous encodings.
  3. Use an allowlist containing bsky.social when custom PDS operation is not required.
  4. If custom PDS instances are required, maintain an explicit trusted-host configuration and require operator confirmation before credentials are sent to a new host.
  5. Consider blocking loopback, link-local, and private-network destinations unless local PDS access is an intentional and documented deployment mode.
  6. Preserve TLS certificate verification and do not expose options that silently disable it.
  7. Display or log the selected PDS hostname before authentication without ever logging the app password.
  8. Document immediate app-password revocation and rotation procedures for suspected endpoint misconfiguration.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The skill documentation and declared capabilities do not fully align with the described behavior, especially around authentication, profile retrieval, and handle resolution. In an authenticated social-media skill, such mismatches can mislead users and reviewers about what account actions occur and what data is accessed, reducing informed consent and making unsafe use more likely.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This skill can perform authenticated write actions on a user's Bluesky account, but the description does not clearly warn users that invoking it may post, reply, like, repost, bookmark, or otherwise modify account state. That omission increases the risk of unintended account actions and weakens user awareness in a sensitive authenticated context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill transmits user-provided text, metadata, and potentially media uploads to external Bluesky/AT Protocol services, but it does not prominently disclose that privacy implication. In a social-posting skill, undisclosed outbound transmission can expose sensitive content or files to third-party infrastructure and public posting surfaces.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The login method accepts an identifier and app password and immediately authenticates with the remote Bluesky service. While the docstring notes that an app password is used, there is no confirmation prompt, visible logging/print, or other user-facing disclosure in the code about transmitting credentials to an external service.

Content

No source excerpt is available for this finding.

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 · lib/bluesky_agent.py (reported line 28)May include surrounding context.

python
def upload_image(self, image_bytes, alt_text, mimetype="image/jpeg"):
        """Uploads an image blob and returns the reference."""
        return self.client.upload_blob(image_bytes, encoding=mimetype)

    def bookmark(self, uri, cid):
        """Private bookmarking."""

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
71% confidence
Finding

The post method transmits provided text and reply metadata to a remote service via send_post. The code contains no confirmation prompt, print/log disclosure, or inline comment/docstring warning that user content will be published externally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The upload_image method uploads raw image bytes to Bluesky using upload_blob. Although the docstring says it uploads an image blob, there is no user-facing disclosure or confirmation indicating that local content will be sent to an external network service.

Content

No source excerpt is available for this finding.