Back to skill

Security audit

Tinker LinkedIn

Security checks for vulnerabilities and agentic risk

Overview

This skill openly automates a user-shared LinkedIn tab and I found no hidden credential storage, remote relay, or exfiltration behavior.

Install this only if you are comfortable letting an agent operate a LinkedIn tab that is signed in as you. The skill does not appear to steal or store cookies, but it can read account and third-party profile data and can send a LinkedIn message when the exact per-message consent flag is provided; using it may still violate LinkedIn rules or risk account restrictions.

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 (48)

Credential Access

High
Category
Privilege Escalation
Confidence
83% confidence
Finding

Even if cookies never leave the browser process, this skill deliberately automates and scrapes a live authenticated LinkedIn session through a shared tab. Any compromise or misuse of the relay/channel controlling that tab effectively grants full access to a password-equivalent signed-in session, so the context remains highly sensitive despite the mitigations described.

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