Back to skill

Security audit

AI Content Repurposer

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its advertised content-repurposing purpose, but it has review-worthy risks around unrestricted URL fetching and unsafe batch output writes.

Review this before installing in any environment with access to internal services or important writable project files. Use only trusted blog URLs and trusted batch config files, avoid confidential input unless OpenAI processing is approved for that data, and prefer a patched version that validates URLs, constrains output paths, and updates the flagged dependencies.

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

T09 · Insecure Skill Coding Practices

Error
Location
src/converter.js:219
Finding
Arbitrary Blog URL Fetching Enables Server-Side Request Forgery## Vulnerability Details **File Location**: `src/converter.js:219-225`; reachable from `bin/cli.js:68-72` and `bin/cli.js:109-113` **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: High ### Vulnerable Code ```javascript async fetchBlogContent(url) { try { const response = await axios.get(url, { headers: { 'User-Agent': 'Mozilla/5.0' }, timeout: 10000 }); ``` The affected CLI commands pass user-controlled URLs directly to this method: ```javascript if (source.startsWith('http')) { console.log('📥 Fetching blog content...'); content = await converter.fetchBlogContent(source); } ``` ### Technical Analysis The `blog-to-twitter` and `blog-to-linkedin` commands accept a user-controlled source. Any value beginning with `http` is submitted to `axios.get()` without validating its scheme, hostname, port, resolved IP address, or redirect destination. A timeout limits request duration but does not restrict where the request can be sent. Consequently, the process can be induced to contact: - Loopback services such as `127.0.0.1` or `::1` - Private-network services - Link-local addresses and cloud instance metadata services - Internal administrative interfaces that are unavailable to the external attacker - Public URLs that redirect to one of these prohibited destinations After retrieval, the response is parsed as page content. For normal conversion operations, up to 8,000 characters of the extracted content are placed in an AI prompt and sent to the configured OpenAI API. Therefore, data obtained through SSRF may be incorporated into generated output or transmitted to the declared external AI provider. Remote URL retrieval is necessary for the documented blog-import feature, but unrestricted access to arbitrary network destinations exceeds the minimum network privileges needed to fetch public blog posts. ### Attack Path 1. An attacker supplies or persu ...[truncated 1255 chars]
Remediation
## Remediation Suggestions 1. Parse input with `new URL()` and reject malformed URLs. 2. Permit only explicitly required schemes, preferably HTTPS. 3. Reject embedded credentials, nonstandard ports, and hostnames not required by the feature. 4. Resolve the destination hostname before connecting and block loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 ranges. 5. Repeat destination validation after every DNS resolution and for every redirect target. 6. Disable automatic redirects or implement a bounded redirect handler that validates each destination before following it. 7. Consider an explicit public-domain allowlist or a controlled outbound proxy. 8. Apply response-size limits in addition to the existing timeout. 9. Clearly notify users that fetched article content will be submitted to OpenAI when AI processing is enabled. 10. Add tests covering loopback addresses, private ranges, IPv6, alternative numeric IP representations, DNS rebinding scenarios, and redirects to blocked destinations.

T09 · Insecure Skill Coding Practices

Error
Location
bin/cli.js:255
Finding
Unsanitized Batch Job Names Permit Output Directory Traversal and File Overwrite## Vulnerability Details **File Location**: `bin/cli.js:255-277` **Vulnerability Type**: Path Traversal and Arbitrary JSON File Overwrite **Risk Level**: High ### Vulnerable Code ```javascript for (const [index, job] of config.jobs.entries()) { console.log(`[${index + 1}/${config.jobs.length}] Processing: ${job.name}`); try { let result; const outputFile = path.join(options.outputDir, `${job.name}.json`); switch (job.type) { case 'youtube-to-shorts': result = await converter.youtubeToShortForm(job.content, job.platform || 'tiktok'); break; case 'blog-to-twitter': result = await converter.blogToTwitterThread(job.content, job.tweetCount || 7); break; case 'blog-to-linkedin': result = await converter.blogToLinkedIn(job.content, job.tone || 'thought-leadership'); break; case 'podcast-to-summary': result = await converter.podcastToSummary(job.content); break; default: console.log(` ⚠️ Unknown job type: ${job.type}`); continue; } fs.writeFileSync(outputFile, JSON.stringify(result, null, 2)); ``` ### Technical Analysis The batch configuration is parsed from a user-selected JSON file, and each attacker-controlled `job.name` is directly interpolated into an output filename. `path.join()` normalizes path components but does not guarantee that the resulting path remains under `options.outputDir`. A job name containing parent-directory components, such as `../../target`, causes the normalized destination to escape the intended output directory. The `.json` suffix limits the most direct targets to JSON filenames, but many applications store security-sensitive settings, package metadata, state, and operational configuration in JSON files. `fs.writeFileSync()` overwrites an existing destination by default. There is no canonical-path containment check, fi ...[truncated 1886 chars]
Remediation
## Remediation Suggestions 1. Treat `job.name` as a filename identifier rather than a path. 2. Enforce a restrictive allowlist such as letters, digits, periods, underscores, and hyphens. 3. Reject names containing path separators, parent-directory components, drive prefixes, null bytes, or empty values. 4. Resolve the output directory and candidate path to absolute canonical paths. 5. Verify that every candidate begins with the resolved output-directory path followed by the platform path separator. 6. Use `path.basename(job.name)` only as defense in depth; do not rely on it instead of validation and containment checks. 7. Prevent silent replacement by using exclusive file creation where practical or requiring explicit overwrite authorization. 8. Detect duplicate sanitized job names before processing the batch. 9. Run the Skill with filesystem permissions limited to the intended input and output locations. 10. Add tests for `../`, nested traversal, Windows separators, absolute paths, drive-letter paths, duplicate names, symbolic-link edge cases, and overwrite attempts.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (15)

