T09 · Insecure Skill Coding Practices
- Location
scripts/video-to-s3-universal.js:95- Finding
Arbitrary Command Execution Through Unsafely Interpolated Video URLs
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill mostly does what it advertises, but unsafe command handling could let a crafted video URL or S3 path run commands on the user's machine.
Install only after reviewing the security tradeoff. Use least-privilege S3 credentials, protect the local config file, and avoid feeding URLs or S3 object keys from untrusted sources until the maintainer replaces shell-string exec calls with safe argument-array process execution. Expect the skill to upload media and metadata to your configured storage and to delete downloaded local copies after successful upload unless kept by option.
scripts/video-to-s3-universal.js:95Arbitrary Command Execution Through Unsafely Interpolated Video URLs
scripts/fixed-upload-video-to-s3.js:268Command Injection in S3 Upload Verification
The declared description is for a video-downloading and S3-uploading skill. The supplied code chunk does not implement any video retrieval, media processing, platform access, or storage upload behavior. Instead, it is a helper script that edits another JavaScript file by inserting an import line. This is a materially different primary purpose and introduces filesystem-modification behavior not represented in the description.
The declared description emphasizes a multi-platform video downloader with platform-specific acquisition features and post-processing (quality selection and audio merging), followed by S3 upload. The supplied code chunk only implements the S3 upload portion: it takes a local video path, determines content type, uploads to S3-compatible storage using multipart or simple upload, and optionally verifies accessibility of the uploaded object. There is no code for interacting with YouTube, X/Twitter, TikTok, Douyin, or Bilibili; no network retrieval of videos; no quality selection logic; and no audio/video merging. This is a material description-behavior mismatch because the primary declared purpose is downloading videos from external platforms, while the actual code is solely an uploader for local files.
The declared description presents a full-featured video downloading and upload skill, but the supplied code chunk contains only utility functions for filename cleaning and simple filename generation. While such helpers could support a downloader workflow, this chunk does not implement any of the core declared capabilities or behaviors. Therefore, the actual code behavior is materially different from the declared primary purpose.
The core behavior substantially matches the declared purpose: it detects video platforms, uses yt-dlp to fetch metadata and download content, chooses a best format, merges audio/video when needed using ffmpeg, uploads to S3-compatible storage through a helper uploader, and outputs the resulting URL. However, there are notable undeclared capabilities. The code explicitly supports Instagram, Facebook, and Twitch in addition to the listed services, which is a materially broader downloader scope than described. It also automatically deletes the downloaded local file after upload, an additional filesystem-modifying behavior not reflected in the description. These do not change the primary purpose, but they are meaningful undeclared capabilities, so this should be flagged as a mismatch.
The core S3 upload behavior generally matches the description, and the code does perform smart format selection plus optional audio merging. However, the declared description materially overstates platform coverage: this code only accepts a YouTube URL, labels itself repeatedly as a YouTube-to-S3 uploader, and contains no platform-specific logic for Twitter/X, TikTok, Douyin, or Bilibili. That makes the declared primary purpose ('universal video downloader' across multiple services) inaccurate for this supplied code chunk. The filesystem/config access is supporting behavior rather than the main mismatch, but it does indicate reliance on local resources not mentioned in the declared permissions.
The declared description presents the skill as a broad multi-platform video downloader/uploader. The supplied code chunk, however, is narrowly branded and structured as 'youtube-s3-upload', accepts a single '' described as a YouTube video URL, and describes itself as 'Download YouTube videos and upload to S3 storage'. It also adds operational commands unrelated to the declared downloader summary: 'test' checks S3 connection, lists available buckets, and may list objects in a bucket; 'config' reveals current bucket configuration metadata. Based on this code alone, the actual behavior is materially narrower than declared in download scope, and it also includes undeclared S3 inspection/config-display capabilities.
The declared purpose is a media downloading and upload utility, but the actual code is a simple version-bump script for package.json. Its primary purpose is materially different from the description, and it uses local filesystem access for package metadata editing rather than any video platform access or S3-compatible storage interaction. This is a clear description-behavior mismatch.
Referenced artifact was not completely inspected
- **❌ New API**: Universal `video-to-s3-universal.js` script
Referenced artifact was not completely inspected
node scripts/fixed-upload-video-to-s3.js /path/to/large-video.mp4
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.
The project directly depends on js-yaml 4.1.1, which has multiple CPU exhaustion advisories involving crafted YAML features such as merge keys and omap resolution. If this skill accepts user-controlled YAML configuration, an attacker can supply malicious YAML that drives excessive parsing work and causes denial of service; this is more relevant here because js-yaml is a direct dependency, not merely transitive.
The package depends on js-yaml 4.1.1, which is flagged with multiple advisories for CPU exhaustion during YAML parsing. In the context of a skill that likely reads YAML configuration files, an attacker who can supply or influence YAML input could trigger denial of service through excessive CPU consumption, making this more dangerous than a purely dormant dependency issue.
The manifest says the skill is a universal downloader for YouTube, Twitter/X, TikTok, Douyin, and Bilibili, but the README consistently presents the skill as 'YouTube to S3 Uploader' and documents only YouTube URLs and YouTube-specific use cases. This is a semantic mismatch in stated behavior and scope between the skill manifest and the skill's own documentation.
The README advertises downloading remote content, validating S3 credentials, uploading files, and automatically cleaning up local files without prominent warnings about data transmission, secret handling, or deletion behavior. Users may run the skill without understanding that credentials are stored locally, media is sent to third-party storage, and local artifacts may be removed automatically, increasing the chance of accidental data loss or exposure.
The README instructs users to store long-lived S3 access keys in a plaintext YAML file under the home directory, creating persistent local secrets that may be exposed through weak filesystem permissions, backups, shared accounts, or endpoint compromise. In the context of a tool that handles cloud storage credentials, this increases the risk of unauthorized bucket access and data exfiltration.
Create ~/.youtube-s3-uploader.yml:
default: my-videos
The README states 'No external APIs: Everything runs locally' even though the skill necessarily connects to YouTube or other video platforms, S3-compatible storage, and may auto-install yt-dlp. This can cause users to underestimate network exposure and trust boundaries, leading them to provide credentials or run the tool in sensitive environments under false assumptions.
The skill describes shell-capable commands and executable workflows but does not declare any explicit tool scope or permissions. In an agent ecosystem, this weakens security boundaries and can allow the skill to invoke shell operations beyond what a user would reasonably infer from metadata.
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.
- **✅ Universal Support**: Works with 1000+ websites via yt-dlp
### Breaking Changes:
- **❌ NOT backward compatible**: v3.x is a complete rewrite from v2.x
- **❌ New API**: Universal `video-to-s3-universal.js` script
- **❌ Platform Detection**: Automatically detects video platform
The skill advertises automatic cleanup of local files after upload, but the documentation does not prominently warn about potential irreversible data loss if upload verification is flawed, a wrong path is targeted, or a user expected local retention. In automation contexts, silent deletion materially increases operational risk.
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.
1. **Use IAM roles** when possible instead of long-term credentials
2. **Set short expiration** for presigned URLs (minutes, not days)
3. **Enable bucket versioning** for accidental deletion protection
4. **Configure lifecycle rules** to automatically delete old files
5. **Use bucket policies** to restrict access by IP or referrer
## Troubleshooting
The manifest describes support for YouTube, Twitter/X, TikTok, Douyin, and Bilibili, but the user-facing help text expands the skill's scope to Instagram, Facebook, Twitch, and '1000+ more sites supported by yt-dlp'. This is a semantic mismatch in the stated behavior of the skill because the code advertises a materially broader downloader capability than the manifest declares.
This code writes directly to another source file using fs.writeFileSync, changing repository contents without any confirmation prompt or prior warning comment/docstring. Although there is a success log after the fact, the user is not warned before the modification occurs, so the operation lacks adequate disclosure for a file-writing action.
This code loads access keys from a local YAML config and immediately uses them to configure an S3 client for upload. Although the script logs upload progress, it does not disclose that it will use stored credentials and send file contents and metadata to a remote endpoint, which is a safety-relevant network operation.
The verification routine builds a shell command with a URL interpolated into child_process.exec, which introduces unnecessary command-execution capability into a file uploader. Although the URL is typically derived from configured endpoint, bucket, and key, any attacker-controlled value containing shell metacharacters or quotes could break out of the quoted curl argument and execute arbitrary commands.
The manifest description names YouTube, Twitter/X, TikTok, Douyin, and Bilibili as the supported sources. The code explicitly adds Instagram, Facebook, and Twitch to the supported platform list, and later states that unsupported platforms may still work because yt-dlp supports many sites, expanding the skill beyond the described scope.
Detected: suspicious.dangerous_exec