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## 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
## 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## 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
## 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## 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
## 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## 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
## 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## 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
## 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
Content
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:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

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.

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.

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.

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.

Lp3

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.

Missing User Warnings

Medium
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.

Behavior Manipulation

Medium
Category
Prompt Injection
Content
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
Confidence
70% confidence
Finding
Subtle instructions detected that may alter agent decision-making or introduce hidden biases.

Missing User Warnings

Medium
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.

External Transmission

Medium
Category
Data Exfiltration
Content
}).encode()

req = urllib.request.Request(
    "https://api.openai.com/v1/images/generations",
    data=data,
    headers={
        "Content-Type": "application/json",
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Context-Inappropriate Capability

Medium
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.

Context-Inappropriate Capability

Medium
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.

Missing User Warnings

Medium
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.

Context-Inappropriate Capability

Medium
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.

Description-Behavior Mismatch

Low
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.

Natural-Language Policy Violations

Low
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.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/instagram-post.js:120

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/viral-search.js:68