Back to skill

Security audit

Long Task Runner

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed local long-running command runner with meaningful operational risks but no artifact-backed hidden, destructive, or exfiltrating behavior.

Install only from a reviewed commit or pinned package version, inspect the scripts before first use, and treat any job spec as equivalent to running those commands yourself. Avoid running untrusted specs, be aware launched commands inherit your local environment, and use separate job directories with explicit timeouts and artifact checks.

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:15
Finding

Unpinned Installer and Mutable Repository Installation

Content
View full analysis
Remediation
View remediation
add dhzyw/long-task-runner --skill long-task-runner --agent codex ``` 2. Record and verify the npm package integrity digest or obtain the package through a trusted lockfile-controlled installation process. 3. Install the repository at the documented audited 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 ``` 4. Prefer downloading a commit-specific archive and verifying a published SHA-256 digest or cryptographic signature before copying it into the agent's Skill directory. 5. Inspect the installed `SKILL.md`, agent metadata, and executable scripts after installation and before first use. 6. Document an update procedure that requires reviewing changes and explicitly selecting a new commit instead of silently tracking the default branch. ]]>
Vulnerability Patterns
  • 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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Claiming a general-purpose long-task runner while actually centering other testing or watcher behavior can mislead users into granting trust and execution latitude that the implementation has not earned. In a skill that coordinates shell commands and possible remote jobs, deceptive or inaccurate descriptions materially increase the chance of misuse and unreviewed side effects.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Claiming a general-purpose long-task runner while actually centering other testing or watcher behavior can mislead users into granting trust and execution latitude that the implementation has not earned. In a skill that coordinates shell commands and possible remote jobs, deceptive or inaccurate descriptions materially increase the chance of misuse and unreviewed side effects.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Claiming a general-purpose long-task runner while actually centering other testing or watcher behavior can mislead users into granting trust and execution latitude that the implementation has not earned. In a skill that coordinates shell commands and possible remote jobs, deceptive or inaccurate descriptions materially increase the chance of misuse and unreviewed side effects.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill content is written as a direct language constraint in Chinese, including a platform default, without offering the user a language choice or documenting a justified locale restriction. Under the policy, forcing a specific language or locale without opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

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

High
Category
Data Flow
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.

Content

Scanner excerpt · scripts/demo_task.py (reported line 45)May include surrounding context.

python
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')

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
93% confidence
Finding

The child environment is built from the full parent os.environ plus user-controlled overrides, which can expose secrets such as API keys, tokens, credentials, proxy settings, and cloud metadata configuration to every launched command. In a skill explicitly designed to run arbitrary local commands, this materially increases the blast radius because any executed task can read and exfiltrate inherited secrets.

Content

Scanner excerpt · scripts/runner.py (reported line 305)May include surrounding context.

python
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:

Rp1

Medium
Category
MCP Rug Pull
Confidence
89% confidence
Finding

The installation command uses npx skills without pinning an exact package version, so users may fetch whatever package version is current at execution time. If the npm package is compromised, unpublished/replaced, or a new malicious version is published, running the install command could execute attacker-controlled code on the local machine during skill installation.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding

