Back to skill

Security audit

Posta

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly matches its social-media posting purpose, but its credential handling, public-posting defaults, and temporary file storage need careful review before installation.

Review before installing. Prefer POSTA_API_TOKEN over email/password, avoid putting Posta or fal credentials in project .env files, do not set POSTA_BASE_URL except for trusted development use, clear /tmp/.posta_token after use, and require explicit confirmation for publish, schedule, delete, and TikTok privacy choices. Do not send confidential prompts or unreleased campaign content to fal.ai unless that external sharing is acceptable.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/posta-api.sh:12
Finding

Configurable API Origin Can Exfiltrate Posta Credentials and Bearer Tokens

Content
View full analysis
&2 echo "Searched: env vars, ~/.zshrc, ~/.bashrc, .env files, ~/.posta/credentials" >&2 return 1 fi local response response=$(curl -sf -X POST "${POSTA_BASE_URL}/auth/login" \ -H "Content-Type: application/json" \ -d "{\"email\": \"${POSTA_EMAIL}\", \"password\": \"${POSTA_PASSWORD}\"}") ``` ```bash posta_api() { local method="$1" local endpoint="$2" local body="${3:-}" local token local tmpfile="/tmp/.posta_response_$$" token=$(posta_get_token) local args=( -s -X "$method" -H "Authorization: Bearer ${token}" -H "Content-Type: application/json" -o "$tmpfile" -w "%{http_code}" ) if [[ -n "$body" ]]; then args+=(-d "$body") fi local http_code http_code=$(curl "${args[@]}" "${POSTA_BASE_URL}${endpoint}") ``` ### Technical Analysis `POSTA_BASE_URL` is accepted directly from the process environment without validating its scheme or host. Both legacy Posta email/password credentials and bearer tokens are subsequently transmitted to that destination. The override may be useful for development, but allowing an arbitrary origin in the normal authentication path exceeds the minimum privilege required by the production Skill. In particular, the implementation does not require HTTPS and does not restrict the host to the documented `api.getposta.app` service. This is not an unexplained network transmission: authentication and API calls are necessary for the Skill. The vulnerability is that the security-sensitive destination can be changed without a separate, explicit de ...[truncated 1025 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/posta-api.sh:13
Finding

Predictable Shared Temporary Files Expose JWTs and Private API Responses

Content
View full analysis
"$POSTA_TOKEN_FILE" echo "$token" } posta_get_token() { # If POSTA_API_TOKEN is set, use it directly (no login needed) if [[ -n "${POSTA_API_TOKEN:-}" ]]; then printf '%s' "$POSTA_API_TOKEN" return 0 fi # Return cached token if it exists and is non-empty if [[ -f "$POSTA_TOKEN_FILE" ]]; then local token token=$(cat "$POSTA_TOKEN_FILE") if [[ -n "$token" ]]; then printf '%s' "$token" return 0 fi fi ``` ```bash posta_api() { local method="$1" local endpoint="$2" local body="${3:-}" local token local tmpfile="/tmp/.posta_response_$$" token=$(posta_get_token) local args=( -s -X "$method" -H "Authorization: Bearer ${token}" -H "Content-Type: application/json" -o "$tmpfile" -w "%{http_code}" ) if [[ -n "$body" ]]; then args+=(-d "$body") fi local http_code http_code=$(curl "${args[@]}" "${POSTA_BASE_URL}${endpoint}") # If 401, handle based on token type if [[ "$http_code" == "401" ]]; then if [[ -n "${POSTA_API_TOKEN:-}" ]]; then echo "ERROR: API token is invalid or revoked. Generate a new one at your Posta dashboard." >&2 rm -f "$tmpfile" return 1 fi # JWT flow: re-login and retry once rm -f "$POSTA_TOKEN_FILE" token=$(posta_login) args[4]="Authorization: Bearer ${token}" # index 4 = the Authorization header value http_code=$(curl "${args[@]}" "${POSTA_BASE_URL}${endpoint}") fi if [[ "$http_code" -ge 400 ]]; then echo "ERROR: API returned HTTP ${http_code}" >&2 cat "$tmpfile" >&2 rm -f "$tmpfile" return 1 fi posta_sanitize_json "$tmpfile" > /tmp/.posta_last_response cat /tmp ...[truncated 2294 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/posta-api.sh:328
Finding

Remote Media URL Validation Is Vulnerable to SSRF Bypass

Content
View full analysis
&2 return 1 fi # Block private/internal IPs local host host=$(echo "$url" | sed -E 's|^https://([^/:]+).*|\1|') if [[ "$host" =~ ^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|127\.|0\.|localhost|metadata\.google) ]]; then echo "ERROR: URLs pointing to private/internal networks are not allowed." >&2 return 1 fi # Determine extension from mime type (or URL) local ext="" if [[ -n "$mime_type" ]]; then case "$mime_type" in image/png) ext=".png" ;; image/jpeg) ext=".jpg" ;; image/webp) ext=".webp" ;; image/gif) ext=".gif" ;; video/mp4) ext=".mp4" ;; video/quicktime) ext=".mov" ;; video/webm) ext=".webm" ;; audio/mpeg) ext=".mp3" ;; audio/wav) ext=".wav" ;; audio/mp4) ext=".m4a" ;; audio/webm) ext=".webm" ;; *) ext="" ;; esac else # Try to infer from URL path local url_ext="${url##*.}" url_ext=$(echo "$url_ext" | tr '[:upper:]' '[:lower:]' | sed 's/[?#].*//') case "$url_ext" in jpg|jpeg|png|webp|gif|mp4|mov|webm|mp3|wav|m4a) ext=".${url_ext}" ;; esac fi local tmpfile="/tmp/posta_upload_${RANDOM}${ext}" # Download file curl -sf -o "$tmpfile" "$url" ``` ### Technical Analysis The function attempts to prevent SSRF by requiring an `https://` prefix and comparing the textual hostname against a small regular expressi ...[truncated 2016 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (34)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is for a broad social media automation and content-generation skill. The provided code chunk only implements a local JSON sanitization helper that reads an input file and normalizes JSON output. It does not interact with any social platforms, user accounts, media files, analytics services, or AI generation systems. This is a materially different primary purpose rather than a mere supporting detail, so the description does not accurately represent the supplied code chunk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The instruction to always set TikTok privacy to PUBLIC_TO_EVERYONE unless the user specifies otherwise creates a default-public posting behavior without affirmative user opt-in. In this skill's context, that can cause unintended broad disclosure of content, including sensitive or unreleased material, directly to a public social platform.

Content

No source excerpt is available for this finding.

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 · references/posta-api-reference.md (reported line 12)May include surrounding context.

Authentication

POST /auth/login

Login and get access token.

Body:

json

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 · references/posta-api-reference.md (reported line 36)May include surrounding context.

Authentication

POST /auth/login

Login and get access token.

Body:

json

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

The script automatically reads secrets from project-local .env files when sourced, which can expose unrelated credentials from the current working directory to the skill. In an agent context, this is more dangerous because the helper is designed to auto-discover and export secrets without an explicit per-file consent step, increasing the risk of over-collection from arbitrary repositories.

Content

Scanner excerpt · scripts/posta-api.sh (reported line 40)May include surrounding context.

sh
# Only dedicated config files are checked — shell profiles are NOT read.
_POSTA_CREDENTIAL_SOURCES=(
  "$HOME/.posta/credentials"   # dedicated Posta config (preferred)
  ".env"                       # project dotenv
  ".env.local"                 # project dotenv (local override)
  ".env.production"            # project dotenv (production)
)

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

Automatically harvesting credentials from .env.local broadens the attack surface to developer-local secrets that may belong to other services. In an AI skill, sourcing the script can silently ingest sensitive material from the user's repository context, making this more dangerous than a normal CLI helper.

Content

Scanner excerpt · scripts/posta-api.sh (reported line 41)May include surrounding context.

sh
_POSTA_CREDENTIAL_SOURCES=(
  "$HOME/.posta/credentials"   # dedicated Posta config (preferred)
  ".env"                       # project dotenv
  ".env.local"                 # project dotenv (local override)
  ".env.production"            # project dotenv (production)
)

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Reading .env.production is a particularly sensitive pattern because production dotenv files often contain high-value credentials unrelated to this tool. Auto-discovery from the current project directory can cause unnecessary secret access in agent workflows, violating least privilege.

Content

Scanner excerpt · scripts/posta-api.sh (reported line 42)May include surrounding context.

sh
"$HOME/.posta/credentials"   # dedicated Posta config (preferred)
  ".env"                       # project dotenv
  ".env.local"                 # project dotenv (local override)
  ".env.production"            # project dotenv (production)
)

