Back to skill

Security audit

Linkedin Cli

Security checks for vulnerabilities and agentic risk

Overview

This skill is a mostly coherent LinkedIn posting tool, but it installs unaudited global code and exposes destructive post deletion without matching warnings or confirmation.

Install only if you trust and have reviewed the upstream linkedin-cli package, preferably pinning to an immutable commit or using an isolated install. Treat the configured LinkedIn token as authority to publish and delete content on your account, and require explicit confirmation before any delete operation.

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:8
Finding
Mutable External Git Source Used for Global CLI Installation## Vulnerability Details **File Location**: `SKILL.md`, lines 8-15 **Vulnerability Type**: Supply-chain exposure through an externally fetched package pinned to a mutable Git tag **Risk Level**: Medium ### Vulnerable Code ```yaml metadata: {"openclaw":{"emoji":"💼","requires":{"bins":["linkedin-cli"],"env":["LINKEDIN_CLIENT_ID","LINKEDIN_CLIENT_SECRET","LINKEDIN_ACCESS_TOKEN"]},"install":[{"id":"npm","kind":"shell","command":"npm install -g github:0xmythril/linkedin-cli#v1.0.0","bins":["linkedin-cli"],"label":"Install linkedin-cli v1.0.0 (npm)"}]}} ``` ```bash npm install -g github:0xmythril/linkedin-cli#v1.0.0 ``` ### Technical Analysis The installation procedure downloads and installs executable code directly from a personal GitHub repository. Although the source is pinned to the `v1.0.0` tag, Git tags can be moved or recreated by a repository administrator and therefore do not provide the immutability of a reviewed commit hash or a cryptographically verified archive. The downloaded implementation, package manifest, lockfile, and dependency tree are not included in the audited project. Consequently, the assertions in `SKILL.md` that the package has no installation scripts, has only three runtime dependencies, and communicates exclusively with LinkedIn cannot be independently verified from the available artifact. The `-g` option installs the package globally. Any npm lifecycle script present in the retrieved package could execute with the privileges of the user running npm, while the installed CLI will subsequently receive access to LinkedIn OAuth credentials. This behavior grants externally controlled code substantial authority relative to the Skill's narrow posting functionality. ### Attack Path 1. An attacker compromises the GitHub repository owner account, repository, release workflow, or another component involved in dependency resolution. 2. The attacker moves or recreates the `v1.0.0` tag, or modifies an unpinne ...[truncated 1364 chars]
Remediation
## Remediation Suggestions 1. Pin the installation to a reviewed, immutable full Git commit hash rather than a release tag. 2. Obtain the source archive through a controlled release process and verify a documented cryptographic checksum before installation. 3. Include the reviewed source, `package.json`, and lockfile in the audit scope so lifecycle scripts, dependencies, and network destinations can be verified. 4. Prefer a project-local or isolated installation over `npm install -g` to reduce the affected scope. 5. Use `npm install --ignore-scripts` when the verified package does not require lifecycle scripts. 6. Pin all transitive dependencies through a lockfile and use integrity hashes. 7. Verify repository ownership, release signatures, package contents, and the resolved commit before installation. 8. Run the CLI with only the required environment variables and avoid exposing unrelated credentials or sensitive directories.

T09 · Insecure Skill Coding Practices

