Back to skill

Security audit

Long Task Runner

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed local long-job runner with real command execution power, so it should only be used with commands and install sources the user trusts.

Install from a pinned, verified source where possible. Use this only for commands you would be comfortable running yourself, because child processes inherit the current environment and can access whatever that account can access. Review job specs before starting them, avoid untrusted validators, and treat remote watching as status polling only, not remote cancellation or submission.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (1)

T08 · Insecure Dependencies

Warning
Location
README.md:18
Finding
Unpinned Installation Sources Permit Supply-Chain Substitution## Vulnerability Details **File Location**: `README.md`, lines 18 and 24 **Vulnerability Type**: Unpinned third-party installer and mutable repository revision **Risk Level**: Medium ### Vulnerable Code ```sh npx skills add dhzyw/long-task-runner --skill long-task-runner --agent codex ``` ```powershell git clone https://github.com/dhzyw/long-task-runner.git "$env:USERPROFILE\.agents\skills\long-task-runner" ``` ### Technical Analysis The recommended `npx` installation command does not pin the Skills CLI package to a reviewed version or verify its integrity. Consequently, the code executed by `npx` may differ from the version available during this audit. The alternative `git clone` command also retrieves the repository's current default branch rather than the source commit identified in `README.md` line 3: ```text Source commit: 3e267399cc5db606556ecbd0ec8b3746429b790b. ``` Neither installation path cryptographically binds the installed content to the audited artifact. An upstream account compromise, malicious package release, compromised transitive dependency, or unauthorized repository update could therefore substitute installer logic or Skill files after this review. ### Attack Path 1. An attacker compromises the package used by the unversioned `npx skills` command, one of its dependencies, the upstream repository, or a maintainer account. 2. The attacker publishes malicious installer code or changes the repository's default branch. 3. A user follows one of the documented installation commands. 4. The mutable package or repository content is downloaded without a version, commit, checksum, or signature verification step. 5. In the `npx` path, attacker-controlled installation code can execute immediately with the invoking user's privileges. In the clone path, malicious Skill instructions or scripts are installed into the user's Skill directory. 6. The altered Skill may subsequently execute commands or influence agent behavior under the user's account. ...[truncated 716 chars]
Remediation
## Remediation Suggestions 1. Pin the Skills CLI to a specific audited version rather than invoking an unversioned package: ```sh npx --yes skills@<AUDITED_VERSION> add dhzyw/long-task-runner --skill long-task-runner --agent codex ``` 2. Pin repository installation to the documented source commit: ```powershell git clone https://github.com/dhzyw/long-task-runner.git "$env:USERPROFILE\.agents\skills\long-task-runner" git -C "$env:USERPROFILE\.agents\skills\long-task-runner" checkout --detach 3e267399cc5db606556ecbd0ec8b3746429b790b ``` 3. Require users to verify the resulting commit: ```powershell git -C "$env:USERPROFILE\.agents\skills\long-task-runner" rev-parse HEAD ``` 4. Publish SHA-256 checksums or signed release artifacts and document a mandatory verification procedure before loading or executing the Skill. 5. Prefer immutable release archives or signed tags. Protect release publication with multi-factor authentication, branch protection, and restricted maintainer permissions. 6. Pin and audit installer dependencies through an appropriate lockfile or verified package-manager mechanism. Avoid allowing package resolution to silently select newer versions. 7. Continue advising users to inspect executable Skill content before activation, but do not rely on manual inspection as a replacement for cryptographic provenance and immutable version pinning.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (36)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description presents a broad orchestration skill for running slow local commands and queues, handling logs, recovery, artifact checks, remote jobs, and workflow handoffs. The supplied code does not implement any of that infrastructure. It is a standalone read-only media checking tool that invokes ffprobe and optionally ffmpeg against a given file to validate duration, stream types, dimensions, and decode success. While this could loosely fit under 'artifact checks,' the primary purpose is much narrower and materially different from a runner/queue system, and the other advertised capabilities are absent. Therefore the description does not accurately represent the code chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description is for a broader execution/queue management skill with safety and recovery features. The supplied code does not implement that system; it is a test fixture/demo workload generator. Its primary purpose is to simulate outcomes for another runner system to test against, including failures, bad outputs, large stdout noise, flaky behavior, process-tree escape behavior, and WAV corruption. While this loosely relates to local command testing, the described capabilities such as bounded logs, safe recovery, artifact checks, remote-job follow-up, and handoff support are absent from this code chunk. Therefore the code materially differs from the declared purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding
Most of the declared description matches the code: it does run slow local commands, persists job state on disk, bounds logs with rotation, supports cancellation/resume/recovery checks, and validates artifacts including JSON/WAV/hash/custom validators. It is appropriate for rendering, TTS, builds, and batch processing, and can execute commands that themselves submit remote jobs. However, the description also advertises 'fresh-chat handoffs' and 'reusable skills when a completed runner-assisted task is followed by independent new work.' There is nothing in the code related to chat/session handoff, skill creation/reuse, or any transition to independent follow-on work. Additionally, calling it a 'queue' system is somewhat broader than the implementation, which is a sequential job runner with resource locking rather than a general queued task service. Because these undeclared/unsupported high-level capabilities are part of the stated purpose, this is a description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
The declared description focuses on executing slow local commands and queues, artifact checking, safe recovery, and some workflow handoff behavior. In contrast, this code does not implement a runner for local commands or queues. Its primary purpose is to test remote job watching logic via HTTP loopback fixtures: it serves simulated remote job endpoints, invokes another script as a subprocess, checks expected exit codes and output artifacts, and verifies only GET polling occurred. Although artifact checking and subprocess invocation are supporting overlaps, the main behavior is materially different: network-based remote job status polling tests rather than a general local-command/queue runner. Therefore the description does not accurately represent this code chunk.

