Back to skill

Security audit

Unipile Linkedin Sdk

Security checks for vulnerabilities and agentic risk

Overview

This LinkedIn automation skill is mostly coherent, but it gives write-capable account actions too easily by default.

Install only if you trust the publisher and need LinkedIn automation through Unipile. Before use, set UNIPILE_PERMISSIONS=read by default, enable write only for a specific task, verify the UNIPILE_DSN comes from your Unipile dashboard and uses HTTPS, and revoke or rotate the token if it may have been used with an untrusted endpoint.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/linkedin.mjs:20
Finding

Write-capable LinkedIn operations are enabled by default

Content
View full analysis
p.trim().toLowerCase()); // Commands that require write permission const WRITE_COMMANDS = [ 'send', 'start-chat', 'invite', 'cancel-invite', 'create-post', 'comment', 'react' ]; function checkPermission(cmd) { if (WRITE_COMMANDS.includes(cmd) && !hasWrite) { console.error(`Error: Command '${cmd}' requires write permission.`); console.error(`Current permissions: ${PERMISSIONS.join(', ')}`); console.error(`Set UNIPILE_PERMISSIONS=write or UNIPILE_PERMISSIONS=read,write to enable.`); process.exit(3); } if (READ_COMMANDS.includes(cmd) && !hasRead) { console.error(`Error: Command '${cmd}' requires read permission.`); console.error(`Current permissions: ${PERMISSIONS.join(', ')}`); console.error(`Set UNIPILE_PERMISSIONS=read to enable.`); process.exit(3); } } ``` ### Technical Analysis The authorization layer defaults `UNIPILE_PERMISSIONS` to `read,write` whenever the variable is absent. Consequently, write authorization is granted implicitly rather than through an explicit operator decision. The write-command list includes externally visible and account-modifying operations such as sending messages, starting chats, publishing posts, commenting, reacting, sending invitations, and canceling invitations. Although `checkPermission()` blocks write commands when the configured permissions exclude `write`, that protection does not apply under the default configuration because `hasWrite` evaluates to true. This violates secure-by-default and least-privilege principles. The documentation recommends read-only operation, but the executable behavior grants full access u ...[truncated 1334 chars]
Remediation
View remediation
permission.trim().toLowerCase()); ``` 2. Require explicit write authorization for every write-capable deployment. Do not infer write permission from an absent or malformed value. 3. Reject unrecognized and empty permission entries: ```javascript const VALID_PERMISSIONS = new Set(['read', 'write']); if ( PERMISSIONS.length === 0 || PERMISSIONS.some(permission => !VALID_PERMISSIONS.has(permission)) ) { throw new Error('UNIPILE_PERMISSIONS must contain only "read" and/or "write".'); } ``` 4. Add an explicit confirmation mechanism for externally visible operations such as sending messages, invitations, comments, and posts. For unattended automation, require a separate narrowly scoped confirmation flag. 5. Where supported by Unipile, enforce equivalent restrictions at the API-token or account level. The local environment variable should not be the only authorization boundary. 6. Update help text and documentation so the secure default and explicit write opt-in are consistent across the implementation and documentation. 7. Add tests confirming that all write commands fail when `UNIPILE_PERMISSIONS` is absent. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/linkedin.mjs:18
Finding

Access token can be associated with an unvalidated caller-controlled API endpoint

Content
View full analysis
p.trim().toLowerCase()); if (!DSN || !TOKEN) { console.error('Error: UNIPILE_DSN and UNIPILE_ACCESS_TOKEN must be set'); console.error('Get credentials from https://dashboard.unipile.com'); process.exit(1); } const client = new UnipileClient(DSN, TOKEN); ``` ### Technical Analysis The application accepts `UNIPILE_DSN` from the environment and verifies only that it is nonempty. It does not parse the endpoint, require HTTPS, reject embedded credentials, or ensure that the hostname belongs to an approved Unipile service. The same configuration is then passed to `UnipileClient` together with the access token. Therefore, the confidentiality of the token and LinkedIn data depends entirely on the integrity of an unrestricted environment variable. If a deployment configuration, wrapper script, automation instruction, or compromised environment changes the DSN to an attacker-controlled endpoint, authenticated client traffic may be directed to that endpoint. A plain HTTP endpoint can also expose traffic to network interception. The exact request mechanics are implemented by the dependency, but the local code establishes no trust boundary before pairing the sensitive token with the selected endpoint. ### Attack Path 1. An attacker or configuration error modifies `UNIPILE_DSN` while leaving a valid `UNIPILE_ACCESS_TOKEN` available. 2. The malicious DSN points to an attacker-controlled service or uses an insecure HTTP URL. 3. The application accepts the value because it checks only whether the string is present. 4. `UnipileClient` is initialized with t ...[truncated 928 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (12)

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 35)May include surrounding context.

