Back to skill

Security audit

task-files-explorer

Security checks for vulnerabilities and agentic risk

Overview

This skill openly creates a persistent file preview service, but it also exposes task files and auto-runs project scripts on startup with too little control.

Install only if you intentionally want a persistent preview service for task files. Before enabling it, require a clear opt-in, remove the automatic bun install/db:push/dev-server block, add authentication or otherwise confirm preview URLs are access-controlled, limit exposed roots, and document how to stop and fully uninstall the boot hook, watcher, PID files, logs, and background process.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T06 · System Persistence

Error
Location
assets/dev.sh.template:142
Finding
Persistent Boot Hook and Automatic Process Resurrection<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:42-48`, `SKILL.md:71-77`, `assets/dev.sh.template:142-156`, `assets/explorer.sh:72-73` **Vulnerability Type**: Cross-session startup persistence **Risk Level**: Critical ### Vulnerable Code From `SKILL.md:42-48`: ```text ### Kasus A — container baru (belum ada .zscripts/dev.sh) 1. Salin assets ke lokasi aktif: `mkdir -p ~/.zscripts/explorer-ui` (root proyek: /home/z/my-project) `cp assets/explorer.py assets/explorer.sh <proyek>/.zscripts/` `cp assets/explorer-ui/index.html <proyek>/.zscripts/explorer-ui/` `cp assets/dev.sh.template <proyek>/.zscripts/dev.sh && chmod +x <proyek>/.zscripts/dev.sh` 2. Jalankan sekali: `bash <proyek>/.zscripts/explorer.sh --ensure` 3. Mulai sekarang setiap boot container, /start.sh menjalankan dev.sh yang menghidupkan explorer + watcher (auto-heal) secara otomatis. ``` From `assets/dev.sh.template:142-156`: ```bash # --------------------------------------------------------------------------- # 3. PASTIKAN WATCHER DAEMON HIDUP (berlaku di boot maupun run manual) # watcher.sh --ensure = no-op bila sudah jalan; double-fork orphan bila belum # -> jaring pengaman: boot hook + M0 per-session + manual, tiga jalur menuju # satu daemon # --------------------------------------------------------------------------- if [ -f "$PROJECT/.zscripts/watcher.sh" ]; then bash "$PROJECT/.zscripts/watcher.sh" --ensure >> "$BOOTLOG" 2>&1 || log "WARN: watcher --ensure gagal" fi # --------------------------------------------------------------------------- # 4. PASTIKAN TASK FILES EXPLORER HIDUP (pengganti fungsional popup preview) # explorer.sh --ensure idempoten; guard Next.js ada di dalamnya. # --------------------------------------------------------------------------- if [ -f "$PROJECT/.zscripts/explorer.sh" ]; then bash "$PROJECT/.zscripts/explorer.sh" --ensure >> "$BOOTLOG" 2>&1 || log "WARN: explorer --ensure gagal" fi ``` From `assets/explore ...[truncated 2301 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not automatically install or replace `.zscripts/dev.sh`. 2. Start the explorer only for the current session and only after explicit user approval. 3. Remove the watcher and automatic self-healing behavior. 4. Avoid `setsid`, double-forking, and other orphan-process techniques unless the user explicitly requests a persistent service and understands the implications. 5. If boot integration is genuinely required, present the exact hook changes for confirmation before applying them. 6. Pin the executable paths and verify file ownership and permissions before every startup. 7. Reject startup when `.zscripts` or its scripts are writable by untrusted users. 8. Provide a documented uninstall operation that removes the boot hook, PID files, watcher, explorer processes, and related logs. 9. Record an auditable installation manifest and require integrity verification before executing persisted scripts. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
assets/explorer.py:220
Finding
Unauthenticated Exposure of Project File Inventory and Contents<![CDATA[ ## Vulnerability Details **File Location**: `assets/explorer.py:33-41`, `assets/explorer.py:158-185`, `assets/explorer.py:220-258` **Vulnerability Type**: Missing authentication and authorization on file-serving endpoints **Risk Level**: High ### Vulnerable Code From `assets/explorer.py:33-41`: ```python # label -> path absolut (label dipakai di URL /file/<label>/... ) ROOTS = [ ("download", os.path.join(PROJECT, "download")), ("archive", os.path.join(PROJECT, "archive")), ] ROOTMAP = dict(ROOTS) BIND = "127.0.0.1" PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 3000 ``` From `assets/explorer.py:220-258`: ```python def do_GET(self): # noqa: N802 path = self.path.split("?", 1)[0] if path == "/healthz": self._send(200, "ok") return if path == "/" or path == "/index.html": try: with open(UI, "rb") as f: self._send(200, f.read(), "text/html; charset=utf-8") except OSError: self._send(500, "UI index.html tidak ditemukan") return if path == "/api/files": self._send(200, json.dumps(build_api(), ensure_ascii=False), "application/json; charset=utf-8") return if path.startswith("/file/"): rest = path[len("/file/"):] label, _, rel = rest.partition("/") fp = safe_path(label, rel) if not fp: self._send(403, "Akses file ditolak (di luar root yang diizinkan)") return size = os.path.getsize(fp) name = os.path.basename(fp) self.send_response(200) self.send_header("Content-Type", ctype_of(fp)) self.send_header("Content-Length", str(size)) self.send_header("Content-Disposition", 'inline; filename="%s"' % name.replace('"', "")) self._no_store() self.end_headers() if self.command == "HEAD": return with open(fp, "rb") as f: while True: ...[truncated 2278 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require authentication for `/api/files` and every `/file/` request. 2. Use a cryptographically random, short-lived session token rather than a static token embedded in the UI. 3. Validate authorization independently on the server for each requested file. 4. Do not expose `archive/` by default; require an explicit opt-in for each root. 5. Replace broad directory publication with an explicit allowlist of files approved for preview. 6. Confirm that the platform ingress enforces authenticated access and does not create public or broadly shared preview URLs. 7. Minimize metadata returned by `/api/files`; omit absolute paths, process IDs, and unrelated task metadata. 8. Add security headers, including an appropriate Content Security Policy, `X-Content-Type-Options: nosniff`, and a restrictive framing policy where compatible with the preview environment. 9. Log authenticated access events without recording sensitive tokens or file contents. ]]>

T08 · Insecure Dependencies

Error
Location
assets/dev.sh.template:80
Finding
Automatic Execution of Unreviewed Package Lifecycle and Project Scripts<![CDATA[ ## Vulnerability Details **File Location**: `assets/dev.sh.template:80-99` **Vulnerability Type**: Unsafe automatic dependency installation and package-script execution **Risk Level**: High ### Vulnerable Code ```bash if [ -f "$PROJECT/package.json" ]; then log "package.json terdeteksi -> delegasi flow fullstack standar" cd "$PROJECT" || true bun install >> "$BOOTLOG" 2>&1 || log "WARN: bun install gagal" bun run db:push >> "$BOOTLOG" 2>&1 || log "WARN: db:push gagal" nohup bun run dev >> "$BOOTLOG" 2>&1 & log "Next.js dev server dinyalakan di background" for d in "$PROJECT"/mini-services/*/; do [ -f "${d}package.json" ] || continue ( cd "$d" || exit 0 bun install >> "$BOOTLOG" 2>&1 nohup bun run dev >> "$BOOTLOG" 2>&1 & ) log "mini-service dinyalakan: $d" done fi ``` ### Technical Analysis The persistent boot hook treats the existence of any root-level `package.json` as authorization to install dependencies and execute package-defined scripts. It runs `bun install`, `bun run db:push`, and `bun run dev` in the root project, then repeats installation and development-server execution for every matching mini-service. Dependency installation can execute package lifecycle hooks. The `db:push` and `dev` commands are resolved from project-controlled `package.json` scripts. Consequently, these operations execute code that is outside the reviewed Skill package and whose behavior can change after the Skill has been audited. The code does not enforce a frozen lockfile, dependency integrity policy, trusted registry, script allowlist, or explicit confirmation. It also runs automatically from a persistent boot hook, increasing the likelihood and repeatability of exploitation. ### Attack Path 1. An attacker compromises a dependency referenced by the project, modifies a package source, or gains the ability to alter a root or mini-service `package.jso ...[truncated 989 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove full-stack project startup and dependency management from this file-explorer Skill because those actions are not required for its core functionality. 2. Never run `bun install`, database commands, or package scripts automatically merely because `package.json` exists. 3. Require explicit user approval for each dependency installation and package-script invocation. 4. Enforce a committed lockfile and use frozen or immutable installation mode. 5. Configure an allowlist of trusted registries and verify package integrity. 6. Disable lifecycle scripts during installation where practical, enabling only individually reviewed scripts. 7. Review the exact definitions of `db:push` and `dev` before execution. 8. Run package scripts in a restricted environment with minimal filesystem, network, database, and credential access. 9. Do not start every discovered mini-service automatically; require an explicit service manifest. 10. Separate database migration privileges from normal development-server privileges and require confirmation before schema changes. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (15)

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The user-facing README text is written in Indonesian ('Pengganti fungsional', 'lihat', 'buka') with no indication that this skill is intentionally region-specific or that other language options are available. This can violate language/locale policy because it imposes a specific language on users without opt-in.

Lp3

Medium
Category
MCP Least Privilege
Confidence
97% confidence
Finding
The skill instructs the agent to copy files, modify startup hooks, launch shell scripts, and run a local HTTP server, but it declares no explicit tool scope or permission boundaries. That mismatch is dangerous because the skill can perform persistent filesystem changes, execute commands, and expose task files over the preview ingress without any documented constraint or user-consent guardrail.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The title and usage instructions are presented partly in Indonesian while also referencing English, which can impose a language expectation on users without explicit opt-in. The policy for this audit flags language or locale constraints when the skill does not clearly offer a choice or justify the locale requirement.

Session Persistence

Medium
Category
Rogue Agent
Content
### Kasus A — container baru (belum ada .zscripts/dev.sh)
1. Salin assets ke lokasi aktif:
   `mkdir -p ~/.zscripts/explorer-ui` (root proyek: /home/z/my-project)
   `cp assets/explorer.py assets/explorer.sh <proyek>/.zscripts/`
   `cp assets/explorer-ui/index.html <proyek>/.zscripts/explorer-ui/`
   `cp assets/dev.sh.template <proyek>/.zscripts/dev.sh && chmod +x <proyek>/.zscripts/dev.sh`
Confidence
95% confidence
Finding
The skill is explicitly designed to survive container restarts by writing into persistent startup locations and re-launching itself automatically via /start.sh and watcher logic. This persistence is dangerous because it creates a durable execution foothold that can continue serving files or running code after the original session ends, reducing operator visibility and making accidental or unauthorized long-term exposure more likely.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# dev.sh — PERSISTENT BOOT HOOK (dijalankan otomatis oleh /start.sh setiap boot)
#
# Dipanggil oleh /start.sh:
#   sudo -u z bash /home/z/my-project/.zscripts/dev.sh
#
# TUJUAN:
#   1. MITIGASI POPUP "All files in task": panel & popup preview di sisi
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The boot hook expands far beyond a file-explorer skill by automatically running dependency installation, database migration, and starting application and mini-service dev servers whenever package.json exists. This increases the attack surface and can execute unreviewed project scripts on boot, which is risky because package manager lifecycle scripts and dev commands may perform network access, code execution, or persistent changes without explicit user consent.

Session Persistence

Medium
Category
Rogue Agent
Content
cd "$PROJECT" || true
    bun install        >> "$BOOTLOG" 2>&1 || log "WARN: bun install gagal"
    bun run db:push    >> "$BOOTLOG" 2>&1 || log "WARN: db:push gagal"
    nohup bun run dev  >> "$BOOTLOG" 2>&1 &
    log "Next.js dev server dinyalakan di background"
    for d in "$PROJECT"/mini-services/*/; do
        [ -f "${d}package.json" ] || continue
Confidence
90% confidence
Finding
Starting 'bun run dev' with nohup in a boot hook creates a persistent background process that survives the invoking session and auto-runs on container boot. In the context of a file-explorer skill, this persistence is more dangerous because it can keep unreviewed project code continuously executing, consuming resources, exposing services, or masking unintended behavior behind an unrelated feature.

Session Persistence

Medium
Category
Rogue Agent
Content
(
            cd "$d" || exit 0
            bun install >> "$BOOTLOG" 2>&1
            nohup bun run dev >> "$BOOTLOG" 2>&1 &
        )
        log "mini-service dinyalakan: $d"
    done
Confidence
90% confidence
Finding
The mini-service loop persistently starts additional background dev processes via nohup for every matching subproject, multiplying the amount of unattended code execution. This broad automatic persistence is particularly risky because a single boot can fan out into multiple long-lived services from repository content that may not have been reviewed or expected by the user.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The script automatically moves files from download/ to archive/ during boot, which changes user-visible task artifacts without an execution-time prompt. Even though it targets certain patterns, this can hide outputs, interfere with user workflows, and cause confusion or loss of expected accessibility, especially because it runs persistently on every container start.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The document root sets `lang="id"`, and the interface text throughout the file is written in Indonesian, indicating a fixed language choice. Under the policy, forcing a specific language without user opt-in or a documented region-specific justification is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The formatter uses `toLocaleString("id-ID", ...)`, which hard-codes Indonesian locale conventions for date and time display. This enforces a locale policy choice in the UI without exposing a user preference or documenting a justified regional limitation.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The file contains operational descriptions and command/status text in Indonesian, such as the header comments and messages like "kesehatan" and "dihentikan." Because the skill does not offer a language opt-in or state that it is intentionally limited to Indonesian users, this is a natural-language locale policy issue.

Session Persistence

Medium
Category
Rogue Agent
Content
exit 1
    fi
    echo "[$(date '+%F %T')] explorer.sh start (double-fork orphan)" >> "$LOG"
    ( setsid python3 "$PY" "$PORT" >> "$LOG" 2>&1 & )
    sleep 1
    if alive; then
        echo "[explorer] HIDUP di :$PORT (pid $(cat "$PIDFILE" 2>/dev/null))"
Confidence
91% confidence
Finding
The script launches the Python service with setsid in the background as a detached orphan process, explicitly designed to survive shell/session termination and to auto-restart via related boot/watcher paths described in the skill. In this skill context, that persistence is more dangerous because it establishes a long-lived service on 127.0.0.1:3000 and can survive normal task lifecycle expectations, making unauthorized or hard-to-remove behavior harder to detect and stop.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The script's natural-language instructions, comments, and several user-facing log messages are written in Indonesian, which can impose a language expectation without user opt-in. The file does not indicate that the locale is intentional, optional, or limited to an Indonesian-specific context.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
The live clock uses `toLocaleTimeString("id-ID")`, which fixes the locale for time presentation. This is another instance of mandatory locale selection without opt-in, contrary to the stated policy requirements.

Static analysis

No suspicious patterns detected.