Natural-Language Policy Violations

High
Confidence
98% confidence
Finding
The skill content is written to force a specific language/locale and operating environment default without user opt-in. In security-sensitive workflows, forcing language or locale can cause user misunderstanding of commands, logs, warnings, or consent prompts, increasing the risk of operator error when shell execution and artifact validation are involved.

Direct flow: pathlib.Path.read_bytes (file read) → pathlib.Path.write_bytes (file write)

High
Category
Data Flow
Content
w.setframerate(8000)
        w.writeframes(b'\x00\x00'*8000)
    if a.mode == 'badwav':
        out.write_bytes(out.read_bytes()[:100])
elif a.mode != 'noop':
    out.write_text(json.dumps({'ok':True,'mode':a.mode}),encoding='utf-8')
Confidence
80% confidence
Finding
Data flows directly from a source (env vars, files, network) to a sink (network output, exec, file write) without intermediate validation.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
actual = [sys.executable, SCRIPT, "_child", "--", *argv]
        else:
            actual = argv
        p = subprocess.Popen(actual, cwd=cwd, env={**os.environ, **env}, stdin=subprocess.PIPE if job else subprocess.DEVNULL,
                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT, creationflags=flags,
                             start_new_session=os.name != "nt")
        if job:
Confidence
97% confidence
Finding
Merging `{**os.environ, **env}` passes the full parent process environment to untrusted child commands, which can leak API keys, cloud credentials, session tokens, SSH-related variables, and internal configuration. Because this runner is specifically designed to execute arbitrary local commands, the skill context makes this significantly more dangerous: any queued task can trivially read and exfiltrate inherited secrets.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
The README instructs users to run `npx skills add ...` without pinning an exact package version or commit for the `skills` tool. `npx` may fetch and execute the latest published package at install time, so a compromised upstream package, typo-squatted replacement, or breaking update could result in arbitrary code execution on the user's machine.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding
The README instructs users to install the skill via `npx skills add ...` without pinning the exact package version. This can cause users to fetch whatever version is current at install time, which weakens supply-chain integrity and could expose them to a malicious or compromised upstream release.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill describes and demonstrates use of local Python execution, file access, and potentially network-capable workflows, but it does not declare an explicit tool scope such as allowed-tools or permissions. That increases the chance the skill is invoked with broader capabilities than necessary, enabling command execution or file/network access beyond the intended boundary.

Vague Triggers

