Back to skill

Security audit

Insta Content Engine

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent social-content tool, but it handles live social posting and credentials with unsafe execution patterns that merit review before installation.

Install only if you are comfortable giving this skill access to social accounts and API keys. Use a dedicated Instagram account, avoid passing passwords on the command line, review commands before posting, and treat search queries or captions from untrusted sources as unsafe until the shell/code-injection issues are fixed.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/viral-search.js:76
Finding

Shell Command Injection in X/Twitter Search

Content
View full analysis

Vulnerability Details

File Location: scripts/viral-search.js, lines 76-80
Vulnerability Type: OS command injection
Risk Level: Critical

Vulnerable Code

javascript
const fetchCount = Math.min(limit * 3, 40);
const raw = execSync(`bird search "${searchQuery.replace(/"/g, '\\"')}" -n ${fetchCount} --json`, {
  encoding: 'utf8',
  timeout: 30000,
  stdio: ['pipe', 'pipe', 'pipe'],
});

Technical Analysis

The user-controlled search query is interpolated into a command string passed to execSync, which executes the string through a system shell. Replacing double quotation marks with \" is not sufficient shell escaping.

In particular, command substitutions such as $(command) and backtick expressions remain active inside double-quoted shell strings. Consequently, an attacker who can influence the search topic can cause the shell to execute an arbitrary local command rather than treating the entire value as a literal search query.

Attack Path

  1. An attacker supplies or persuades the Agent to search for a crafted topic containing shell command substitution, such as topic $(attacker_command).
  2. The value is appended to searchQuery.
  3. The script only escapes double quotation marks.
  4. execSync passes the constructed string to a shell.
  5. The shell evaluates the command substitution before invoking bird.
  6. The injected command runs with the same operating-system privileges and environment as the Agent.

Impact Assessment

Successful exploitation permits arbitrary command execution under the account running the Skill. An attacker could read or modify accessible files, retrieve environment variables and API credentials, access browser or social-media authentication state, invoke network utilities, alter generated content, or use the Agent's account to compromise other reachable resources.

Remediation
View remediation

Remediation Suggestions

Replace shell-based execSync with an argument-array API that does not invoke a shell:

javascript
const { execFileSync } = require('child_process');

const raw = execFileSync(
  'bird',
  ['search', searchQuery, '-n', String(fetchCount), '--json'],
  {
    encoding: 'utf8',
    timeout: 30000,
    stdio: ['pipe', 'pipe', 'pipe'],
    shell: false,
  }
);

Also validate query length and reject control characters. Do not attempt to solve this issue using ad hoc shell escaping; keeping untrusted values out of shell command strings is the safer design.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/viral-search.js:141
Finding

Shell Command Injection in Instagram Search Invocation

Content
View full analysis

Vulnerability Details

File Location: scripts/viral-search.js, lines 141-158
Vulnerability Type: OS command injection
Risk Level: Critical

Vulnerable Code

javascript
const raw = execSync(
  `node "${path.join(scriptDir, 'instagram-search.js')}" "${query} viral popular trending" --limit ${limit}`,
  { encoding: 'utf8', timeout: 15000, stdio: ['pipe', 'pipe', 'pipe'] }
);