# Exact variable names the skill will search for — nothing else is read.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/posta-api.sh (reported line 132)May include surrounding context.

sh
posta_login() {
  if [[ -z "${POSTA_EMAIL:-}" || -z "${POSTA_PASSWORD:-}" ]]; then
    echo "ERROR: POSTA_EMAIL and POSTA_PASSWORD must be set" >&2
    echo "Searched: env vars, ~/.zshrc, ~/.bashrc, .env files, ~/.posta/credentials" >&2
    return 1
  fi

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/posta-api.sh (reported line 527)May include surrounding context.

sh
posta_delete_post() {
  local post_id="$1"
  posta_api DELETE "/posts/${post_id}"
}

posta_cancel_post() {

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/posta-api.sh (reported line 578)May include surrounding context.

sh
posta_delete_media() {
  local media_id="$1"
  posta_api DELETE "/media/${media_id}"
}

posta_generate_carousel_pdf() {

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill declares shell and environment-based capabilities but does not constrain them with explicit tool scopes or allowed-tools. In a skill that can access API tokens, local files, and external endpoints, missing scope boundaries increases the blast radius of prompt injection or accidental misuse because the agent may invoke broader shell/env access than intended.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

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

md
---
name: posta
description: Post to Instagram, TikTok, LinkedIn, YouTube, X/Twitter, Facebook, Pinterest, Threads and Bluesky from your terminal. Create posts with AI-generated images and captions, upload media, schedule or publish instantly, view analytics, and manage all your social accounts — without leaving your editor. Use this skill when the user wants to create social media content, generate images/videos/text with AI, upload media, create posts, schedule or publish posts, view analytics, compare post performance, or manage social accounts through Posta.
license: MIT
homepage: https://github.com/STGime/posta-skill
metadata:

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation text is very broad and can match a large range of ordinary requests involving social media, AI content, analytics, or account management. Over-broad activation increases the chance the skill is invoked in contexts where the user did not intend external posting, credential use, or third-party API interaction, making downstream risky actions more likely.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

The skill is designed to communicate with external services, including the Posta API and fal.ai, using discovered credentials from environment files. This is not inherently malicious, but it is a genuine data egress boundary: account metadata, media, analytics, and tokens may be transmitted off-host, and the skill context increases risk because it interacts with social accounts and content that may be business-sensitive.

Content

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

md
### Optional Environment Variables

- `POSTA_BASE_URL` — API base URL (default: `https://api.getposta.app/v1`)
- `FAL_KEY` — fal.ai API key (for image generation). Format is `<key_id>:<key_secret>`. Get one at https://fal.ai/dashboard/keys. The skill auto-discovers this from env vars, `~/.posta/credentials`, or `.env` files.

> Captions and hashtags are written by Claude directly — no text-generation API key is needed. The only external content service is the image generator (fal.ai).

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

This workflow sends user-supplied prompts and the FAL_KEY credential to an external fal.ai endpoint for image generation. External transmission is expected for the feature, but it still creates confidentiality and billing risk because prompts may contain sensitive content and the API key can be abused if mishandled; the skill context makes this more sensitive because it also recommends spending credits and generating publishable content.

Content

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

Generate an image with fal.ai (FLUX):

bash
# fal returns a hosted image URL (JSON), not raw bytes
RESULT=$(curl -s -X POST "https://fal.run/fal-ai/flux/schnell" \
  -H "Authorization: Key ${FAL_KEY}" \
  -H "Content-Type: application/json" \
  -d '{

Session Persistence

Medium
Category
Rogue Agent
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.

Content

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

md
6. **Use appropriate aspect ratios.** Match the content format to the target platform — portrait for TikTok/Reels, square for Instagram feed, landscape for LinkedIn/X.

7. **Create posts as drafts first.** Always set `isDraft: true` when creating posts, then schedule or publish after user confirmation.

8. **Combine media types strategically.** For maximum reach, generate both an image (for Instagram/LinkedIn) and a video (for TikTok/Reels) from the same content.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The manifest says the skill should be used to create social media content, including AI-generated images, through Posta, but this example instructs the agent to call fal.ai directly with curl and a FAL_KEY. Directly integrating an external image-generation service and handling separate credentials is not obviously required by the documented Posta skill itself and introduces a capability outside the core social-posting/account-management context.

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 · examples/workflows.md (reported line 92)May include surrounding context.

md
source "${POSTA_SKILL_ROOT:-${OPENCLAW_SKILL_ROOT:-${CLAUDE_PLUGIN_ROOT:-}}}/skills/posta/scripts/posta-api.sh"

# Generate image with fal.ai — returns a hosted URL, not raw bytes
RESULT=$(curl -s -X POST "https://fal.run/fal-ai/flux/schnell" \
  -H "Authorization: Key ${FAL_KEY}" \
  -H "Content-Type: application/json" \
  -d '{

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The example includes a destructive media deletion command with no confirmation, preview, or verification that the target media is actually safe to remove. In an agent-assisted workflow, this raises the chance of accidental data loss because an LLM or user could invoke deletion on the wrong identifier without an explicit guardrail.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · references/content-generation.md (reported line 11)May include surrounding context.

md
**Required:** `FAL_KEY` environment variable.

- **Get a key:** Sign up at https://fal.ai and create a key at https://fal.ai/dashboard/keys
- **Key format:** `<key_id>:<key_secret>` (contains a colon)
- **Auth header:** `Authorization: Key ${FAL_KEY}`
- **Auto-discovery:** The skill searches env vars, `~/.posta/credentials`, and `.env` files (dedicated config only — shell profiles are never read)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The example sends user-supplied prompts and an API credential to a third-party image generation service without clearly warning that prompt contents leave the local environment. In a social-posting skill, prompts may contain unpublished campaign details, sensitive brand material, or personal data, so the omission creates a real privacy and compliance risk even if the transmission is intentional.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

This command transmits prompt data and an authorization key to an external service. That is expected for the feature, but without explicit data-sharing notice and input hygiene guidance, users may unknowingly send sensitive content or mishandle credentials.

Content

Scanner excerpt · references/content-generation.md (reported line 26)May include surrounding context.

Request

bash
RESULT=$(curl -s -X POST "https://fal.run/fal-ai/flux/schnell" \
  -H "Authorization: Key ${FAL_KEY}" \
  -H "Content-Type: application/json" \
  -d '{

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The workflow creates a post with "isDraft": false and a scheduled publish time, but does not clearly warn that this can create a live post on connected accounts. In a multi-account social publishing skill, unclear guidance around live publishing increases the chance of unintended publication, reputational harm, and accidental posting to the wrong accounts.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

The combined workflow repeats the external transmission pattern in a more automated end-to-end flow, increasing the chance that users copy and run it without noticing that data is being sent off-box. Because it is embedded in a publish workflow, the risk is amplified by automation and reduced user scrutiny.

Content

Scanner excerpt · references/content-generation.md (reported line 84)May include surrounding context.

md
source "${POSTA_SKILL_ROOT:-${OPENCLAW_SKILL_ROOT:-${CLAUDE_PLUGIN_ROOT:-}}}/skills/posta/scripts/posta-api.sh"

# 1. Generate image with fal.ai (FLUX)
RESULT=$(curl -s -X POST "https://fal.run/fal-ai/flux/schnell" \
  -H "Authorization: Key ${FAL_KEY}" \
  -H "Content-Type: application/json" \
  -d '{

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 · references/posta-api-reference.md (reported line 3)May include surrounding context.

md
set -euo pipefail

POSTA_BASE_URL="${POSTA_BASE_URL:-https://api.getposta.app/v1}"
POSTA_TOKEN_FILE="/tmp/.posta_token"

# ─── JSON Parsing Helper ─────────────────────────────────────────────────────

Static analysis

No suspicious patterns detected.