The installation command uses npx skills without pinning an exact package version, so the resolved code can change over time or be replaced via a compromised dependency publication path. Because this skill is specifically instructing users how to install and invoke tooling, an attacker who controls or hijacks the package supply chain could cause arbitrary code execution on the user's machine at install/run time.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill describes behavior that entails shell execution, file access, environment use, and potentially networked remote-job handling, but it does not declare any explicit tool scope or permission boundaries. In an agent system, this increases the chance that the skill is invoked with broader capabilities than intended, enabling command execution or data access without clear least-privilege constraints.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The invocation scope is broad enough to match many generic tasks such as builds, rendering, batch processing, remote jobs, and handoffs, which can cause over-selection of a skill with powerful execution semantics. Over-broad matching is dangerous because it may route unrelated user requests into a shell-capable workflow and expand operational reach beyond what is necessary.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The entire skill reference is written in Chinese and does not indicate that users may choose another language or that the skill is intentionally limited to a Chinese-speaking context. Under the policy, imposing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This markdown file presents all user-facing guidance in Chinese and does not indicate that the user can choose another language or that the skill is intentionally limited to a Chinese-speaking context. That creates a natural-language policy concern because it implicitly forces a specific language without opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The entire document is written in Chinese and provides no indication that users may choose another language or locale. Under the policy, forcing a specific language without user opt-in is a natural-language policy concern unless the locale restriction is clearly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file is written entirely in Chinese and includes example user-facing prompts, but it does not instruct the agent to match the user's language or provide multilingual fallbacks. In a general-purpose task handoff skill, this can cause the assistant to unexpectedly switch languages, confusing users and leading to misunderstandings about workflow choices such as starting a new chat or creating a reusable skill.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/benchmark.py (reported line 23)May include surrounding context.

python
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)]

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/benchmark.py (reported line 28)May include surrounding context.

python
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'))

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/check_media.py (reported line 31)May include surrounding context.

python
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))

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
74% confidence
Finding

The ffmpeg decode path executes a full decode of attacker-controlled media using an external parser/decoder, which expands the attack surface beyond metadata inspection. Although shell injection is mitigated by passing arguments as a list and stdin is disabled, malformed media can still trigger denial of service or potentially exploit vulnerabilities in ffmpeg/libavcodec, and the allowed timeout can be very large.

Content

Scanner excerpt · scripts/check_media.py (reported line 50)May include surrounding context.

python
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))

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

Medium
Category
Data Flow
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.

Content

Scanner excerpt · scripts/demo_task.py (reported line 20)May include surrounding context.

python
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':

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/demo_task.py (reported line 24)May include surrounding context.

python
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):

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
91% confidence
Finding

This code executes arbitrary commands from the job spec via subprocess.Popen. Although it avoids shell injection by using an argv list, the skill's purpose is to run user-specified local commands, so an attacker controlling the spec can achieve arbitrary code execution in the runner's security context and also inherit sensitive ambient privileges and files accessible to that account.

Content

Scanner excerpt · scripts/runner.py (reported line 305)May include surrounding context.

python
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:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/runner.py (reported line 595)May include surrounding context.

python
def spawn_worker(job, state):
    flags = (subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP) if os.name == "nt" else 0
    p = subprocess.Popen([sys.executable, SCRIPT, "_worker", str(job), state["token"]],
                         stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
                         creationflags=flags, start_new_session=os.name != "nt", close_fds=True)
    # It is deliberately detached; no model/API/wakeup command exists here.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/runner.py (reported line 658)May include surrounding context.

python
if sys.stdin.buffer.read(1) != b"G":
            return 125
        try:
            return subprocess.call(sys.argv[3:], stdin=subprocess.DEVNULL)
        except OSError as e:
            print(f"E_EXEC: {e}", file=sys.stderr)
            return 127

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/test_remote.py (reported line 62)May include surrounding context.

python
output=root/(name+'.json')
    cmd=[sys.executable,str(Path(__file__).with_name('remote_watch.py')),'--url',f'http://127.0.0.1:{server.server_port}/{name}',
         '--job-id','job-1','--output',str(output),'--interval','1','--timeout','4' if name!='timeout' else '1.2']
    p=subprocess.run(cmd,capture_output=True,timeout=10)
    assert p.returncode==expected,(name,p.stdout,p.stderr)
    assert output.exists()==(expected==0),(name,'unexpected artifact state')
    if expected==0:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/test_runner.py (reported line 26)May include surrounding context.

python
def cli(*args):
    start = time.monotonic()
    p = subprocess.run([sys.executable, str(RUNNER), *map(str,args)], capture_output=True, timeout=60)
    CALLS.append({'action':args[0], 'bytes':len(p.stdout)+len(p.stderr), 'seconds':round(time.monotonic()-start,4)})
    try:
        return p.returncode, json.loads(p.stdout)