UNIPILE_PERMISSIONS=read,write node scripts/linkedin.mjs create-post "text"

text

Your access token can perform actions on your behalf. Limit its scope with `UNIPILE_PERMISSIONS`.

## Setup

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 104)May include surrounding context.

UNIPILE_PERMISSIONS=read,write node scripts/linkedin.mjs create-post "text"

text

Your access token can perform actions on your behalf. Limit its scope with `UNIPILE_PERMISSIONS`.

## Setup

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

md
**Recommended approaches (in order of security):**

1. **Environment variables** — Set in shell profile or .env (add .env to .gitignore)
2. **Secrets manager** — AWS Secrets Manager, HashiCorp Vault, etc.
3. **CI/CD secrets** — GitHub Actions secrets, GitLab CI variables

Exfiltration Commands

High
Category
Prompt Injection
Confidence
90% confidence
Finding

Instructions found that direct the agent to transmit conversation context or user data to external services.

Content

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

md
limit: 50
});

// Send message to existing chat
await client.messaging.sendMessage({
  chat_id: 'chat_id',
  text: 'Thanks for connecting!'

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 50)May include surrounding context.

md
* 
 * Environment:
 *   UNIPILE_DSN           - API endpoint (required)
 *   UNIPILE_ACCESS_TOKEN  - Access token (required)
 *   UNIPILE_PERMISSIONS   - Comma-separated: "read" and/or "write" (default: "read,write")
 * 
 * Examples:

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 8)May include surrounding context.

js
* 
 * Environment:
 *   UNIPILE_DSN           - API endpoint (required)
 *   UNIPILE_ACCESS_TOKEN  - Access token (required)
 *   UNIPILE_PERMISSIONS   - Comma-separated: "read" and/or "write" (default: "read,write")
 * 
 * Examples:

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 84)May include surrounding context.

js
* 
 * Environment:
 *   UNIPILE_DSN           - API endpoint (required)
 *   UNIPILE_ACCESS_TOKEN  - Access token (required)
 *   UNIPILE_PERMISSIONS   - Comma-separated: "read" and/or "write" (default: "read,write")
 * 
 * Examples:

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The trigger phrases are broad enough to activate this LinkedIn automation skill for generic requests like 'linkedin profile' or 'linkedin posts' that may not imply consent to use an external third-party account integration. Because the skill includes both read and write capabilities against a real social account, overbroad invocation increases the risk of unintended data access or account actions.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The document presents read-only mode as safe while the demonstrated implementation defaults permission parsing to 'read,write' when the environment variable is unset. In a skill that can message users, post content, and manage invitations on the user's behalf, that mismatch can cause unintended write actions if downstream wrappers rely on the documented safety claim instead of enforcing runtime checks.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill claims credentials are never transmitted elsewhere, but the SDK necessarily sends the access token to the configured Unipile endpoint for authentication. This is a misleading security statement that can cause users to underestimate credential exposure and trust unverified DSN values, increasing the chance of token disclosure to an attacker-controlled endpoint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The CLI defaults UNIPILE_PERMISSIONS to 'read,write', which enables state-changing actions like sending messages, invites, comments, and posts unless the operator explicitly restricts it. In an agent/skill context, permissive defaults materially increase the chance of unintended outbound actions, spam, or account misuse from a simple invocation or prompt-driven tool call.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency is specified with a caret range (^1.9.3), which permits automatic installation of newer compatible versions. This increases supply-chain risk because a future compromised or breaking upstream release could be pulled in without explicit review, especially for a CLI SDK that may handle authentication tokens or external API interactions.

Content

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

json
"author": "",
  "license": "ISC",
  "dependencies": {
    "unipile-node-sdk": "^1.9.3"
  }
}

Static analysis

No suspicious patterns detected.