Private Web App (PWA)

Security checks across malware telemetry and agentic risk

Overview

PrivateApp is a coherent personal dashboard, but it exposes powerful local-file, plugin-code, and host shutdown controls with weak scoping and no visible authentication.

Install only if you are comfortable administering a personal server with local-file access, executable plugins, and host power controls. Before running it, bind to localhost or protect it with strong authentication and firewall/Tailscale ACLs, avoid using your whole home directory as the file root, review any plugin path before enabling it, and consider removing or disabling the reboot/shutdown endpoints.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (32)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
async def action_shutdown():
    """Shutdown the system."""
    try:
        subprocess.Popen(["sudo", "shutdown", "-h", "now"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        return {"status": "ok", "message": "System is shutting down..."}
    except Exception as e:
        raise HTTPException(500, f"Failed to shutdown: {e}")
Confidence
99% confidence
Finding
subprocess.Popen(["sudo", "shutdown", "-h", "now"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"""Restart the system."""
    try:
        if _IS_MACOS:
            subprocess.Popen(["sudo", "shutdown", "-r", "now"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        else:
            subprocess.Popen(["sudo", "reboot"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        return {"status": "ok", "message": "System is restarting..."}
Confidence
99% confidence
Finding
subprocess.Popen(["sudo", "shutdown", "-r", "now"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if _IS_MACOS:
            subprocess.Popen(["sudo", "shutdown", "-r", "now"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        else:
            subprocess.Popen(["sudo", "reboot"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        return {"status": "ok", "message": "System is restarting..."}
    except Exception as e:
        raise HTTPException(500, f"Failed to restart: {e}")
Confidence
99% confidence
Finding
subprocess.Popen(["sudo", "reboot"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

Tainted flow: 'req' from os.environ.get (line 90, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
data=data,
            headers={"Content-Type": "application/json"},
        )
        with urllib.request.urlopen(req, timeout=10) as resp:
            return resp.status == 200

    except Exception as e:
Confidence
92% confidence
Finding
with urllib.request.urlopen(req, timeout=10) as resp:

Tainted flow: 'req' from os.environ.get (line 90, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
data=data,
            headers={"Content-Type": "application/json"},
        )
        with urllib.request.urlopen(req, timeout=10) as resp:
            return resp.status == 200

    except Exception as e:
Confidence
92% confidence
Finding
with urllib.request.urlopen(req, timeout=10) as resp:

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill documentation directs the agent to clone repositories, run shell installers, manage services, build code, edit config files, and interact with networked endpoints, but it declares no permissions. This creates a capability transparency problem: users and policy systems are not warned that the skill can read/write files, execute shell commands, access environment data, and make network requests.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The documented purpose frames the skill as a dashboard setup/management tool, but the referenced behavior includes much more sensitive functionality: file browsing/sharing, system and service introspection, host restart/shutdown actions, optional remote-access setup, and outbound communications. This mismatch can cause users to authorize a skill without understanding that it may expose local files, disclose system state, or perform disruptive host-level operations.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The file-browser defaults its root to the entire current user's home directory, and the exposed endpoints allow listing directories, reading file contents, and downloading files anywhere under that root. In a dashboard/server context, this creates broad local file disclosure if the app is reachable by an unintended user, lacks strong auth, or is exposed through another component, making the default far more permissive than necessary.

Description-Behavior Mismatch

Low
Confidence
87% confidence
Finding
The implementation returns absolute filesystem paths in /list and allows file content reading and download from the configured root, while the documentation describes a generic file browser without highlighting this sensitivity. Exposing absolute paths leaks environment structure and usernames, which aids attackers in targeting valuable files, and combined with read/download functionality increases the consequences of any access-control weakness.

Intent-Code Divergence

Medium
Confidence
99% confidence
Finding
The markdown renderer explicitly passes through raw HTML lines unchanged, then injects the rendered result with dangerouslySetInnerHTML. Because file contents are attacker-controlled in a file browser context, a malicious markdown file can include active HTML such as script-capable payloads, event handlers, or dangerous links, leading to XSS in the frontend.

Description-Behavior Mismatch

High
Confidence
100% confidence
Finding
The System Monitor routes include reboot and shutdown actions, which are destructive host-control operations unrelated to read-only monitoring. Exposing such capability in a monitoring component broadens attack surface and turns compromise of this app into immediate host-level denial of service.

Context-Inappropriate Capability

High
Confidence
100% confidence
Finding
A monitoring app that can reboot or power off the host violates least privilege and creates a severe mismatch between expected and actual capability. That context makes the behavior more dangerous because operators may expose the app broadly for observability, unintentionally exposing host shutdown functions too.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
The frontend includes a generic action dispatcher that issues POST requests to host-control endpoints such as restart and shutdown. Even with a confirmation dialog, exposing destructive machine-control operations in a monitoring UI expands the attack surface significantly: any user with access to this page, or any web attack that can trigger same-origin requests, may be able to disrupt host availability.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The UI renders explicit Restart and Shutdown buttons for the host, which is unjustified for a dashboard described primarily as a personal PWA server with plugin apps and system monitoring. This creates a direct denial-of-service capability: if the interface is exposed to unintended users or abused through web-layer weaknesses, an attacker can forcibly reboot or power off the system.

Intent-Code Divergence

Medium
Confidence
91% confidence
Finding
The page explicitly advertises 'secured by Tailscale — no auth required' while also exposing state-changing actions such as saving preferences and triggering a push test. If the backend actually relies only on network location or tailnet membership, any reachable user or compromised device on that network could modify settings or trigger actions without per-user authentication, which weakens trust boundaries and can enable unauthorized use.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The loader dynamically imports and executes backend/routes.py from app directories discovered on disk, including user-local and user-configured paths. This is arbitrary code execution within the server process, so anyone able to place or influence a plugin directory can run code with the application's privileges; that exceeds simple plugin metadata discovery and is especially risky because startup/rescan triggers execution automatically.

Context-Inappropriate Capability

High
Confidence
94% confidence
Finding
add_discovery_path accepts an arbitrary filesystem path, stores it, creates the directory, and later discovery/import logic scans those locations for apps and executes their Python route modules. That turns a configuration feature into a code-loading primitive from attacker-controlled locations, broadening the trust boundary well beyond the built-in app directory.

Description-Behavior Mismatch

Medium
Confidence
90% confidence
Finding
The installer expands its scope beyond setting up PrivateApp by optionally installing and configuring Tailscale, including exposing the local service over HTTPS. That increases the attack surface and can publish a service bound to 0.0.0.0 to a network path outside the local machine, which is riskier in an install script than a separate, explicit networking step.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The script installs unrelated third-party software by downloading and executing Tailscale's remote installer via a shell pipeline. This is dangerous because it grants arbitrary code from the network immediate execution on the host during application setup, creating a supply-chain and remote-code-execution risk.

Intent-Code Divergence

Medium
Confidence
78% confidence
Finding
The script tells the user the VAPID email is 'never sent anywhere,' but push notification infrastructure typically uses VAPID contact metadata in interactions with external push services. Misrepresenting privacy behavior can cause users to disclose data under false assumptions and undermines informed consent.

Description-Behavior Mismatch

Medium
Confidence
85% confidence
Finding
The default configuration gives the file-browser app access to the user's home directory, which can expose far more data than needed for a personal dashboard server. In this codebase, plugin apps are dynamically loaded and mounted, so broad filesystem access increases the blast radius if a plugin is vulnerable or if the server is reachable by other users on the network.

Description-Behavior Mismatch

Medium
Confidence
88% confidence
Finding
The discovery-path management API lets clients add arbitrary filesystem paths that will be scanned for apps, and elsewhere the server dynamically imports backend/routes.py from discovered app directories. That creates a path from remote API access to loading attacker-controlled code from local or mounted paths, which is especially risky because the service listens on 0.0.0.0 and uses permissive CORS.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The documentation advertises a Files app that can browse, preview, and share files, yet it provides no warning that personal data may become accessible over HTTP from the configured root. In this skill's context, that omission is meaningful because the example configuration points the file browser at the user's home directory, increasing the chance of unintentionally exposing sensitive documents.

Missing User Warnings

High
Confidence
97% confidence
Finding
The example configuration binds the service to `0.0.0.0`, exposing it on all network interfaces, but gives no warning about LAN/WAN reachability or the risks of unauthenticated access to dashboard, file, and control endpoints. In this context that is especially dangerous because the service appears to include sensitive functions such as file browsing, system telemetry, and possibly restart/shutdown operations.

Missing User Warnings

High
Confidence
98% confidence
Finding
The restart endpoint performs an immediately destructive action without any visible confirmation, secondary check, or warning in this file. If reachable via browser-based session context or accidental invocation, it can disrupt service availability instantly.

VirusTotal

66/66 vendors flagged this skill as clean.

View on VirusTotal