T01 · Skill Instruction Hijacking
- Location
SKILL.md:37- Finding
Mandatory unpinned preflight permits remote influence over agent responses and workflow
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This media skill matches its stated purpose, but it should be reviewed because it can run unpinned external tools, install packages automatically, load broad credentials, and leave background audio jobs running.
Install only if you are comfortable with this skill running Node and Python subprocesses, installing packages, using media provider API keys, and sending media to cloud providers when those paths are chosen. Prefer a dedicated project and virtual environment, expose only the needed environment variables, use pinned local dependencies where possible, avoid sensitive media unless external upload is approved, and monitor or clean up BGM jobs and temp files.
SKILL.md:37Mandatory unpinned preflight permits remote influence over agent responses and workflow
scripts/lib/bgm.mjs:23Background music generation automatically installs unpinned Python packages
scripts/lib/tts.mjs:252Fallback TTS and transcription execute an unversioned npm package
scripts/lib/heygen.mjs:14Credential loader imports unrelated secrets from ancestor .env files
scripts/lib/tts.mjs:314Narration text is left in persistent plaintext temporary files
scripts/lib/heygen.mjs:102Provider-supplied media URLs are downloaded without host, size, or timeout controls
scripts/lib/bgm.mjs:146Detached BGM processes are not terminated after workflow timeout
Referenced artifact was not completely inspected
- `scripts/heygen-tts.mjs` is a single-shot CLI over the same code (one text → wav + words) for when you just need HeyGen TTS without a request file.
Referenced artifact was not completely inspected
- `scripts/heygen-tts.mjs` is a single-shot CLI over the same code (one text → wav + words) for when you just need HeyGen TTS without a request file.
Referenced artifact was not completely inspected
- `scripts/heygen-tts.mjs` is a single-shot CLI over the same code (one text → wav + words) for when you just need HeyGen TTS without a request file.
Referenced artifact was not completely inspected
- `scripts/heygen-tts.mjs` is a single-shot CLI over the same code (one text → wav + words) for when you just need HeyGen TTS without a request file.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
// heygen.mjs — vendored HeyGen REST helpers (auth + transport) for the audio
// pipeline. The credential resolver is copied from hyperframes-media's
// heygen-tts.mjs (and matches the hyperframes CLI auth): first usable source
// wins — $HEYGEN_API_KEY / $HYPERFRAMES_API_KEY → a nearby .env → ~/.heygen/
// credentials (oauth → Bearer, else api_key → X-Api-Key; $HEYGEN_CONFIG_DIR
// overrides the dir). Vendored so the skill ships standalone. Pure node.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
// heygen.mjs — vendored HeyGen REST helpers (auth + transport) for the audio
// pipeline. The credential resolver is copied from hyperframes-media's
// heygen-tts.mjs (and matches the hyperframes CLI auth): first usable source
// wins — $HEYGEN_API_KEY / $HYPERFRAMES_API_KEY → a nearby .env → ~/.heygen/
// credentials (oauth → Bearer, else api_key → X-Api-Key; $HEYGEN_CONFIG_DIR
// overrides the dir). Vendored so the skill ships standalone. Pure node.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
// heygen.mjs — vendored HeyGen REST helpers (auth + transport) for the audio
// pipeline. The credential resolver is copied from hyperframes-media's
// heygen-tts.mjs (and matches the hyperframes CLI auth): first usable source
// wins — $HEYGEN_API_KEY / $HYPERFRAMES_API_KEY → a nearby .env → ~/.heygen/
// credentials (oauth → Bearer, else api_key → X-Api-Key; $HEYGEN_CONFIG_DIR
// overrides the dir). Vendored so the skill ships standalone. Pure node.
This code walks up to five parent directories and loads the first .env it finds, importing arbitrary key-value pairs into process.env. In shared or untrusted working directories, that can cause credential confusion or unintended secret ingestion from a parent project, increasing the risk of using attacker-controlled API keys or leaking operational context to downstream requests.
export function loadEnvFromDir(startDir) {
let dir = resolve(startDir);
for (let i = 0; i < 5; i++) {
const envPath = join(dir, ".env");
if (existsSync(envPath)) {
for (const raw of readFileSync(envPath, "utf8").split("\n")) {
let line = raw.trim();
The skill explicitly instructs use of shell commands and environment-resolved credentials, but it declares no tool restrictions or allowed-tools scope. In systems that honor skill metadata for sandboxing, this can cause the skill to run with broader-than-necessary shell/env access, increasing the chance of command execution or credential exposure if the skill is invoked in an unsafe context.
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.
Always run this before generating voice or BGM — inside a full workflow or a one-off "generate me a BGM/voiceover" request. No HeyGen credential is not a reason to silently fall back to local engines: first recommend signing in and let the user decide. Run the shared preflight and relay its output verbatim — don't improvise your own "missing key" prompt, and don't offer to write keys into a per-repo .env:
npx hyperframes auth status
Using npx hyperframes auth status without a pinned package version allows whatever version of hyperframes resolves at execution time to run. If the package is updated maliciously, compromised upstream, or subject to dependency confusion in the execution environment, the agent could execute untrusted code during a security-sensitive auth flow.
A second unpinned npx hyperframes reference appears on the same line in the API-key login example, creating the same supply-chain execution risk. In an agent workflow, even documentation examples can be operationalized verbatim, so an attacker controlling the package resolution path could hijack an auth action.
The unpinned JSON-status command can execute a non-deterministic package version, undermining the skill's claim of deterministic branching. While this invocation is less credential-sensitive than login, it still executes remote code and may produce attacker-controlled output that influences subsequent agent decisions.
Recommending npx hyperframes auth login again without version pinning repeats the same remote-code execution and credential interception risk. The danger is amplified because the skill tells the agent to stop and wait around this decision point, making the auth path central to the workflow.
The reference to npx hyperframes tts is also unpinned, so generating audio may execute arbitrary code from an unexpected package version. Although less sensitive than auth, this still grants code execution in the agent environment and may access files, network, or environment variables depending on runtime permissions.
The transcription command reference uses unpinned npx, which can fetch and run an unintended package version. In agent environments, documentation often becomes executable instruction, so this creates a real supply-chain risk rather than a purely informational issue.
The background-removal command reference is unpinned and therefore subject to the same package-resolution and remote code execution risks as the other npx examples. Since media-processing tools often touch user-supplied files, compromise could expose local content or alter outputs maliciously.
The TTS-to-captions workflow reference relies on unpinned npx, again allowing execution of whatever package version resolves in the environment. Because this may chain multiple processing steps, a compromised package could tamper with transcripts, captions, or intermediate assets while executing arbitrary code.
Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.
## Failure modes
| Failure | Behavior |
| --------------------------------------------- | ---------------------------------------------------------------------------------------- |
| No music match (retrieve) | `bgm: null`, anomaly logged. Render proceeds without BGM. |
| Explicit `retrieve`, no credential | Skipped (no silent generate fallback). Use `mode: generate` or omit `mode` for auto. |
The documentation instructs users to run npx hyperframes ... without pinning an exact package version. npx may fetch the latest published package at execution time, so a compromised upstream release, typosquatted package, or unexpected breaking change could result in unreviewed code being executed on the user's machine.
This command uses npx hyperframes add ... with no version pin, which can download and execute whatever version is current at the time of use. In a skill context, examples are often copied verbatim, so this increases supply-chain risk and makes builds non-reproducible.
The unpinned npx hyperframes catalog --tag caption-style example allows remote package resolution at runtime, which can lead to execution of a malicious or altered package version. Because this file is instructional documentation, the risk is indirect but real: users may execute the command in trusted environments based solely on the example.
The file instructs users to upload local audio to third-party transcription APIs and send API bearer tokens, but it provides no explicit warning that transcript content and raw media leave the local environment. In a media workflow, audio commonly contains sensitive voice, personal data, or unpublished content, so omission of a privacy/data-sharing notice can cause unintentional disclosure.
This command explicitly transmits audio.mp3 and an API credential to OpenAI's external service. The transmission is intentional and functionally necessary, but in this skill context it still creates a real confidentiality risk because media assets may contain sensitive speech, licensed material, or internal recordings.
# Generate with word timestamps, then import
curl https://api.openai.com/v1/audio/transcriptions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-F file=@audio.mp3 -F model=whisper-1 \
-F response_format=verbose_json \
This example sends local audio and a bearer token to Groq's external API endpoint. Although expected for cloud transcription, it is still a genuine data-exposure pathway, and the skill context increases relevance because transcription inputs are often raw user recordings that may contain personal or confidential information.
Groq Whisper API (fast, free tier available):
curl https://api.groq.com/openai/v1/audio/transcriptions \
-H "Authorization: Bearer $GROQ_API_KEY" \
-F file=@audio.mp3 -F model=whisper-large-v3 \
-F response_format=verbose_json \
Detected: suspicious.dangerous_exec, suspicious.env_credential_access