Medium
Confidence
87% confidence
Finding
The description advertises broad activation around fresh-chat handoffs and reusable skills, which can cause the skill to be selected in contexts beyond its core runner functionality. Overbroad activation increases the chance of unnecessary access to shell/file capabilities and may steer conversations into workflow transitions the user did not explicitly request.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The task-switch reminder is triggered by the assistant's subjective judgment about whether a prior task was complete and a new task is independent. Ambiguous triggers can be abused or simply misfire, causing unsolicited workflow changes, context shifts, or prompts to create new chats/skills that may expose extra context or alter user intent.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The entire template is written as mandatory Chinese-language content, with no indication that the user can choose another language or locale. This creates a natural-language policy concern because it appears to enforce a specific language by default rather than offering opt-in or documenting a justified locale restriction.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The entire skill file is written in Chinese and does not indicate that language selection is optional or limited to a justified region-specific context. Under the policy rule, forcing a specific language or locale without user opt-in is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The entire skill reference is written in Chinese, with no indication that the user may choose another language or that the skill is intended only for a Chinese-language or region-specific context. Under the stated policy, a language constraint without opt-in or clear justification is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This markdown file presents all operational guidance exclusively in Chinese and does not indicate that the user can choose another language. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is explicitly justified.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The entire skill instruction set is written in Chinese and includes example user-facing phrasing in Chinese, but there is no statement that the behavior is language-optional or limited to a Chinese-specific deployment. Under the policy, forcing a specific language without opt-in can be a natural-language policy violation.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
rows=[]
for mode in ['status_every_1s','bounded_wait']:
    d=root/mode
    subprocess.run([sys.executable,str(here/'make_demo.py'),'--directory',str(d),'--seconds',str(a.seconds)],check=True,capture_output=True)
    calls=[]
    def call(action,*more):
        cmd=[sys.executable,str(here/'runner.py'),action,'--job',str(d/'job'),*map(str,more)]
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def call(action,*more):
        cmd=[sys.executable,str(here/'runner.py'),action,'--job',str(d/'job'),*map(str,more)]
        before=time.monotonic()
        proc=subprocess.run(cmd,capture_output=True,timeout=40)
        calls.append({'action':action,'bytes':len(proc.stdout)+len(proc.stderr),'seconds':round(time.monotonic()-before,3)})
        if proc.returncode not in [0,3]:
            raise RuntimeError(proc.stdout.decode('utf-8','replace'))
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if not .1<=a.decode_timeout<=2592000:
            raise ValueError('Invalid decode timeout')
        with tempfile.TemporaryFile() as output:
            proc=subprocess.run([a.ffprobe,'-v','error','-show_entries','format=duration:stream=codec_type,width,height',
                                 '-of','json',str(a.path.resolve())],stdin=subprocess.DEVNULL,stdout=output,timeout=30)
            if proc.returncode!=0:
                raise ValueError('ffprobe exited '+str(proc.returncode))
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if a.width and any(s.get('width')!=a.width for s in video) or a.height and any(s.get('height')!=a.height for s in video):
            raise ValueError('Video dimensions mismatch')
        if a.decode:
            proc=subprocess.run([a.ffmpeg,'-nostdin','-v','error','-xerror','-i',str(a.path.resolve()),'-f','null',os.devnull],
                                stdin=subprocess.DEVNULL,timeout=a.decode_timeout)
            if proc.returncode!=0:
                raise ValueError('Decode failed: '+str(proc.returncode))
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Tainted flow: 'count' from pathlib.Path.read_text (line 19, file read) → pathlib.Path.write_text (file write)

Medium
Category
Data Flow
Content
if a.counter:
    cp = Path(a.counter)
    count = int(cp.read_text())+1 if cp.exists() else 1
    cp.write_text(str(count))
else:
    count = 1
if a.mode == 'tree':
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
else:
    count = 1
if a.mode == 'tree':
    child = subprocess.Popen([sys.executable,'-c',"import time; from pathlib import Path; time.sleep(4); Path('escaped-child.txt').write_text('escaped'); time.sleep(40)"])
    Path('descendant-pid.txt').write_text(str(child.pid))
if a.mode == 'noise':
    for _ in range(256):
Confidence
96% confidence
Finding
In 'tree' mode, the script deliberately spawns a descendant process that outlives the main task and later writes escaped-child.txt. In the context of a long-task runner skill, this is dangerous because it exercises process-tree escape behavior and can leave orphaned processes or side effects outside the runner’s expected lifecycle, which can bypass cleanup and confuse artifact accounting.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The spawned child writes a file later without obvious disclosure to the caller, creating a hidden asynchronous side effect. In a skill meant to validate safe recovery and artifact checks, undisclosed descendant behavior is especially risky because it can defeat assumptions about task completion, cleanup, and provenance of produced files.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
actual = [sys.executable, SCRIPT, "_child", "--", *argv]
        else:
            actual = argv
        p = subprocess.Popen(actual, cwd=cwd, env={**os.environ, **env}, stdin=subprocess.PIPE if job else subprocess.DEVNULL,
                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT, creationflags=flags,
                             start_new_session=os.name != "nt")
        if job:
Confidence
89% confidence
Finding
This code executes task-provided commands from the job spec via `subprocess.Popen`, enabling arbitrary local program execution. In the context of an agent skill, an attacker who can influence the spec can run any executable available on the host, and the inherited environment may amplify impact by exposing credentials, tokens, proxy settings, or other sensitive execution context to the spawned process.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/test_runner.py:21