Back to skill

Security audit

postnext-social-manager

Security checks for vulnerabilities and agentic risk

Overview

This skill is coherent for managing PostNext social accounts, but it needs review because its raw curl instructions can change real public social content without the helper's enforced approval gate.

Install only if you are comfortable giving this skill an API key that can act on real PostNext-connected social accounts. Prefer the bundled postnext helper and require an exact preview before publishing, scheduling, cancelling, deleting, or uploading; avoid using the raw curl mutating examples unless you manually verify the final provider, channel, content, media, target id, and time.

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

T09 · Insecure Skill Coding Practices

Warning
Location
references/posts.md:82
Finding

Mutating Raw Curl Workflow Bypasses the Enforced User-Approval Gate

Content
View full analysis

Vulnerability Details

File Location: references/posts.md, lines 82–87
Vulnerability Type: Missing technical enforcement of approval for a destructive API operation
Risk Level: Medium

Vulnerable Code

bash
# publish now
curl -sS -X POST https://api-app.postnext.io/api/posts/publish \
  -H "x-api-key: $POSTNEXT_API_KEY" -H 'Content-Type: application/json' \
  -d '{"providers":{"twitter":{"channelName":"@brand","providerId":"tw_123",
       "content":{"text":"hi","media":[{"url":"https://cdn/x.png","type":"IMAGE"}]}}}}'

Technical Analysis

The Skill requires publishing, scheduling, cancellation, deletion, and upload operations to be previewed and explicitly approved. The bundled postnext helper enforces this requirement with an operation-bound confirmation code. However, the Skill also permits Bash(curl:*) and presents raw curl as a supported alternative when the helper is unavailable.

The documented command above directly sends an authenticated request to /api/posts/publish. It contains no confirmation parameter, approval token, dry-run mode, or other technical mechanism binding the exact provider, channel, text, and media to prior user approval.

Consequently, the raw-curl execution path bypasses the helper's confirmation gate. A textual instruction elsewhere in the documentation to obtain approval does not technically prevent an Agent from immediately executing this command.

Attack Path

  1. The user requests that the Agent draft or prepare a social-media post.
  2. The Agent follows the documented raw-curl workflow rather than invoking the gated postnext helper.
  3. The Agent constructs a request body containing the selected provider, account identifier, post text, and media.
  4. Before obtaining explicit approval for that exact content, the Agent executes the documented authenticated POST /api/posts/publish request.
  5. PostNext accepts the request under POSTNEXT_API_KEY and publishes the content to the connected ...[truncated 702 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove mutating raw-curl recipes from Agent-executable instructions and require all publish, schedule, cancel, delete, and upload operations to use the gated postnext helper.
  2. Remove or narrow Bash(curl:*) from allowed-tools if direct authenticated API calls are not essential.
  3. If raw curl must remain supported, add a separate approval helper that:
    • Produces a canonical preview of the exact operation.
    • Hashes the provider, channel, content, media, schedule, and target identifier.
    • Issues a short-lived, operation-bound confirmation token.
    • Refuses to generate or execute the mutating curl command unless that token matches.
  4. Keep read-only curl examples separate from mutating examples so an Agent cannot mistake a direct publishing command for a safe preparation step.
  5. Add tests covering the raw API workflow and verify that no account-changing request can be sent before approval of the exact operation.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (12)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: Bash(./postnext:*), Bash(curl:*), Bash(jq:*), Read

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: Bash(./postnext:*), Bash(curl:*), Bash(jq:*), Read

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'shell' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · postnext (reported line 77)May include surrounding context.

text
esac
    rm -f "$tmp"; die "HTTP $code: $msg"
  fi
  cat "$tmp"; rm -f "$tmp"
}

# unwrap: read stdin, return .data if the {success,data} envelope is present, else the body as-is

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% 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 · postnext (reported line 276)May include surrounding context.

text
cmd_delete() {
  id_and_confirm "postnext delete <groupId> [--confirm CODE]" "$@"
  gate "$(jq -n --arg id "$ID" '{op:"delete", groupId:$id}')" "$CONFIRM"
  api DELETE "/api/posts/$ID" | jq '.data'
}