Known Vulnerable Dependency: axios==1.13.6 — 16 advisory(ies): CVE-2026-44494 (axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `co); CVE-2026-44495 (axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollut); CVE-2025-62718 (Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF) +13 more

High
Category
Supply Chain
Confidence
95% confidence
Finding
The lockfile pins axios 1.13.6, and the supplied advisories include high-severity issues such as NO_PROXY normalization bypass leading to SSRF and prototype-pollution-related MITM/credential theft scenarios. In an agent skill that likely fetches remote content, a vulnerable HTTP client is directly security-relevant because attacker-controlled URLs, proxy settings, or redirects may be part of normal operation.

Known Vulnerable Dependency: form-data==4.0.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
90% confidence
Finding
form-data 4.0.5 is flagged for CRLF injection via unescaped multipart field names/filenames, which can enable request smuggling or malformed downstream requests when attacker-controlled values are embedded into multipart bodies. If this skill uploads or forwards content derived from external input, the bug may become reachable through normal usage.

Known Vulnerable Dependency: undici==7.24.3 — 12 advisory(ies): CVE-2026-6733 (undici vulnerable to HTTP response queue poisoning via keep-alive socket reuse); CVE-2026-13697 (undici vulnerable to cross-user information disclosure and parse-time crash via ); CVE-2026-16728 (undici vulnerable to downstream response desynchronization via retry interceptor) +9 more

High
Category
Supply Chain
Confidence
91% confidence
Finding
undici 7.24.3 is associated with multiple high-severity HTTP parsing, queue poisoning, desynchronization, and information disclosure advisories. Because cheerio depends on undici and this skill likely retrieves untrusted web content, flaws in the HTTP stack can affect confidentiality and integrity of fetched data or allow cross-request contamination.

Known Vulnerable Dependency: axios==1.13.6 — 16 advisory(ies): CVE-2026-44494 (axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `co); CVE-2026-44495 (axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollut); CVE-2025-62718 (Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF) +13 more

High
Category
Supply Chain
Confidence
97% confidence
Finding
The manifest allows installation of axios versions in the ^1.6.0 range, and the finding indicates the resolved version includes multiple known high-severity advisories, including SSRF-related and MITM/prototype-pollution-gadget issues. In a tool that likely fetches remote content for transcription, scraping, or summarization, a vulnerable HTTP client materially increases risk because attacker-controlled URLs, proxy settings, or responses may be processed.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The README instructs users to provide transcripts, blog URLs, and podcast content to a tool powered by an external AI API, but it does not clearly warn that this input may be transmitted to a third-party service such as OpenAI. This can cause users to unintentionally submit sensitive or proprietary content, creating confidentiality, privacy, and compliance risks.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill requires an OpenAI API key and explicitly describes AI-powered transformations, but it does not clearly warn users that submitted transcripts, blog text, or podcast content may be transmitted to an external third-party AI service. This creates a real privacy and data-handling risk because users may provide unpublished, client-owned, or sensitive content without understanding that it could leave their local environment.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The manifest explicitly requires an OPENAI_API_KEY, which strongly implies user content will be transmitted to an external AI provider, but it does not disclose that behavior or warn users about privacy, retention, or third-party processing. For a content-repurposing skill handling blogs, podcasts, and social media drafts, this can expose unpublished, proprietary, or client content to an external service without informed consent.

External Transmission

Medium
Category
Data Exfiltration
Content
constructor(options = {}) {
    this.apiKey = options.apiKey || process.env.OPENAI_API_KEY;
    this.model = options.model || 'gpt-4';
    this.baseUrl = 'https://api.openai.com/v1';
  }

  /**
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
90% confidence
Finding
No manifest is available, so the only stated intent comes from the file-level documentation describing a content repurposer that transforms provided content into other formats. The fetchBlogContent method adds a separate capability to retrieve and scrape arbitrary URLs over the network, which is not clearly required by the documented conversion role itself.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
Content fetched from arbitrary blog URLs can be passed into prompts and sent to the external OpenAI API without an explicit consent gate or warning at the transmission point. This can expose copyrighted, private, or sensitive page contents to a third party, especially if callers do not realize that fetched material is being exfiltrated beyond the local process.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The quickstart instructs users to export an API key directly in the shell but does not caution them to protect the credential or avoid persisting it in shell history, scripts, screenshots, or shared environments. While this is common documentation practice, it can still lead to accidental secret exposure and unauthorized API usage if copied into unsafe contexts.

Vague Triggers

Low
Confidence
84% confidence
Finding
This manifest-like JSON allows the same `content` field to mean either pasted text or a file path, using the phrase "Path to transcript file or paste content here...". That dual-use description is ambiguous about how the skill decides which mode to use and what inputs are valid, which can lead to unintended invocation behavior or misinterpretation of user input.

Known Vulnerable Dependency: follow-redirects==1.15.11 — 1 advisory(ies): CVE-2026-40895 (follow-redirects leaks Custom Authentication Headers to Cross-Domain Redirect Ta)

Low
Category
Supply Chain
Confidence
88% confidence
Finding
follow-redirects 1.15.11 is reported as leaking custom authentication headers across cross-domain redirects. In a content-repurposing skill that performs HTTP requests, this can expose API keys or bearer tokens if the application follows attacker-influenced redirects to a different host.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"author": "OpenClaw",
  "license": "MIT",
  "dependencies": {
    "commander": "^11.0.0",
    "axios": "^1.6.0",
    "cheerio": "^1.0.0-rc.12"
  },
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"license": "MIT",
  "dependencies": {
    "commander": "^11.0.0",
    "axios": "^1.6.0",
    "cheerio": "^1.0.0-rc.12"
  },
  "engines": {
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
src/converter.js:11