Back to skill

Security audit

storyagent_linkedin

Security checks for vulnerabilities and agentic risk

Overview

This LinkedIn skill is coherent and not malicious, but it can immediately send messages, invitations, posts, comments, and reactions through a real account without clear confirmation safeguards.

Install only if you are comfortable giving the skill a Unipile token that can act on your LinkedIn account. Treat send, start-chat, invite, cancel-invite, create-post, comment, react, and profile --notify as live external actions, and require explicit approval before running them. Use a trusted Unipile endpoint, protect and rotate the token, and revoke it if the endpoint or environment configuration may have been changed.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/linkedin.mjs:8
Finding

User-Controlled API Endpoint Can Receive the Unipile Access Token

Content
View full analysis

Vulnerability Details

File Location: scripts/linkedin.mjs, lines 8–16
Vulnerability Type: Unvalidated credential-bearing service endpoint
Risk Level: Medium

Vulnerable Code

js
const DSN = process.env.UNIPILE_DSN;
const TOKEN = process.env.UNIPILE_ACCESS_TOKEN;

if (!DSN || !TOKEN) {
  console.error('Error: Set UNIPILE_DSN and UNIPILE_ACCESS_TOKEN environment variables');
  console.error('Get credentials from https://dashboard.unipile.com');
  process.exit(1);
}

const client = new UnipileClient(DSN, TOKEN);

Technical Analysis

The CLI obtains both the API endpoint and access token from environment variables and passes them directly to UnipileClient. Although the code checks that both values exist, it does not validate the endpoint's protocol, hostname, port, embedded credentials, or destination.

Consequently, an attacker who can influence UNIPILE_DSN while preserving the legitimate UNIPILE_ACCESS_TOKEN can redirect authenticated SDK requests to an attacker-controlled service. Depending on how the SDK transmits authentication, that service may receive the access token or another reusable authorization value.

This requires control over the process environment, an environment file loaded by dotenv/config, or the mechanism that supplies skill configuration. The issue does not independently provide such control.

Attack Path

  1. A legitimate Unipile access token is configured in UNIPILE_ACCESS_TOKEN.
  2. An attacker modifies the process environment or loaded dotenv configuration so that UNIPILE_DSN references an attacker-controlled endpoint.
  3. A user or agent invokes any CLI command, such as accounts.
  4. The CLI initializes UnipileClient with the attacker-selected endpoint and legitimate token.
  5. The SDK sends an authenticated request to that endpoint.
  6. The attacker captures the exposed authentication material and attempts to reuse it against the legitimate Unipile service.

Impact Assessment

Successfu ...[truncated 691 chars]

Remediation
View remediation

Remediation Suggestions

Validate and normalize the endpoint before constructing the API client:

  1. Parse UNIPILE_DSN with new URL() and reject malformed values.
  2. Require the https: protocol.
  3. Enforce an explicit allowlist of trusted Unipile hostnames or the exact tenant endpoint provisioned through a trusted configuration source.
  4. Reject IP literals, loopback addresses, private-network destinations, link-local addresses, embedded URL credentials, fragments, and unexpected ports.
  5. Ensure the HTTP client does not forward authorization headers across cross-origin redirects; preferably disable redirects or validate every redirect destination.
  6. Store the endpoint in deployment-controlled configuration that untrusted users and skill inputs cannot modify.
  7. Scope and rotate the access token, and revoke it immediately if endpoint manipulation or credential exposure is suspected.
  8. Consider deriving the endpoint from a trusted tenant or region identifier rather than accepting an unrestricted URL.

Example validation pattern:

js
function validateUnipileDsn(rawDsn) {
  const url = new URL(rawDsn);

  if (url.protocol !== 'https:') {
    throw new Error('UNIPILE_DSN must use HTTPS');
  }

  if (
    url.username ||
    url.password ||
    url.hash ||
    !url.hostname.endsWith('.unipile.com')
  ) {
    throw new Error('UNIPILE_DSN is not an approved Unipile endpoint');
  }

  return url.origin;
}

