OpenClaw LinkedIn Poster Skill

PassAudited by VirusTotal on May 12, 2026.

Overview

Type: OpenClaw Skill Name: openclawlinkedinposterskill Version: 1.0.0 The skill is classified as suspicious due to two main factors: the use of `child_process.exec` to open a browser with a URL that incorporates environment variables, which presents a potential shell injection vulnerability if `LINKEDIN_CLIENT_ID` is maliciously crafted (runner.cjs). Additionally, the skill relies on an external, third-party OAuth callback server (`https://linkedin-oauth-server-production.up.railway.app`) for handling the authorization flow, introducing a significant trust dependency and potential attack surface if that external service were compromised (SKILL.md, runner.cjs, README.md). While the skill's stated purpose is benign, these implementation details introduce notable security risks.

Findings (0)

Artifact-based informational review of SKILL.md, metadata, install specs, static scan signals, and capability signals. ClawScan does not execute the skill or run runtime probes.

What this means

A third-party service participates in the OAuth handoff for permissions that can publish to LinkedIn. If that service is compromised or mishandles state, authorization codes could be exposed or mixed up.

Why it was flagged

The OAuth authorization code is routed through and polled from a third-party hosted callback server, with timestamp-based state and no client-side authentication shown for retrieving the code.

Skill content
const CALLBACK_SERVER = 'https://linkedin-oauth-server-production.up.railway.app'; ... const state = Date.now().toString(); ... fetch(`${CALLBACK_SERVER}/api/token/${state}`);
Recommendation

Use a local or user-controlled audited OAuth callback, generate cryptographically random state, authenticate callback retrieval, and document the callback server's ownership, retention, and source.

What this means

A mistaken or ambiguous organization name could cause the agent to publish public content to the wrong company page or profile.

Why it was flagged

For company posts, the code selects the first organization name containing the provided text, then publishes a public LinkedIn post without an explicit confirmation step.

Skill content
if (orgInfo.name.toLowerCase().includes(normalizedTarget)) { ... return urn; } ... "com.linkedin.ugc.MemberNetworkVisibility": "PUBLIC" ... fetch('https://api.linkedin.com/v2/ugcPosts', { method: 'POST'
Recommendation

Require a preview and explicit confirmation before posting, use exact organization IDs or a user-selected list, and support draft/dry-run behavior.

What this means

If the saved token is misused or stolen, it may allow LinkedIn posting, including organization-page actions when those scopes are granted.

Why it was flagged

The skill requests personal and organization LinkedIn social permissions and persists the resulting access token locally for reuse.

Skill content
const TOKEN_FILE = path.join(__dirname, '.linkedin_token'); ... const SCOPE = 'openid profile w_member_social w_organization_social r_organization_social'; ... fs.writeFileSync(TOKEN_FILE, JSON.stringify(data));
Recommendation

Request organization scopes only when needed, separate personal and organization authorization flows, store tokens with restrictive permissions, and provide a clear token revocation/removal process.

What this means

Normal users should see a browser open for LinkedIn authorization; the main concern is implementation hardening rather than evidence of malicious execution.

Why it was flagged

The OAuth flow opens the browser through a shell command. This is expected for the setup flow, but using shell execution with runtime-built strings is a safer-to-avoid pattern.

Skill content
const { exec } = require('child_process'); ... exec(`${startCmd} "${authUrl}"`);
Recommendation

Use a non-shell launcher such as spawn/execFile with fixed arguments, and ensure URL parameters are encoded.