Back to skill

Security audit

Local UIs

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its local-UI discovery purpose, but needs review because its scanner can be redirected outside localhost and saves sensitive local service metadata to disk.

Review before installing in sensitive environments. Run with --no-open if you do not want a browser launched, avoid sharing the generated dashboard, and be aware that redirects or proxy settings may cause network requests beyond localhost despite the primary skill text saying otherwise.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scan_uis.py:65
Finding

Loopback Probe Can Escape to Arbitrary Hosts Through HTTP Redirects

Content
View full analysis

Vulnerability Details

File Location: scan_uis.py:65-68
Vulnerability Type: Server-Side Request Forgery through unrestricted redirect following
Risk Level: Medium

Vulnerable Code

python
url = f"http://127.0.0.1:{port}/"
req = urllib.request.Request(url, headers={"User-Agent": "local-uis-scan"})
try:
    with urllib.request.urlopen(req, timeout=1.4) as r:
        status = r.status

Technical Analysis

The initial URL is restricted to 127.0.0.1, but urllib.request.urlopen follows HTTP redirects by default. It also uses the standard environment-aware proxy configuration. The code does not validate redirect destinations or ensure that each resulting connection remains on a loopback address.

Consequently, a locally listening HTTP service can return a redirect to an arbitrary external or internal host. This contradicts the assertion in SKILL.md:31 that the tool does not probe other hosts. The limitation is acknowledged separately in README.md:53-54, but no technical control enforces the intended boundary.

The request uses a fixed HTTP GET operation and does not explicitly attach credentials. Nevertheless, redirect-driven requests can reach services available from the victim machine, including private network resources that are inaccessible to the attacker directly.

Attack Path

  1. An attacker starts or compromises an HTTP service listening on a local port.
  2. lsof identifies the port, and the scanner sends a request to http://127.0.0.1:<port>/.
  3. The malicious service responds with a 30x status and an attacker-selected Location header.
  4. urllib.request.urlopen follows the redirect without validating the destination.
  5. The scanner connects to the selected external host, private-network service, or other non-loopback destination using the victim machine's network access.
  6. The destination receives the request, and a state-changing endpoint could potentially ...[truncated 802 chars]
Remediation
View remediation

Remediation Suggestions

  1. Construct a custom urllib opener that disables automatic redirects.
  2. Disable environment-derived proxy handling by installing an empty ProxyHandler.
  3. If redirects are required, validate every redirect destination before following it:
    • Require the http scheme.
    • Resolve the hostname.
    • Require every resolved address to be loopback.
    • Reject credentials, malformed authorities, and non-loopback IPv4 or IPv6 addresses.
  4. Apply the destination validation again after DNS resolution and immediately before connection to reduce resolution-based bypasses.
  5. Add tests covering redirects to public addresses, private network addresses, IPv6 addresses, and proxy-configured environments.
  6. Update SKILL.md so its safety claims accurately match the implemented guarantees.

A hardened implementation should use a no-redirect, no-proxy opener unless redirect support is essential.

T08 · Insecure Dependencies

Warning
Location
README.md:31
Finding

Installation Instructions Execute Mutable and Unpinned Remote Components

Content
View full analysis

Vulnerability Details

File Location: README.md:31
Vulnerability Type: Unpinned remote installer and mutable Skill source
Risk Level: Medium

Vulnerable Code

bash
npx skills add AntreasAntoniou/local-uis

Technical Analysis

The documented installation command invokes npx without pinning the skills package to a reviewed version. Depending on the local environment and package availability, npx can retrieve and execute the current package release from a remote registry.

The Skill source is also identified by a mutable repository name rather than a specific release, tag, or commit digest. The effective installer and installed content can therefore change after this repository revision has been audited.

This is a supply-chain weakness rather than evidence that the current repository contains malicious code. Exploitation requires compromise, malicious replacement, or unexpected modification of an upstream package, account, or mutable repository reference.

Attack Path

  1. An attacker compromises the registry package used by npx, its publisher account, or the referenced repository account.
  2. The attacker publishes a malicious installer release or modifies the content resolved by the mutable Skill reference.
  3. A user follows the documented installation command.
  4. npx retrieves and executes the unpinned installer under the user's account.
  5. The installer downloads or activates attacker-controlled Skill content.
  6. The malicious installer or Skill gains the ability to perform actions available to the invoking user.

Impact Assessment

If an upstream dependency or source is compromised, malicious installer code could execute with the privileges of the user running the command. Potential consequences include:

  • Reading or modifying files accessible to that user.
  • Stealing user-level credentials or tokens available in the execution environment.
  • Installing altered Skill ...[truncated 340 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin the npx package to an explicitly reviewed version, such as npx skills@X.Y.Z.
  2. Pin the Skill source to an immutable commit digest or signed release rather than a mutable repository reference.
  3. Publish and verify checksums or cryptographic signatures for released artifacts.
  4. Use npx --no-install when installation from the network is not intended and the trusted tool is already present.
  5. Document which remote components are downloaded and which code executes during installation.
  6. Recommend inspecting the resolved package and Skill content before activation in sensitive environments.
  7. Configure continuous dependency and release-integrity monitoring for the installer and repository.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (6)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SECURITY.md (reported line 3)May include surrounding context.

md
# Security

Please report vulnerabilities privately through GitHub's security advisory interface. Do not include credentials, private documents, access tokens, internal hostnames, or personal paths in a public issue.

This project provides agent instructions and local helpers. It is not a sandbox, an authorization system, or a guarantee that an external service is secure.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill invokes a Python scanner that reads local listeners, performs HTTP probes, writes a dashboard file, and may open it, but the manifest declares no explicit tool scope or permissions. That mismatch creates an authorization and review gap: an agent or user cannot easily tell from the skill metadata that shell, network, file-read, and file-write capabilities are required, increasing the chance of over-broad or unexpected execution.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
76% confidence
Finding

The skill creates a persistent artifact at ~/.local/state/local-uis/dashboard.html containing page titles, ports, process names, and PIDs from local services. This data can reveal sensitive local application metadata across sessions, and the optional browser-opening behavior increases the chance of exposing that information to other local users, logs, or follow-on tools that consume the saved file.

Content

Scanner excerpt · SKILL.md (reported line 16)May include surrounding context.

python3 scan_uis.py

text

Use `--no-open` to create the launcher without opening it, or `--json` for machine-readable results.

The scanner:

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 · scan_uis.py (reported line 36)May include surrounding context.

python
def listening_ports():
    """Return {port: {'pid','cmd'}} for TCP listeners on loopback/all-interfaces."""
    try:
        raw = subprocess.run(
            ["lsof", "-nP", "-iTCP", "-sTCP:LISTEN"],
            capture_output=True, text=True, timeout=15,
        ).stdout

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 · scan_uis.py (reported line 172)May include surrounding context.

python
if "--no-open" not in args:
        opener = shutil.which("open") or shutil.which("xdg-open")
        if opener:
            subprocess.run([opener, str(path)], check=False)
        else:
            print("  no supported browser opener found; use the file URL above", file=sys.stderr)

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
tests/test_scan_uis.py:10