const client = new UnipileClient(
  validateUnipileDsn(process.env.UNIPILE_DSN),
  process.env.UNIPILE_ACCESS_TOKEN
);

A strict tenant-specific hostname allowlist is preferable to a broad suffix check.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (13)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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

md
Requires environment variables in `~/.openclaw/workspace/TOOLS.md` or shell:
- `UNIPILE_DSN` - Your Unipile API endpoint (e.g., `https://api1.unipile.com:13111`)
- `UNIPILE_ACCESS_TOKEN` - Your Unipile access token

Get credentials from [dashboard.unipile.com](https://dashboard.unipile.com).

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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

md
Requires environment variables in `~/.openclaw/workspace/TOOLS.md` or shell:
- `UNIPILE_DSN` - Your Unipile API endpoint (e.g., `https://api1.unipile.com:13111`)
- `UNIPILE_ACCESS_TOKEN` - Your Unipile access token

Get credentials from [dashboard.unipile.com](https://dashboard.unipile.com).

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/linkedin.mjs (reported line 273)May include surrounding context.

js
Environment:
  UNIPILE_DSN              API endpoint (https://xxx.unipile.com:port)
  UNIPILE_ACCESS_TOKEN     Access token from dashboard.unipile.com
`);
        process.exit(0);
    }

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README documents commands that send messages, create posts, comment, react, and manage invitations on LinkedIn, but it does not clearly warn that these are live external actions performed on the user's behalf. In an agent-skill context, that omission can cause accidental social actions, spam, reputation damage, or unintended outreach if a user or agent treats the commands as read-only or low-risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The profile command includes a --notify option that can alert the viewed party, but the README does not explain the privacy consequence of enabling it. In a social-networking skill, silent omission of that behavior can expose the user's identity, reveal research or outreach activity, and create unexpected contact or trust issues.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill exposes capabilities that rely on environment-held secrets and external account access, but it does not declare any tool scope or permission boundaries. In an agent setting, this makes it easier for the skill to be invoked without clear authorization constraints, increasing the chance of unintended access to LinkedIn account data or actions.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
76% confidence
Finding

The skill is designed to operate on a persistent authenticated LinkedIn session through stored account identifiers and access tokens, enabling repeated access and actions over time. In context, that persistence increases risk because the skill supports both private data access and outward-facing actions without clear guardrails.

Content

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

md
---
name: unipile-linkedin
description: Interact with LinkedIn via Unipile API - send messages, view profiles, manage connections, create posts, react to content. Use when the user asks to message someone on LinkedIn, check LinkedIn messages, view LinkedIn profiles, send connection requests, create LinkedIn posts, or interact with LinkedIn content.
---

# Unipile LinkedIn

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The description is broad enough to match many generic LinkedIn-related user requests, including sensitive ones like messaging, connection management, and posting. Over-broad routing can cause the agent to invoke this skill in situations where the user did not clearly consent to account access or outbound actions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill can perform external actions on behalf of the user, including sending messages, creating posts, commenting, reacting, and sending invitations, yet the documentation provides no warning that these actions affect a real LinkedIn account. Without clear warnings and confirmation expectations, users may trigger public or irreversible actions unintentionally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The CLI exposes multiple state-changing LinkedIn operations such as sending messages, starting chats, sending invitations, creating posts, commenting, reacting, and canceling invitations without any confirmation gate, dry-run mode, or explicit safety warning. In an agent skill context, this increases the risk of accidental or prompt-induced external side effects on a real user account, especially because these actions can execute immediately from provided arguments.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The documentation instructs users to supply an access token and references account data retrieval, but it does not include privacy guidance on handling secrets or personal LinkedIn data. This increases the risk of accidental credential exposure or over-collection of account information in shared environments.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 6)May include surrounding context.

json
"version": "1.0.0",
  "type": "module",
  "dependencies": {
    "dotenv": "^17.2.4",
    "unipile-node-sdk": "^1.9.3"
  }
}

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 7)May include surrounding context.

json
"type": "module",
  "dependencies": {
    "dotenv": "^17.2.4",
    "unipile-node-sdk": "^1.9.3"
  }
}

Static analysis

No suspicious patterns detected.