Back to skill

Security audit

Tinker LinkedIn

Security checks for vulnerabilities and agentic risk

Overview

This skill is high-trust LinkedIn browser automation, but its sensitive access is clearly disclosed, scoped to a shared LinkedIn tab, and includes meaningful user controls.

Install only if you are comfortable letting an agent operate a LinkedIn tab you explicitly share, including reading inbox-related data and sending a message when you provide the exact consent flag. Keep the cache off unless you need it, unshare the tab to stop access, and understand that LinkedIn automation can put the account at risk even when the skill itself is scoped.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (49)

Credential Access

High
Category
Privilege Escalation
Confidence
79% confidence
Finding

Even though the skill claims it never reads cookies directly, it automates a live authenticated LinkedIn browser tab and issues in-page requests using the user's active session. That gives the skill effective access to a password-equivalent authenticated context, including inbox, connections, feed, and messaging capabilities, so compromise or misuse of the skill could act fully as the user without reauthentication.

Content

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

md
- **Your LinkedIn session cookies — indirectly, and it never sees them.** Treat `li_at` as a password: it is a full sign-in as you, with no second factor. This version has no code that reads it. The browser attaches it to a same-origin request; the skill neither receives nor stores the value.
- **It navigates and scrapes that tab.** Naming this plainly, because it is more than passive API use: people-search works by sending the shared tab to a LinkedIn search URL and reading the rendered DOM (LinkedIn's SDUI broke the classic Voyager search endpoint). It is browser automation on a live, signed-in session, and you should treat it as such.
- **Two files, both mode 0600, both under `~/.openclaw/workspace/memory`** — the rate-guard counters (`linkedin-activity.json`) and the opt-in crawl cache (`linkedin-cache.json`), each written via a temp file and atomic rename; counter updates also hold a short-lived `linkedin-activity.json.lock`. No credential file is written under any flag. It reads nothing else on your disk.
- **One binary per platform, run with a fixed argument list and no shell** — `secret-tool clear` (Linux) or `security delete-generic-password` (macOS), run **only** by `session logout` to delete a keychain entry an older version could have created, with its output discarded. The code contains no keychain lookup.
- **The local browser relay, and only on loopback.** `LINKEDIN_CDP_URL` / `LINKEDIN_RELAY_HTTP` are overridable, so both are parsed and the host must be a **literal loopback IP** (`127.0.0.1`, anything in `127.0.0.0/8`, or `[::1]`). A hostname — `localhost` included — is refused rather than resolved, so a name that answers loopback at check time and something else at connect time (DNS rebinding) cannot get through, and the relay's HTTP redirects are refused. Anything else is refused outright — the `LINKEDIN_ALLOW_REMOTE_RELAY` escape hatch has been removed, because that channel is full control of a tab that is signed in as you.

### Where the secret l
...[truncated 23 chars]

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
Run them with `node --test tests/origin.test.mjs tests/cli.test.mjs` (Node 22+, no dev dependencies).

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- **Off switch** — `node scripts/linkedin.mjs session logout`

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

js
// is no keychain lookup anywhere in this file: no code path asks the keychain for a
// value, so a legacy secret is never copied into this process. Nothing in this
// version writes a credential anywhere.
const KEYRING_SERVICE = 'openclaw-linkedin-hack';
const KEYRING_ACCOUNT = 'linkedin-session';
const KEYCHAIN_BIN = platform() === 'darwin' ? 'security' : 'secret-tool';

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

js
// is no keychain lookup anywhere in this file: no code path asks the keychain for a
// value, so a legacy secret is never copied into this process. Nothing in this
// version writes a credential anywhere.
const KEYRING_SERVICE = 'openclaw-linkedin-hack';
const KEYRING_ACCOUNT = 'linkedin-session';
const KEYCHAIN_BIN = platform() === 'darwin' ? 'security' : 'secret-tool';

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

js
// is no keychain lookup anywhere in this file: no code path asks the keychain for a
// value, so a legacy secret is never copied into this process. Nothing in this
// version writes a credential anywhere.
const KEYRING_SERVICE = 'openclaw-linkedin-hack';
const KEYRING_ACCOUNT = 'linkedin-session';
const KEYCHAIN_BIN = platform() === 'darwin' ? 'security' : 'secret-tool';

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

js
// is no keychain lookup anywhere in this file: no code path asks the keychain for a
// value, so a legacy secret is never copied into this process. Nothing in this
// version writes a credential anywhere.
const KEYRING_SERVICE = 'openclaw-linkedin-hack';
const KEYRING_ACCOUNT = 'linkedin-session';
const KEYCHAIN_BIN = platform() === 'darwin' ? 'security' : 'secret-tool';

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

js
// is no keychain lookup anywhere in this file: no code path asks the keychain for a
// value, so a legacy secret is never copied into this process. Nothing in this
// version writes a credential anywhere.
const KEYRING_SERVICE = 'openclaw-linkedin-hack';
const KEYRING_ACCOUNT = 'linkedin-session';
const KEYCHAIN_BIN = platform() === 'darwin' ? 'security' : 'secret-tool';

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

js
// version writes a credential anywhere.
const KEYRING_SERVICE = 'openclaw-linkedin-hack';
const KEYRING_ACCOUNT = 'linkedin-session';
const KEYCHAIN_BIN = platform() === 'darwin' ? 'security' : 'secret-tool';

// Stamped into every file this skill creates, so the delete guard below can prove a
// file is ours before removing it.

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

js
// version writes a credential anywhere.
const KEYRING_SERVICE = 'openclaw-linkedin-hack';
const KEYRING_ACCOUNT = 'linkedin-session';
const KEYCHAIN_BIN = platform() === 'darwin' ? 'security' : 'secret-tool';

// Stamped into every file this skill creates, so the delete guard below can prove a
// file is ours before removing it.

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

js
// version writes a credential anywhere.
const KEYRING_SERVICE = 'openclaw-linkedin-hack';
const KEYRING_ACCOUNT = 'linkedin-session';
const KEYCHAIN_BIN = platform() === 'darwin' ? 'security' : 'secret-tool';

// Stamped into every file this skill creates, so the delete guard below can prove a
// file is ours before removing it.

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

js
// version writes a credential anywhere.
const KEYRING_SERVICE = 'openclaw-linkedin-hack';
const KEYRING_ACCOUNT = 'linkedin-session';
const KEYCHAIN_BIN = platform() === 'darwin' ? 'security' : 'secret-tool';

// Stamped into every file this skill creates, so the delete guard below can prove a
// file is ours before removing it.

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

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

js
if (!conv || !message) {
    console.error(
      'Usage: linkedin message-send <conversationUrn> --message "text" --i-mean-it <conversationUrn>\n' +
        '  Sending is the only write this skill can perform, and consent is PER ACTION:\n' +
        '  --i-mean-it must repeat the exact conversation URN you are writing to.',
    );
    process.exit(1);

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

md
// End-to-end CLI tests. Every run gets a throwaway HOME so nothing touches the real
// activity counters or cache, and an empty PATH so the keychain binary is absent and
// the result is the same on any machine.
import test from 'node:test';
import assert from 'node:assert/strict';

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

md
// End-to-end CLI tests. Every run gets a throwaway HOME so nothing touches the real
// activity counters or cache, and an empty PATH so the keychain binary is absent and
// the result is the same on any machine.
import test from 'node:test';
import assert from 'node:assert/strict';

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

md
// End-to-end CLI tests. Every run gets a throwaway HOME so nothing touches the real
// activity counters or cache, and an empty PATH so the keychain binary is absent and
// the result is the same on any machine.
import test from 'node:test';
import assert from 'node:assert/strict';

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

md
// End-to-end CLI tests. Every run gets a throwaway HOME so nothing touches the real
// activity counters or cache, and an empty PATH so the keychain binary is absent and
// the result is the same on any machine.
import test from 'node:test';
import assert from 'node:assert/strict';

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

md
// End-to-end CLI tests. Every run gets a throwaway HOME so nothing touches the real
// activity counters or cache, and an empty PATH so the keychain binary is absent and
// the result is the same on any machine.
import test from 'node:test';
import assert from 'node:assert/strict';

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

md
// End-to-end CLI tests. Every run gets a throwaway HOME so nothing touches the real
// activity counters or cache, and an empty PATH so the keychain binary is absent and
// the result is the same on any machine.
import test from 'node:test';
import assert from 'node:assert/strict';

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

md
// End-to-end CLI tests. Every run gets a throwaway HOME so nothing touches the real
// activity counters or cache, and an empty PATH so the keychain binary is absent and
// the result is the same on any machine.
import test from 'node:test';
import assert from 'node:assert/strict';

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

js
// End-to-end CLI tests. Every run gets a throwaway HOME so nothing touches the real
// activity counters or cache, and an empty PATH so the keychain binary is absent and
// the result is the same on any machine.
import test from 'node:test';
import assert from 'node:assert/strict';

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

js
// End-to-end CLI tests. Every run gets a throwaway HOME so nothing touches the real
// activity counters or cache, and an empty PATH so the keychain binary is absent and
// the result is the same on any machine.
import test from 'node:test';
import assert from 'node:assert/strict';

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

js
// End-to-end CLI tests. Every run gets a throwaway HOME so nothing touches the real
// activity counters or cache, and an empty PATH so the keychain binary is absent and
// the result is the same on any machine.
import test from 'node:test';
import assert from 'node:assert/strict';

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

js
// End-to-end CLI tests. Every run gets a throwaway HOME so nothing touches the real
// activity counters or cache, and an empty PATH so the keychain binary is absent and
// the result is the same on any machine.
import test from 'node:test';
import assert from 'node:assert/strict';

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

js
// End-to-end CLI tests. Every run gets a throwaway HOME so nothing touches the real
// activity counters or cache, and an empty PATH so the keychain binary is absent and
// the result is the same on any machine.
import test from 'node:test';
import assert from 'node:assert/strict';

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/linkedin.mjs:165

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
tests/cli.test.mjs:36