cmd_analytics() {

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
88% confidence
Finding

This documentation exposes destructive endpoints for publish, schedule, cancel, and delete operations against real social media accounts. Although the file includes safety warnings, an agent that follows the raw endpoint guidance without robust approval/state validation could be manipulated into deleting content, cancelling scheduled posts, or causing duplicate/double publishing, making this a real tool-parameter abuse risk in an agentic context.

Content

Scanner excerpt · references/posts.md (reported line 36)May include surrounding context.

md
| Publish immediately | `POST /api/posts/publish` |
| Schedule | `POST /api/posts/schedule` with `"scheduledAt": "<future ISO8601>"` |

Existing post by id: `POST /api/posts/{postId}/publish`, `POST /api/posts/{postId}/schedule`, `POST /api/posts/{postId}/cancel-schedule` (back to draft), `DELETE /api/posts/{groupId}` (removes from PostNext; does not delete an already-published post from the platform).

> Safety: every call in this section changes the user's account. Before any publish, schedule, cancel or delete, show the user the exact provider, channel, text, media, time and post id, and wait for their explicit yes. The `postnext` helper enforces this with a preview and a `--confirm` code; with raw curl it is on you.

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 · postnext (reported line 23)May include surrounding context.

text
# valid_id VALUE -> dies unless VALUE is a plain token (no slash, dot, ?, #, space) so it cannot rewrite the request path
valid_id() { case "$1" in ''|*[!A-Za-z0-9_-]*) die "invalid id: $1";; esac; }
[ -n "${POSTNEXT_API_KEY:-}" ] || die "set POSTNEXT_API_KEY (create one at https://postnext.io/account/api-keys)"
case "$POSTNEXT_API_KEY" in *[!A-Za-z0-9_.-]*) die "POSTNEXT_API_KEY contains unexpected characters";; esac

# kcurl ARGS... -> curl with the key header fed on stdin, so the key never appears in the process list.

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 · postnext (reported line 59)May include surrounding context.

text
local tmp code
  tmp="$(mktemp)"
  if [ -n "$body" ]; then
    code="$(kcurl -sS -o "$tmp" -w '%{http_code}' -X "$method" "$BASE$path" \
      -H 'Content-Type: application/json' -d "$body")"
  else
    code="$(kcurl -sS -o "$tmp" -w '%{http_code}' -X "$method" "$BASE$path")"

External Transmission

Medium
Category
Data Exfiltration
Confidence
63% confidence
Finding

The upload flow sends local file contents to a presigned URL returned by the remote API, and the script only checks that the URL uses HTTPS. If the upstream API is compromised or malicious, it could return an arbitrary HTTPS destination and cause local file contents to be exfiltrated to an attacker-controlled host during upload.

Content

Scanner excerpt · postnext (reported line 139)May include surrounding context.

text
upl_url="$(echo "$init" | jq -r '.data.uploadUrl')"
    case "$upl_url" in https://*) ;; *) die "refusing non-https upload URL";; esac
    # PUT the bytes; Content-Type MUST match the signed contentType or S3 rejects the signature
    curl -sS -X PUT "$upl_url" -H "Content-Type: $mime" --data-binary "@$file" >/dev/null \
      || die "S3 upload PUT failed"
    api POST /api/assets/upload/complete "$(jq -n --arg u "$upl_id" '{uploadId:$u}')" \
      | jq -r '.data.url'

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/media.md (reported line 22)May include surrounding context.

bash
BASE=https://api-app.postnext.io
# 1. request an upload URL (declares type + exact byte size; pre-charges storage quota)
INIT=$(curl -sS -X POST $BASE/api/assets/upload/create-url \
  -H "x-api-key: $POSTNEXT_API_KEY" -H 'Content-Type: application/json' \
  -d '{"filename":"hero.png","contentType":"image/png","sizeBytes":48213}')
UPLOAD_URL=$(echo "$INIT" | jq -r .data.uploadUrl)

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/media.md (reported line 29)May include surrounding context.

md
UPLOAD_ID=$(echo "$INIT" | jq -r .data.uploadId)

# 2. PUT the bytes. Content-Type MUST equal the declared contentType or S3 rejects the signature.
curl -sS -X PUT "$UPLOAD_URL" -H 'Content-Type: image/png' --data-binary @hero.png

# 3. finalize -> returns the asset; use .data.url in the post
curl -sS -X POST $BASE/api/assets/upload/complete \

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/posts.md (reported line 80)May include surrounding context.

Idempotency: raw POST /api/posts/{postId}/schedule will create a duplicate job if called twice, causing a double-publish. Before re-scheduling, list the post's current state and confirm it is not already scheduled. The postnext helper refuses past times, and its --confirm code covers one exact operation, but it does not detect an existing job for the same post.

Raw curl

bash
# publish now

Static analysis

No suspicious patterns detected.