Back to skill

Security audit

AI Content Repurposer Pro

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its content-repurposing purpose, but it needs review because arbitrary URL fetching and batch output writes are not safely bounded.

Review before installing in environments that can reach private networks or sensitive internal sites. Do not feed confidential, regulated, or proprietary content unless you are comfortable sending it to OpenAI, avoid processing untrusted URLs, and treat batch config files as trusted input until URL validation, privacy disclosure, dependency updates, and output-path containment are fixed.

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
Unrestricted Blog URL Fetching Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `src/converter.js:219-242` **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 }); const $ = cheerio.load(response.data); // Remove scripts, styles, nav, footer $('script, style, nav, footer, header, aside').remove(); // Try to find main content let content = $('article').text() || $('main').text() || $('.post-content').text() || $('.entry-content').text() || $('body').text(); // Clean up whitespace return content.replace(/\s+/g, ' ').trim(); } catch (error) { throw new Error(`Failed to fetch blog content: ${error.message}`); } } ``` The vulnerable method is reached from user-controlled CLI input at `bin/cli.js:77-80` and `bin/cli.js:121-124`: ```javascript if (source.startsWith('http')) { console.log('📥 Fetching blog content...'); content = await converter.fetchBlogContent(source); } ``` ### Technical Analysis The Skill sends an HTTP request to a user-supplied URL without validating: - The URL scheme. - The destination hostname and resolved IP addresses. - Whether the destination belongs to a loopback, private, link-local, multicast, or reserved network. - The destination port. - Redirect destinations. - The maximum response size. The superficial `source.startsWith('http')` check does not provide a security boundary. Values beginning with `http://` or `https://` can still target internal services, such as loopback interfaces, private network hosts, or link-local cloud metadata services. Axios follows redirects by default. Consequently, even validation of only the initial URL would be insufficient: an apparently public endpoint could redirect the request to an ...[truncated 1893 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse input with the standard `URL` class and allow only `http:` and `https:` protocols. 2. Resolve the hostname before connecting and reject every address in: - IPv4 and IPv6 loopback ranges. - RFC 1918 private ranges. - Link-local ranges. - Multicast, unspecified, documentation, and other reserved ranges. - IPv4-mapped IPv6 representations of prohibited IPv4 addresses. 3. Prevent DNS rebinding by ensuring the validated address is the address used for the connection. 4. Disable automatic redirects or validate the scheme, hostname, resolved addresses, and port at every redirect hop. 5. Apply an explicit allowlist of public domains when the operational use case permits it. 6. Restrict destination ports to expected web ports, such as 80 and 443, unless other ports are explicitly required. 7. Set a strict response-size limit using Axios `maxContentLength` and reject non-text content types. 8. Consider routing retrieval through an isolated fetch service with no access to internal networks or cloud metadata endpoints. 9. Inform users before fetched content is submitted to OpenAI, and provide a local-only or confirmation mode for sensitive material. 10. Add tests for loopback, private IPv4, IPv6, link-local, encoded IP forms, DNS rebinding, redirects to internal addresses, oversized responses, and unsupported schemes. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
bin/cli.js:276
Finding
Batch Job Name Path Traversal Allows Writes Outside the Output Directory<![CDATA[ ## Vulnerability Details **File Location**: `bin/cli.js:276-293` **Vulnerability Type**: Path Traversal / Arbitrary File Write **Risk Level**: Medium ### Vulnerable Code ```javascript 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 `job.name` property is read from the user-supplied batch configuration and interpolated directly into an output path: ```javascript path.join(options.outputDir, `${job.name}.json`) ``` There is no validation that `job.name` is a simple filename. Directory traversal sequences such as `../` can cause the normalized destination to escape `options.outputDir`. The code also uses `fs.writeFileSync` with its default behavior, which creates a missing file or truncates an existing file. Therefore, a crafted configuration can write generated JSON to any location writable by the current process, provided the parent directory exists. ### Attack Path 1. An attacker creates or modifies a batch configuration consumed by the victim. 2. A job is assigned a traversal name, for example: ```json { "jobs": [ { "name": "../../target", "type": "blog-to-twitter", "content": "Attacker-controlled content" } ] } ``` 3. The victim runs the batch command with an out ...[truncated 1373 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict job names to safe filename characters, for example: ```javascript if ( typeof job.name !== 'string' || !/^[A-Za-z0-9._-]+$/.test(job.name) || job.name === '.' || job.name === '..' ) { throw new Error('Invalid batch job name'); } ``` 2. Resolve and verify the final destination before writing: ```javascript const outputRoot = path.resolve(options.outputDir); const outputFile = path.resolve(outputRoot, `${job.name}.json`); if ( outputFile === outputRoot || !outputFile.startsWith(outputRoot + path.sep) ) { throw new Error('Output path escapes the configured directory'); } ``` 3. Explicitly reject `/`, `\`, `..`, null bytes, absolute paths, and platform-specific path prefixes in job names. 4. Use a generated identifier for filenames and store the display name only inside the JSON result where practical. 5. Use exclusive file creation (`flag: 'wx'`) if overwriting existing output is not required. 6. Apply restrictive output permissions appropriate to the platform. 7. Treat batch configuration files as untrusted input and validate the complete schema before processing. 8. Add tests covering `../`, nested traversal, Windows separators, absolute-path forms, repeated separators, Unicode edge cases, and attempted overwrites. ]]>
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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
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
97% confidence
Finding
The lockfile pins axios to 1.13.6, which the static analysis reports as having multiple published advisories including SSRF-related proxy bypass and prototype-pollution-assisted request/response compromise issues. In a skill that repurposes content and likely fetches remote URLs, a vulnerable HTTP client materially increases risk because attacker-controlled URLs, redirects, proxy settings, or crafted objects may influence outbound requests and expose internal services, credentials, or response integrity.

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 reported vulnerable to CRLF injection via unescaped multipart field names and filenames. If any part of this skill constructs multipart requests from untrusted input, an attacker may be able to smuggle or alter HTTP message structure, potentially affecting downstream services or enabling request manipulation.

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
92% confidence
Finding
undici 7.24.3 is flagged with multiple HTTP parsing, queue poisoning, and desynchronization-related advisories. Because cheerio depends on undici and this skill likely retrieves remote web content, these issues can affect the integrity and isolation of HTTP responses, potentially causing information disclosure, response mix-ups, or denial of service when interacting with malicious endpoints.

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 skill declares axios with a broad range (^1.6.0), and the analysis indicates resolution to axios 1.13.6 with multiple published advisories, including SSRF-related and prototype-pollution-assisted attack paths. Because this skill is described as transforming external content and includes web-fetching libraries, a vulnerable HTTP client is more dangerous in context: attacker-controlled URLs, proxy behavior, redirects, or crafted responses could be leveraged to exfiltrate data, bypass network restrictions, or hijack request handling.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The quick start encourages URL-based blog conversion without warning that the tool may retrieve webpage content and, when AI features are enabled, potentially transmit that content to an external model provider. This can lead users to process private, internal, or copyrighted material without understanding the data exposure implications.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The README advertises commands that accept URLs and use AI features backed by an OpenAI API key, but it does not warn users that fetched content and user-supplied text may be transmitted to external services. This creates a real privacy and data-handling risk because users may unknowingly submit proprietary, personal, or sensitive content to third-party infrastructure over the network.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill explicitly requires an OpenAI API key and describes AI-powered transformations, but it does not clearly warn users that their provided transcripts, blog contents, URLs, or files may be transmitted to an external AI service for processing. This can lead users to unknowingly send sensitive, proprietary, or personal content off-platform, creating privacy, compliance, and confidentiality risks.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
The CLI accepts a user-supplied URL and fetches its contents without any explicit warning that the provided URL and resulting network request may disclose information to external services. In a local CLI context this is not code execution, but it can still create privacy and data-handling risks because users may unintentionally send internal, sensitive, or authenticated URLs across the network.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
This command also fetches content from a user-provided URL without prominently informing the user that remote network access will occur. That omission can lead to accidental privacy exposure or retrieval of sensitive internal resources if a user supplies a URL they did not realize would be fetched by the tool.

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
86% confidence
Finding
The module documentation describes a 'Core Converter' that transforms provided content into other formats, but this method adds a separate capability to fetch and scrape arbitrary blog URLs over the network. With no manifest available to justify broader acquisition capabilities, remote content retrieval is not clearly necessary for a converter whose other methods operate on caller-supplied text.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
Content fetched from arbitrary blog URLs is later embedded into prompts and sent to the external OpenAI API without any explicit user consent, warning, or data-classification check at the transmission point. This creates a privacy and data-handling risk because scraped content may contain copyrighted, private, or sensitive material that users do not realize will be forwarded to a third party.

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 flagged for leaking custom authentication headers across cross-domain redirects. If this skill sends authenticated requests while scraping or fetching content, an attacker-controlled redirect could cause bearer tokens or other sensitive headers to be forwarded to an unintended 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