Note
Location
SKILL.md:23
Finding
Credential Setup Can Follow and Overwrite a Pre-existing Symbolic Link## Vulnerability Details **File Location**: `SKILL.md`, lines 23-29 **Vulnerability Type**: Unsafe credential-file creation and symbolic-link handling **Risk Level**: Low ### Vulnerable Code ```bash mkdir -p ~/.config/linkedin-cli touch ~/.config/linkedin-cli/.env chmod 600 ~/.config/linkedin-cli/.env cat > ~/.config/linkedin-cli/.env << 'EOF' LINKEDIN_CLIENT_ID=your_client_id LINKEDIN_CLIENT_SECRET=your_client_secret EOF ``` ### Technical Analysis The setup sequence operates on a predictable path without first verifying that the configuration directory and `.env` destination are genuine user-owned filesystem objects rather than symbolic links. Both `touch` and `chmod` normally follow a pre-existing symbolic link. Shell output redirection also opens the symlink target and truncates it before `cat` executes. If `~/.config/linkedin-cli/.env` points to another file writable by the current user, the instructions can change that target's permissions to mode `600` and replace its contents with the credential template. The parent directory is created without an explicit restrictive mode. The `.env` file is eventually assigned mode `600`, which appropriately restricts ordinary file access, and storing LinkedIn credentials is necessary for the declared OAuth functionality. The issue is therefore unsafe destination handling rather than unnecessary credential access or a direct privilege escalation. ### Attack Path 1. An attacker who can modify the user's configuration path creates `~/.config/linkedin-cli/.env` as a symbolic link to another file writable by that user. 2. The user follows the documented credential setup commands. 3. `touch` follows the symbolic link and accesses the target. 4. `chmod 600` changes the permissions of the linked target rather than safely securing a newly created `.env` file. 5. The shell processes the output redirection and truncates the linked target. 6. The credential template is ...[truncated 791 chars]
Remediation
## Remediation Suggestions 1. Create the configuration directory with mode `700` and verify that it is a real directory owned by the current user. 2. Reject the operation if either the directory or destination is a symbolic link. 3. Create the credential file with mode `600` from the outset rather than creating it under the process's current umask and changing permissions afterward. 4. Write credentials to a securely created temporary file in the validated directory, set mode `600`, and atomically rename it into place only after revalidating the destination. 5. Refuse to overwrite an existing file unless the user explicitly confirms replacement and the file has been verified as a regular, user-owned file. 6. Prefer an operating-system credential store or secret manager when supported, reducing reliance on plaintext OAuth client secrets. A hardened setup utility should perform `lstat`-style checks that do not follow symbolic links, validate ownership and type for every path component, create files with exclusive-create and no-follow semantics, and fail closed if any validation cannot be completed.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

Credential Access

High
Category
Privilege Escalation
Content
3. Configure credentials (file is created with restricted permissions):
```bash
mkdir -p ~/.config/linkedin-cli
touch ~/.config/linkedin-cli/.env
chmod 600 ~/.config/linkedin-cli/.env
cat > ~/.config/linkedin-cli/.env << 'EOF'
LINKEDIN_CLIENT_ID=your_client_id
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
3. Configure credentials (file is created with restricted permissions):
```bash
mkdir -p ~/.config/linkedin-cli
touch ~/.config/linkedin-cli/.env
chmod 600 ~/.config/linkedin-cli/.env
cat > ~/.config/linkedin-cli/.env << 'EOF'
LINKEDIN_CLIENT_ID=your_client_id
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
3. Configure credentials (file is created with restricted permissions):
```bash
mkdir -p ~/.config/linkedin-cli
touch ~/.config/linkedin-cli/.env
chmod 600 ~/.config/linkedin-cli/.env
cat > ~/.config/linkedin-cli/.env << 'EOF'
LINKEDIN_CLIENT_ID=your_client_id
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Session Persistence

Medium
Category
Rogue Agent
Content
```bash
npm install -g github:0xmythril/linkedin-cli#v1.0.0
```
2. Create a LinkedIn app at https://www.linkedin.com/developers/apps
   - Enable **Sign In with LinkedIn using OpenID Connect** and **Share on LinkedIn** products
   - Add `http://localhost:8585/callback` to **Authorized redirect URLs**
3. Configure credentials (file is created with restricted permissions):
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
```bash
mkdir -p ~/.config/linkedin-cli
touch ~/.config/linkedin-cli/.env
chmod 600 ~/.config/linkedin-cli/.env
cat > ~/.config/linkedin-cli/.env << 'EOF'
LINKEDIN_CLIENT_ID=your_client_id
LINKEDIN_CLIENT_SECRET=your_client_secret
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
## Security

- **Credentials**: Stored in `~/.config/linkedin-cli/.env` (read by `dotenv` at runtime). Set `chmod 600` to restrict access.
- **No postinstall scripts**: The package has zero install scripts — verify via `npm pack --dry-run` or inspect `package.json`.
- **No telemetry or network calls** except to the official LinkedIn API (`api.linkedin.com`) and OAuth (`www.linkedin.com`) when you run a command.
- **Pinned install**: The install command pins to a specific release tag. Audit the source at https://github.com/0xmythril/linkedin-cli before installing.
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The documentation presents the tool as 'for posting only' while also exposing a delete command, which is a capability mismatch. This can mislead users or downstream agents into granting or invoking more destructive functionality than expected, increasing the chance of accidental content deletion.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The inline guidance says the tool is only for posting, but the command set includes deletion, creating inconsistent security expectations. Such inconsistencies are risky in agent skills because policy logic may rely on the stated scope and fail to apply safeguards to destructive actions.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill documents a destructive delete command without any warning, preview, or mandatory confirmation flow. In an agent setting, that raises the risk of accidental or prompt-induced deletion of LinkedIn posts, especially if identifiers can be provided in several formats.

Static analysis

No suspicious patterns detected.