console.log(raw);
} catch (e) {
  // Fallback to regular search with popular modifier
  try {
    const raw = execSync(
      `node "${path.join(scriptDir, 'instagram-search.js')}" "${query} popular" --limit ${limit}`,
      { encoding: 'utf8', timeout: 15000, stdio: ['pipe', 'pipe', 'pipe'] }
    );

Technical Analysis

The Instagram search path inserts the user-controlled query directly into two shell command strings. No shell escaping or argument separation is applied.

Double quotes do not prevent command substitution in a shell. A query containing $(command) or backticks can therefore execute an arbitrary command. Inputs containing quotation marks and shell operators may also break out of the intended argument and inject additional commands.

The fallback command repeats the same flaw, so failure of the first invocation does not provide a safe recovery path.

Attack Path

  1. An attacker controls or influences the topic passed to viral-search.js.
  2. The Instagram search path concatenates that topic into an execSync command.
  3. The shell parses substitutions and metacharacters embedded in the topic.
  4. The injected command executes locally.
  5. If the first invocation fails, the fallback invocation processes the malicious query through another vulnerable shell command.

Impact Assessment

Exploitation grants arbitrary command execution with the privileges of the Skill process. The attacker may access the Brave API key, OpenAI credentials, Instagram credentials or session data available ...[truncated 87 chars]

Remediation
View remediation

Remediation Suggestions

Invoke Node directly without a shell and pass every value as a separate argument:

javascript
const { execFileSync } = require('child_process');
const searchScript = path.join(scriptDir, 'instagram-search.js');

const raw = execFileSync(
  process.execPath,
  [searchScript, `${query} viral popular trending`, '--limit', String(limit)],
  {
    encoding: 'utf8',
    timeout: 15000,
    stdio: ['pipe', 'pipe', 'pipe'],
    shell: false,
  }
);

Apply the same change to the fallback invocation. Validate that limit is a bounded positive integer and impose a reasonable maximum query length.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/instagram-post.js:28
Finding

Python Code Injection Through the Instagram Action Argument

Content
View full analysis

Vulnerability Details

File Location: scripts/instagram-post.js, lines 28-28 and 89-93
Vulnerability Type: Generated-code injection
Risk Level: High

Vulnerable Code

javascript
if (args[i] === '--action' && args[i + 1]) { action = args[i + 1]; i++; }

The unvalidated value is subsequently embedded into generated Python source:

javascript
caption = '''${escapePy(caption)}'''
media_files = [${mediaListPy}]
action = '${action}'

try:

The generated source is then executed:

javascript
const result = execSync(`python3 -c '${pyScript.replace(/'/g, "'\"'\"'")}'`, {
  encoding: 'utf8',
  timeout: 120000,
  stdio: ['pipe', 'pipe', 'pipe'],
});

Technical Analysis

Although the documentation states that the action should be one of photo, reel, story, or carousel, the parser accepts any string. That string is inserted directly into a single-quoted Python literal without passing through escapePy or another serialization mechanism.

A crafted action can terminate the Python string, insert Python statements, and comment out the remaining characters. The later shell-quoting transformation only protects transport of the generated script through the shell; it does not make the resulting Python source safe.

Attack Path

  1. An attacker supplies a malicious --action argument containing a closing quote and Python statements.
  2. Argument parsing assigns the complete value to action without allowlist validation.
  3. Template interpolation places the value inside the generated Python program.
  4. The malicious value terminates the intended string literal and changes the Python program.
  5. python3 -c executes the altered program.
  6. Injected Python runs with the privileges and environment of the posting process.

Impact Assessment

Successful exploitation provides arbitrary Python code execution. The injected code runs in a process that has access to ...[truncated 230 chars]

Remediation
View remediation

Remediation Suggestions

Enforce a strict allowlist before any execution:

javascript
const allowedActions = new Set(['photo', 'reel', 'story', 'carousel']);
if (!allowedActions.has(action)) {
  console.error('Invalid action');
  process.exit(1);
}

More importantly, stop constructing Python source from runtime data. Place the Python implementation in a fixed .py file and invoke it with spawnSync or execFileSync, passing action, caption, session path, and media paths through an argument array or structured JSON over standard input. Set shell: false.

The Python program should independently validate the action against the same allowlist before performing any account operation.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/instagram-post.js:29
Finding

Instagram Credentials Accepted Through Process Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/instagram-post.js, lines 29-31
Vulnerability Type: Sensitive information exposure
Risk Level: Medium

Vulnerable Code

javascript
else if (args[i] === '--media' && args[i + 1]) { mediaFiles.push(args[i + 1]); i++; }
else if (args[i] === '--username' && args[i + 1]) { username = args[i + 1]; i++; }
else if (args[i] === '--password' && args[i + 1]) { password = args[i + 1]; i++; }
else if (args[i] === '--session' && args[i + 1]) { sessionFile = args[i + 1]; i++; }

Technical Analysis

Allowing an Instagram password through --password exposes the secret in the process argument vector. Depending on the operating system and execution environment, command-line arguments may be visible in process listings, monitoring tools, audit records, shell history, job metadata, debugging output, or Agent transcripts.

This exposure exists even if the password is not explicitly printed by the script.

Attack Path

  1. A user invokes the script with --password SECRET.
  2. The operating system records SECRET as part of the process argument vector.
  3. Another local process, monitoring service, command-history reader, or log consumer obtains the command line.
  4. The exposed credentials are used to authenticate to the Instagram account.

Impact Assessment

Exposure of the password can enable Instagram account takeover, unauthorized posts or deletion of content, access to account information, and compromise of other services if the password was reused. The exact visibility of process arguments depends on host isolation and operating-system policy.

Remediation
View remediation

Remediation Suggestions

Remove the --password option. Obtain credentials from an approved secret manager, protected credential helper, or inherited environment variable supplied by a secure launcher.

Ensure that:

  • Secrets are never included in command lines, logs, errors, or Agent-visible transcripts.
  • Environment variables are restricted to the child process that needs them.
  • Stored session files have restrictive permissions, such as mode 0600.
  • Documentation recommends a dedicated account and password rather than password reuse.
  • Existing credentials previously passed on command lines are rotated if they may have entered logs or history.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:14
Finding

Unpinned Third-Party Python Dependencies

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, line 14
Vulnerability Type: Supply-chain and dependency integrity risk
Risk Level: Medium

Vulnerable Code

markdown
- **Instagram Posting**: `pip3 install instagrapi pillow` + IG_USERNAME/IG_PASSWORD env vars

Technical Analysis

The installation instruction retrieves the latest available releases of instagrapi, pillow, and their transitive dependencies without version constraints or integrity hashes. The resulting installation is not reproducible and can change after the Skill has been audited.

These packages execute in a process that handles Instagram credentials, session state, and user-selected media. A compromised release, malicious transitive dependency, or unexpected incompatible update would therefore execute in a sensitive context.

Attack Path

  1. An operator follows the documented pip3 install instagrapi pillow instruction.
  2. The package resolver selects whatever versions are current at installation time.
  3. A compromised or unexpectedly changed package is downloaded and installed.
  4. Package installation hooks or imported runtime code execute locally.
  5. The dependency gains access to the posting process's credentials, files, session state, and network permissions.

Impact Assessment

A compromised dependency could steal Instagram credentials or session tokens, alter uploaded content, access local files, or execute arbitrary code with the installing or runtime user's privileges. Unpinned versions also create availability and compatibility risks even in the absence of malicious package behavior.

Remediation
View remediation

Remediation Suggestions

Use a reviewed, reproducible dependency specification:

  • Pin exact direct and transitive dependency versions.
  • Generate and verify cryptographic hashes, for example with pip-tools and pip install --require-hashes.
  • Install packages in a dedicated virtual environment rather than the global Python environment.
  • Use the official package index over TLS and avoid unreviewed alternate indexes.
  • Run dependency vulnerability and provenance checks during release preparation.
  • Periodically update pins through a controlled review and testing process.
  • Execute the posting component with the minimum filesystem and network permissions required.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (16)

Tainted flow: 'req' from os.environ.get (line 42, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/gen_image.py (reported line 53)May include surrounding context.

python
print(f"Generating image ({size})...")
try:
    resp = urllib.request.urlopen(req, timeout=120)
    result = json.loads(resp.read())
    b64 = result["data"][0]["b64_json"]
    with open(output, "wb") as f:

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description promises a broader end-to-end social content workflow: discovering trending topics, creating branded/editorial social graphics, and publishing to X/Twitter and Instagram. The actual code chunk is much narrower: it accepts a prompt, calls OpenAI's image generation API, decodes the returned base64 image, and writes it to a local file. It does not fetch trends, interact with any social platforms, or implement any posting logic. While image generation is consistent with part of the description, the primary described workflow is only partially implemented in this chunk, and important claimed capabilities are absent. This is a material description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The code chunk only implements Instagram posting. It does not discover trending topics, generate editorial graphics, apply photographic backgrounds/overlays/typography, or post to X/Twitter as claimed. It also relies on direct Instagram authentication via IG_USERNAME/IG_PASSWORD and stores a session file, which is a meaningful resource/access behavior absent from the declared permissions. While Instagram posting is part of the description, the primary declared scope is broader than what the code actually does, and several advertised capabilities are missing.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description suggests a multi-step social publishing skill: discover trends, create editorial graphics, and publish to X/Twitter and Instagram. The actual code chunk only performs Instagram-focused search through Brave Search, requiring a Brave API key from environment/config and outputting results to stdout. This is a materially different primary purpose and omits the core advertised capabilities of image generation and social posting. While 'finding trending topics' is loosely adjacent to search, this script does not actually analyze or determine trends; it simply searches Instagram pages. Therefore the description does not accurately represent the code's behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The code materially implements only the 'find trending topics/high-engagement content' portion of the description. It contains search, filtering, ranking, and output logic for X and Instagram discovery, plus a trending mode for predefined X queries. There is no code for generating images, applying visual styles, composing editorial graphics, or publishing content to X/Twitter or Instagram. Because major declared capabilities are absent from the actual behavior, the description does not accurately represent this code chunk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill documents use of environment variables, networked APIs, and account-authenticated CLIs, but it does not declare an explicit tool scope or permissions boundary. That makes the operational surface larger and less auditable, increasing the chance an agent can access secrets or perform networked actions without clear user awareness.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill instructs users to place sensitive API keys and social account credentials in environment variables without guidance on secure storage, rotation, or least-privilege handling. In agentic environments, environment variables are frequently exposed to subprocesses, logs, crash reports, or unrelated tools, raising the risk of credential leakage and account compromise.

Content

No source excerpt is available for this finding.

Behavior Manipulation

Medium
Category
Prompt Injection
Confidence
70% confidence
Finding

Subtle instructions detected that may alter agent decision-making or introduce hidden biases.

Content

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

md
1. **NEVER just put text on a solid dark background** — it looks flat and amateur
2. **ALWAYS use a photographic/cinematic background** — real scenes, real subjects
3. **ALWAYS use dark gradient overlay** on the lower 40% for text readability
4. **Keep subject visible** in the top 60% — face, setting, context
5. **Text lives in the bottom 40% only** — never cover the subject
6. **Use bold condensed typography** (Anton-style) — not regular weight fonts

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill provides concrete commands that can publish directly to real X/Twitter and Instagram accounts, but it does not prominently warn that these are live external actions. In an agent setting, that can cause accidental posting, reputational harm, spam, or disclosure of sensitive content if commands are executed without explicit confirmation.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/gen_image.py (reported line 43)May include surrounding context.

python
}).encode()

req = urllib.request.Request(
    "https://api.openai.com/v1/images/generations",
    data=data,
    headers={
        "Content-Type": "application/json",

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script dynamically constructs Python source code containing user-controlled values and executes it with python3 -c via a shell command. Although it attempts quoting, this pattern is fragile and can lead to command injection or code execution if escaping fails on edge cases, while also embedding credentials directly into generated code.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The manifest describes posting to Instagram and X/Twitter without paid APIs, but does not indicate that the skill will collect account credentials directly from environment variables or CLI arguments. Handling raw usernames and passwords is a materially different capability than using official APIs or delegated auth, and it expands the trust required of the skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script performs real external side effects—logging into Instagram, saving a reusable session, and publishing content—immediately when invoked, without any confirmation, dry-run mode, or explicit warning at execution time. In agent or automation contexts, this increases the risk of unintended account actions, accidental posting, and persistent authenticated state being left behind.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The manifest describes a skill for finding trending topics, creating social graphics, and posting to social platforms, but does not mention credential discovery from local environment variables or unrelated local application config files. While network search itself is expected, probing local config and environment for secrets is an additional capability that goes beyond the stated user-facing purpose.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The top-level documentation presents the script as a posting utility, but its actual behavior includes storing and reusing authentication session settings in ~/.openclaw/ig_session.json. Session persistence is not an obvious posting detail from the documentation because it creates local state and retains authentication material beyond a single run.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The call to toLocaleDateString uses the hard-coded locale 'en-GB', which imposes a specific language/region format on all users. This is a natural-language/locale policy issue because the script does not offer a user opt-in or explain why UK English formatting is required.

Content

No source excerpt is available for this finding.