Back to skill

Security audit

Viraloop

Security checks for vulnerabilities and agentic risk

Overview

The skill honestly describes a social-media automation pipeline, but it gives the agent too much autonomous power to publish publicly, reschedule itself, and process arbitrary websites without enough safeguards.

Install only if you are comfortable with an agent posting live content to your TikTok and Instagram accounts. Use dedicated, low-privilege API tokens, review generated content before publishing, avoid letting it modify cron or other schedules automatically, and analyze only public sites you trust or control until URL validation and the eval-based publisher are fixed.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (5)

T06 · System Persistence

Error
Location
SKILL.md:103
Finding
Autonomous Cross-Session Scheduling Creates System Persistence<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:103` and `SKILL.md:291-310` **Vulnerability Type**: Unauthorized creation or modification of recurring scheduled execution **Risk Level**: Critical ### Vulnerable Code Snippet ```markdown **Agent Execution Schedule:** The agent shouldn't just run at a random time. It should read `learnings.json`, look at the `bestTimes` array, and **automatically adjust its own cron/automation schedule** so that tomorrow's execution happens right at the optimal publishing time. ``` The daily workflow reinforces this instruction: ```bash # STEP 0: Learn from previous posts (skip on first run) UPLOADPOST_TOKEN="..." UPLOADPOST_USER="myuser" bash {baseDir}/scripts/check-analytics.sh 7 node {baseDir}/scripts/learn-from-analytics.js # → Agent reads learnings.json and picks the best hook style # → CRITICAL: Agent checks bestTimes and schedules ITS OWN NEXT EXECUTION for that exact hour tomorrow # STEP 1: Research business node {baseDir}/scripts/analyze-web.js https://my-product.com # STEP 2: Generate slides (using insights from learnings) GEMINI_API_KEY="..." bash {baseDir}/scripts/generate-slides.sh # STEP 3: Review with vision → auto-fix broken slides # Agent checks each slide, regenerates any that fail # STEP 4: Publish UPLOADPOST_TOKEN="..." UPLOADPOST_USER="myuser" bash {baseDir}/scripts/publish-carousel.sh ``` ### Technical Analysis The Skill explicitly directs the Agent to modify its cron or automation schedule so the workflow executes again in future sessions. This is not merely a recommendation that the user configure an external scheduler; it instructs the Agent to alter a persistent execution mechanism itself. The package does not provide: - A bounded scheduler installation procedure. - A required user-confirmation step. - A mechanism for inspecting the resulting scheduled task. - An expiration date or maximum execution count. - Documented disable and removal procedures. - Isolation or reduced privi ...[truncated 1377 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove all instructions directing the Agent to modify its own cron, startup, or automation configuration. 2. Make scheduling an optional, user-managed deployment step outside the normal Skill workflow. 3. Require explicit confirmation before creating any scheduled task, displaying: - The exact command. - Execution frequency. - Credential requirements. - Output and log locations. - Expiration or maximum run count. 4. Provide documented inspection, disable, and removal commands. 5. Use a dedicated least-privileged service account and narrowly scoped API credentials for scheduled execution. 6. Require confirmation before every public publication, even when content generation is scheduled. 7. Prefer generating a sample scheduler configuration for user review rather than installing or modifying it automatically. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/publish-carousel.sh:35
Finding
Website-Derived Content Can Trigger Shell Command Injection Through eval<![CDATA[ ## Vulnerability Details **File Location**: `scripts/publish-carousel.sh:35-88` **Vulnerability Type**: Shell command injection through dynamic command construction and `eval` **Risk Level**: Critical ### Vulnerable Code Snippet ```bash # Load caption if [ -f "$CAPTION_FILE" ]; then CAPTION=$(cat "$CAPTION_FILE") else CAPTION="Check this out! 🔥 #viral #fyp" fi # Caption para Instagram (max 2200 chars) CAPTION_TRUNCATED=$(echo "$CAPTION" | head -c 2000) # TikTok title (max 90 chars) - first line + hashtags TIKTOK_TITLE=$(echo "$CAPTION" | head -1 | head -c 60) TIKTOK_TITLE="$TIKTOK_TITLE #viral #fyp" ``` ```bash # Create command CMD="curl -s -X POST '$UPLOADPOST_URL/api/upload_photos'" CMD="$CMD -H 'Authorization: Apikey $UPLOADPOST_TOKEN'" CMD="$CMD -F 'user=$DEFAULT_USER'" CMD="$CMD -F 'platform[]=tiktok'" CMD="$CMD -F 'platform[]=instagram'" CMD="$CMD -F 'title=$CAPTION_TRUNCATED'" CMD="$CMD -F 'tiktok_title=$TIKTOK_TITLE'" CMD="$CMD -F 'auto_add_music=true'" CMD="$CMD -F 'privacy_level=PUBLIC_TO_EVERYONE'" CMD="$CMD -F 'media_type=IMAGE'" CMD="$CMD -F 'async_upload=true'" # Add photos for slide in $SLIDES; do CMD="$CMD -F 'photos[]=@$slide'" done # Execute RESPONSE=$(eval $CMD) ``` ### Technical Analysis The script constructs a shell program as a string and executes it with `eval`. Values including `CAPTION_TRUNCATED`, `TIKTOK_TITLE`, `DEFAULT_USER`, slide paths, and the API token are directly interpolated into that string. Single quotes embedded in the caption or username are not escaped. An attacker can terminate the intended quoted `curl -F` argument and append shell operators or commands. When `eval` reparses the resulting string, those commands execute with the privileges and environment of the publishing process. The caption is especially dangerous because it is generated from data extracted from an arbitrary website. Website-derived taglines, features, hooks, and calls to action flow through `analysis.json` into `capti ...[truncated 1706 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `eval` and never construct a shell command as a string. 2. Pass arguments through a Bash array so each value remains one argument: ```bash curl_args=( -s -X POST "$UPLOADPOST_URL/api/upload_photos" -H "Authorization: Apikey $UPLOADPOST_TOKEN" -F "user=$DEFAULT_USER" -F "platform[]=tiktok" -F "platform[]=instagram" -F "title=$CAPTION_TRUNCATED" -F "tiktok_title=$TIKTOK_TITLE" -F "auto_add_music=true" -F "privacy_level=PUBLIC_TO_EVERYONE" -F "media_type=IMAGE" -F "async_upload=true" ) for slide in "${slides[@]}"; do curl_args+=(-F "photos[]=@$slide") done RESPONSE=$(curl "${curl_args[@]}") ``` 3. Store slide paths in an array rather than a whitespace-delimited string. 4. Validate `UPLOADPOST_USER` against the exact username grammar accepted by the API. 5. Treat website-derived text as untrusted throughout the pipeline. 6. Add tests containing quotes, command substitutions, semicolons, newlines, and shell metacharacters. 7. Run publication under a restricted account with a minimal environment and narrowly scoped credentials. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/analyze-web.js:48
Finding
Unrestricted URL and Discovered-Link Navigation Enables SSRF<![CDATA[ ## Vulnerability Details **File Location**: `scripts/analyze-web.js:48`, `scripts/analyze-web.js:173-182`, and `scripts/analyze-web.js:232-235` **Vulnerability Type**: Server-side request forgery and cross-origin crawling **Risk Level**: High ### Vulnerable Code Snippet The user-supplied URL is navigated without validation: ```javascript await page.goto(url, { waitUntil: 'networkidle', timeout: 30000 }); ``` Links described as internal are selected only by substring matching: ```javascript // Important internal links const internalLinks = []; const importantPages = ['pricing', 'features', 'about', 'testimonials', 'reviews', 'customers', 'case', 'demo', 'contact']; document.querySelectorAll('a[href]').forEach(a => { const href = a.href.toLowerCase(); const text = a.textContent?.trim(); importantPages.forEach(page => { if (href.includes(page) && !internalLinks.find(l => l.url === a.href)) { internalLinks.push({ url: a.href, text, type: page }); } }); }); ``` Those discovered URLs are then visited without an origin or address check: ```javascript for (const link of homeData.internalLinks.slice(0, 5)) { try { console.log(` → ${link.type}: ${link.url.substring(0, 60)}...`); await page.goto(link.url, { waitUntil: 'domcontentloaded', timeout: 15000 }); ``` ### Technical Analysis The analyzer accepts an arbitrary URL and passes it directly to Playwright. It does not validate: - The URL scheme. - The destination hostname. - Resolved IPv4 or IPv6 addresses. - Loopback, private, link-local, multicast, or reserved ranges. - Redirect destinations. - DNS rebinding behavior. - Whether extracted links share the original website's origin. The `internalLinks` name is misleading: a link is accepted when its absolute URL contains a keyword such as `features`, `pricing`, or `about`. An attacker-controlled page can therefore include a link such as an internal service URL whose path contains one of those keywords. A headless brow ...[truncated 1944 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse every destination with the standard `URL` API and permit only `http:` and `https:`. 2. Resolve hostnames before navigation and reject: - IPv4 loopback, private, link-local, carrier-grade NAT, multicast, and reserved ranges. - IPv6 loopback, link-local, unique-local, mapped private IPv4, and reserved ranges. 3. Require every discovered navigation URL to have the same origin as the initial approved URL. 4. Revalidate every redirect destination rather than validating only the original URL. 5. Add Playwright request interception and block requests to non-approved origins and prohibited address ranges. 6. Defend against DNS rebinding by validating resolved addresses at connection time where possible. 7. Set strict limits on navigation count, response size, content type, and request duration. 8. Keep scraped content explicitly marked as untrusted and prevent it from being automatically transmitted or published. 9. Require user review before sending extracted website content to third-party services. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/generate_image.py:2
Finding
Runtime Installation of Unpinned Third-Party Dependencies<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_image.py:2-7` and `README.md:42-47` **Vulnerability Type**: Mutable and insufficiently constrained software supply chain **Risk Level**: Medium ### Vulnerable Code Snippet ```python # /// script # requires-python = ">=3.10" # dependencies = [ # "google-genai>=1.0.0", # "pillow>=10.0.0", # ] # /// ``` The documented setup also installs Playwright without a pinned package or browser version: ```markdown ## Requirements - Node.js 18+ - Playwright (`npm install playwright && npx playwright install chromium`) - uv (Python package runner) - jq ``` ### Technical Analysis The Python script is executed through `uv run` and declares dependencies using open-ended lower bounds. Any future version satisfying those constraints can be selected and installed at runtime. The project contains no reviewed lockfile or package hashes. The Playwright setup similarly installs the currently resolved package and browser artifacts without an exact version or integrity-pinned lockfile. This means the effective code executed by the Skill can change after the Skill package has been audited. This is not evidence that the named dependencies are currently malicious. The vulnerability is that routine execution and setup trust mutable upstream artifacts without reproducible dependency resolution. ### Attack Path 1. A user runs the image-generation script or follows the Playwright installation instructions. 2. The package manager resolves dependency versions available at that time. 3. A compromised, malicious, or unexpectedly incompatible future release satisfies the broad version constraint. 4. The package is downloaded and imported or its installation behavior executes. 5. The dependency gains the privileges and environment of the Agent process, including access to files and relevant API credentials. ### Impact Assessment A compromised dependency can potentially: - Execute arbitrary code under the Agen ...[truncated 373 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin exact dependency versions rather than using open-ended lower bounds. 2. Generate and commit reproducible lockfiles containing artifact hashes. 3. Pin the Playwright package and corresponding browser build. 4. Install dependencies during a controlled deployment phase rather than during routine Skill execution. 5. Use trusted registries and disable unexpected alternative package indexes. 6. Add automated vulnerability and provenance checks for Python, npm, and browser artifacts. 7. Review and test updates before changing locked versions. 8. Run dependency installation without production API credentials in the environment. 9. Consider using a prebuilt, signed container image with fixed dependency versions. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/analyze-web.js:12
Finding
Predictable Shared Temporary Directory Permits Symlink and State-Poisoning Attacks<![CDATA[ ## Vulnerability Details **File Location**: `scripts/analyze-web.js:12,30,465`; `scripts/generate-slides.sh:5`; `scripts/publish-carousel.sh:8-10`; and `scripts/check-analytics.sh:9,126-136` **Vulnerability Type**: Unsafe temporary-file handling and shared mutable state **Risk Level**: Medium ### Vulnerable Code Snippet The analyzer uses a globally predictable directory: ```javascript const CAROUSEL_DIR = '/tmp/carousel'; ``` ```javascript fs.mkdirSync(CAROUSEL_DIR, { recursive: true }); ``` ```javascript fs.writeFileSync(`${CAROUSEL_DIR}/analysis.json`, JSON.stringify(data, null, 2)); ``` Other scripts reuse fixed paths in the same directory: ```bash CAROUSEL_DIR="/tmp/carousel" CAPTION_FILE="$CAROUSEL_DIR/caption.txt" ANALYSIS_FILE="$CAROUSEL_DIR/analysis.json" ``` Analytics are also written directly to a predictable filename: ```bash SNAPSHOT_FILE="$CAROUSEL_DIR/analytics-snapshot.json" echo "{ \"timestamp\": \"$(date -Iseconds)\", \"days\": $DAYS, \"user\": \"$DEFAULT_USER\", \"profile\": $PROFILE_ANALYTICS, \"impressions\": $IMPRESSIONS }" > "$SNAPSHOT_FILE" 2>/dev/null || echo "{}" > "$SNAPSHOT_FILE" ``` ### Technical Analysis All runs use `/tmp/carousel` and fixed filenames without: - Creating a per-user or per-run private directory. - Setting a restrictive `umask`. - Checking directory ownership and permissions. - Rejecting symbolic links. - Verifying that inputs and outputs are regular files. - Using atomic file creation or replacement. - Separating concurrent runs. On a multi-user system, another local process may pre-create `/tmp/carousel`, place attacker-controlled input files there, or replace expected files with symbolic links. The Skill subsequently trusts files such as `analysis.json`, `caption.txt`, `post-info.json`, and `slide-prompts.json`. The publishing command-injection issue increases the severity of caption poisoning, but unsafe temporary storage remains independently exploitable for content manipulation ...[truncated 1249 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create a unique private working directory for each run: ```bash umask 077 CAROUSEL_DIR=$(mktemp -d "${TMPDIR:-/tmp}/viraloop.XXXXXXXX") ``` 2. For persistent state, use a user-owned application data directory with mode `0700` rather than `/tmp`. 3. Verify directory ownership and reject directories writable by unrelated users. 4. Open output files with exclusive creation and no-follow semantics where supported. 5. Reject symbolic links and verify that every input is a regular file owned by the expected user. 6. Write JSON files atomically to a temporary file in the same directory, then rename them. 7. Separate each publication by a unique job identifier. 8. Clean up ephemeral images and prompt files after use. 9. Encrypt or access-restrict retained analytics and publication metadata. 10. Add locking if concurrent executions are supported. ]]>
Vulnerability Patterns
  • 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
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (37)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The code only covers the research/analysis portion of the description: website scraping, extraction of brand/features/testimonials/stats/CTAs/pricing, basic competitor detection from page text, and creation of storytelling/visual-context metadata. That partially matches the declared analysis capability, but the declared primary skill is broader social media automation for TikTok and Instagram carousel growth, including content generation, auto-publishing, trending music, and analytics. None of those downstream automation capabilities appear in this code chunk. Therefore the description materially overstates what the supplied code actually does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The code chunk implements only the analytics portion of the declared skill: it calls Upload-Post API endpoints to retrieve TikTok profile metrics, impression totals, and optional post analytics, and writes a snapshot file for later use. It does not analyze websites, extract brand or competitor information, generate carousel content, publish posts, or interact with trending music features. While analytics are mentioned in the description, the actual code’s primary behavior is much narrower than the declared end-to-end automation capability, so this is a material description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
The declared description presents a broader end-to-end growth automation skill: website analysis, viral slide generation, auto-publishing to TikTok/Instagram, trending music, and analytics feedback. The supplied code chunk is much narrower. It expects /tmp/carousel/analysis.json to already exist, extracts fields from that file, and generates six image prompts/images plus a caption and a local JSON log of prompts. There are no network calls for website scraping/analysis in this chunk, no social platform posting, no upload-post API usage, no music selection, and no real analytics loop. While slide generation aligns with part of the description, the chunk materially underdelivers relative to the declared primary capabilities, so this is a mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description promises a multi-step social media growth agent focused on TikTok/Instagram carousels, website analysis, publishing, music selection, and analytics. The supplied code does none of those things. It only parses CLI arguments, obtains a Gemini API key, optionally loads an input image, sends a prompt/image request to Google's image generation model, and saves the returned image locally. There is no code for crawling URLs, extracting brand intelligence, generating multi-slide carousels specifically, interacting with social platforms, publishing content, or tracking analytics. This is a clear description-behavior mismatch with a materially different primary purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description promises a broad end-to-end social growth agent with website analysis, content generation, and auto-publishing across TikTok and Instagram. This code chunk only implements the analytics feedback portion: it loads local JSON files from /tmp/carousel and the skill directory, adds a tracked post, computes averages/top performers/best times/days, and saves recommendations. While analytics learning is consistent with the description's final 'feedback loop' claim, the actual code shown lacks the major advertised capabilities and has a materially narrower primary purpose. Therefore the description does not accurately represent this code chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The description claims a broad automated growth workflow: website analysis, competitor/value-prop extraction, carousel generation, auto-publishing, trending music, and analytics feedback. The actual code chunk implements only the publishing portion. It does not fetch or analyze any website, does not generate slides, and does not perform analytics beyond writing a small JSON record with request_id and metadata. Additionally, while it enables auto_add_music for TikTok, it explicitly tells the user to manually add music on Instagram, so the declared cross-platform trending-music automation is overstated. The primary purpose of this code chunk is narrower than the declared skill description, so this is a material mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents a full social-media growth automation skill with content analysis, slide generation, publishing, music selection, and analytics. The provided code does none of those primary functions. Its purpose is narrowly focused on validating the presence/basic integrity of six local slide image files and preparing instructions for a later vision review step. Reading analysis.json is incidental context, not website analysis. There are no network calls, no TikTok/Instagram integrations, no URL handling, no competitor or brand extraction, and no analytics loop. This is a material description-behavior mismatch, not just an incomplete snippet of a larger workflow, because the code chunk’s actual capability is specifically a local review helper.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The code chunk implements only a competitor/review search helper. It launches a headless browser, queries Bing and DuckDuckGo, parses search results, detects known competitor names, and updates a local JSON file. While competitor discovery is one small part of the declared description, the declared purpose emphasizes a much broader pipeline: analyzing any website URL, generating viral carousel slides, auto-publishing to TikTok/Instagram with trending music, and analytics feedback. None of those core capabilities appear in this code. Therefore the description materially overstates and misrepresents what this supplied code chunk actually does.

Missing User Warnings

High
Confidence
99% confidence
Finding
The skill explicitly directs autonomous public posting to TikTok and Instagram without confirmation. In context, this is dangerous because it can publish inaccurate, infringing, off-brand, or policy-violating content directly to public accounts, causing reputational damage and irreversible external actions.

Missing User Warnings

High
Confidence
97% confidence
Finding
The quick-start flow normalizes immediate autonomous execution and direct publishing without a prominent safety warning or gating step. Because the skill uses third-party credentials and posts externally, the absence of a clear upfront warning materially increases the chance of accidental harmful publication.

Ae1

High
Category
analysis-evasion
Content
e won't be analytics data — that's fine. The agent uses the default hooks from `analyze-web.js` and the generic recommendations. After 5-10 posts, `learnings.js
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
e won't be analytics data — that's fine. The agent uses the default hooks from `analyze-web.js` and the generic recommendations. After 5-10 posts, `learnings.js
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
## Step 6: Learn and Improve (`learn-from-analytics.js`)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The manifest describes a skill for analyzing website URLs, extracting brand and competitor information, generating viral slides, auto-publishing to TikTok/Instagram, and using analytics feedback loops. This file instead implements a standalone Gemini image generation/editing utility that takes prompts and optional local input images, calls Google's image API, and writes image files locally, with no website analysis, social publishing, trending music, or analytics behavior.

Credential Access

High
Category
Privilege Escalation
Content
def get_api_key(provided_key: str | None) -> str | None:
    """Get API key from argument first, then environment."""
    if provided_key:
        return provided_key
    return os.environ.get("GEMINI_API_KEY")
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
process.exit(1);
  }
  
  // Output instructions for the agent
  console.log('═══════════════════════════════════════════════════════════════');
  console.log('📋 AGENT: Review each slide using your vision model.');
  console.log('   Use view_file or equivalent to see each image and verify:');
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README explicitly advertises direct publishing with 'No drafts, no manual steps' and 'posts go live instantly' without a prominent warning that generated content will be published immediately to live social accounts. In an automation skill that generates content from arbitrary URLs and posts cross-platform, this increases the risk of accidental brand damage, policy violations, or unintended publication of low-quality or misleading content.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill declares access to environment variables and shell-capable binaries but does not define any explicit tool scope or permission boundaries. In a skill that performs website analysis, file writes, and social-media publishing, this broad undeclared capability increases the chance of unintended command execution, secret exposure, or actions beyond what a user expects.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
## Philosophy: Daily Automated Loop

The key to growth is **consistency + learning**. This skill is designed to run **every day, fully autonomous**. The agent executes the entire pipeline without asking for confirmation — from research to publishing — and only notifies you at the end with the published TikTok and Instagram URLs.

1. **Post 1 carousel per day** - Consistency beats virality
2. **Track everything** - Every post generates data
Confidence
95% confidence
Finding
The skill is designed for fully autonomous decision-making from research through publishing, with no intermediate confirmation. Autonomy is especially risky here because the resulting actions are external, public, and repetitive, and errors can propagate daily without human review.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The skill instructs the agent to modify its own future execution schedule based on learned posting times. Self-rescheduling expands the skill from content generation into persistence and autonomous control of the execution environment, which can create runaway automation, unexpected resource use, or policy evasion without fresh user approval.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
## Step 3: Review with Vision (Autonomous)

After generating, the agent MUST review each slide using its vision/image-to-text model. **This step is fully automatic — do not ask the user to review.**

For each slide, verify:
- ✓ Text is fully legible and correct
Confidence
80% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- Slide 1: no input image (it establishes the style)
- Slides 2-6: always use `slide-1.jpg` as `--input-image` (the original reference)

Re-verify after regenerating. Repeat until all 6 slides pass. Do not ask the user — fix it automatically.

## Image Format
Confidence
80% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The metadata explicitly advertises analysis of "any website," while the skill also has network access, Playwright-based scraping, and downstream automation. That broad scope can enable misuse against internal, sensitive, or unexpected targets and increases SSRF-style or policy-bypass risk if callers provide arbitrary URLs without validation or allowlisting.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script persistently stores scraped website-derived data to /tmp/carousel/analysis.json without any explicit consent, retention control, or user-facing notice. Because the analyzed URL is arbitrary, the collected content can include proprietary business information, personal data exposed on pages, or other sensitive material that users may not realize is being written to disk.

Static analysis

No suspicious patterns detected.