← All MCP servers
MCP server

io.github.uxloom-dev/uxloom

mcp:uxloom-dev/uxloom

Agent-native UI/UX design validation: journey completeness, state coverage, and WCAG checks.

Verdict
Suspicious

Risky behavior the analysis could not rule out.

Analyzed Oct 26, 2026, 12:58 UTC at 4c8c1e3
3
findings
high
highest severity
3
threat classes
155
files scanned
1,803/1,803
checks satisfied
0
package advisories

Why this verdict

mcp-server . Suspicious
  • benign: 908 checks satisfied, no findings for mcp-server:.
mcp-server packages/mcp-server Suspicious
  • suspicious: finding mcp-server:packages/mcp-server:packages/mcp-server/src/preview.ts:416:MANIP
  • suspicious: finding mcp-server:packages/mcp-server:packages/mcp-server/src/preview.ts:416:PERSIST
  • suspicious: finding mcp-server:packages/mcp-server:packages/mcp-server/src/workspace.ts:252:HIJACK
skill packages/mcp-server/skills/uxloom No issues found
  • benign: 174 checks satisfied, no findings for skill:packages/mcp-server/skills/uxloom

Security findings 3

Persistence

highContextual riskmedium confidence

The preview HTTP server listens on all interfaces with no host restriction, and its state-changing POST endpoints (/edit, /comments, /comments/assign, /comments/resolve) have no origin, Host or auth checks, so any LAN peer or web page (cross-site POST or DNS rebinding) can rewrite the project contract file and comments sidecar that agents consume.

server.listen(port);
vector:code
Counter-argument considered

All-interface binding combined with unauthenticated write endpoints lets any LAN or cross-site peer rewrite the contract and comments sidecar that agents consume; nothing in the artifact mitigates this.

Manipulation

mediumContextual risklow confidence

The preview HTTP server calls listen(port) without a host, so it binds on all interfaces and serves unauthenticated, CORS-unchecked POST /edit and /comments endpoints that write the project file and comments sidecar, letting any LAN host or web page via DNS rebinding or CSRF tamper with the design contract.

server.listen(port);
vector:code
Counter-argument considered

listen(port) with no host binds all interfaces, and the state-changing POST endpoints have no auth or origin checks, while the console advertises only localhost; the exposure is real and undisclosed.

Agent hijacking

mediumContextual risklow confidence

Comment text posted through the unauthenticated preview endpoint /comments is stored in the comments sidecar and later embedded verbatim in findings messages that direct the agent to act on it, so a network attacker can inject instructions into the agent's work queue.

message: `Reviewer comment on ${c.screen}#${c.state} (ASSIGNED TO AGENT): "${c.text}"`,
vector:code
Counter-argument considered

Comment text from the unauthenticated preview /comments endpoint is embedded verbatim into findings that instruct the agent to act on it, a concrete injection chain that nothing sanitizes or authenticates.

Refuted findings 11

Candidates the review stage examined and rejected, kept for transparency.

Persistence

highRefutedlow confidence

The opt-in agent eval script writes an MCP config (.mcp.json) into a freshly created temp workspace so a spawned `claude` CLI loads the local uxloom server; the write is confined to a mkdtemp directory and does not touch the user's real agent config.

writeFileSync(join(ws, ".mcp.json"), JSON.stringify({
Why it was refuted

Opt-in dev bench script writes .mcp.json only into a fresh mkdtemp workspace under tmpdir, never the user's real agent config, so there is no harm.

Persistence

highRefutedmedium confidence

The `uxloom init` command writes the agent MCP config (.mcp.json) with an unpinned `npx -y uxloom` server entry and copies skill files into agent skill directories; this is undeclared in the MCP tool list, though disclosed in code comments and consistent with the init purpose.

const serverEntry = { command: "npx", args: ["-y", "uxloom"] };
Why it was refuted

The `uxloom init` command is a user-invoked CLI whose documented purpose is to register the MCP server and install skills; it is not an undeclared write, and the entry points at the artifact's own package.

Persistence

highRefutedlow confidence

The `uxloom init` command writes the MCP server registration into ./.mcp.json and installs skill files into agent directories (.claude/skills, .agents/skills), which are agent control-plane writes, though they are the documented purpose of the command.

registers the MCP server in ./.mcp.json (created or merged)
Why it was refuted

The writes are the documented core purpose of `uxloom init`, run only when the user invokes it, and are merge-only without overwriting.

Code execution

highRefutedlow confidence

loadPlaywright evaluates a fixed-literal dynamic import through `new Function` to load an optional Playwright module at runtime. The string is constant with no untrusted input, but the module is resolved from the local environment.

new Function('return import("playwright")')
Why it was refuted

The Function body is a constant literal import of "playwright" with no untrusted input, disclosed in the file header; it fails silently when Playwright is absent.

Code execution

highRefutedlow confidence

Playwright is loaded via an indirect dynamic import built with `new Function(...)`, which evaluates a constructed string at runtime and loads whatever module resolves; the specifier is not visible in the shown unit.

`new Function("return import(...)")()`
Why it was refuted

The shown function unit has a fixed literal specifier "playwright", and the mechanism is openly documented in the header; no constructed or attacker-controlled string.

Persistence

highRefutedlow confidence

The design_audit tool lets the agent supply a scaffold path that is resolved relative to the project directory and written with JSON derived from design-export frame names. Any non-existing file path can be created, with no confinement to the workspace.

writeFileSync(out, JSON.stringify(result.scaffold, null, 2) + "\n");
Why it was refuted

The scaffold write is the declared capability of design_audit, refuses to overwrite existing files, and writes only the computed scaffold JSON.

Data exfiltration

highRefutedlow confidence

The server makes an undeclared outbound network call to registry.npmjs.org for an update check (with a local cache in ~/.cache/uxloom), though it is disclosed in code comments, sends no local data, fails silently, and can be disabled via UXLOOM_NO_UPDATE_CHECK.

https://registry.npmjs.org/-/package/uxloom/dist-tags
Why it was refuted

A plain GET of the public npm dist-tags endpoint sends no local data, times out, caches only the version string, and fails silently; it is not exfiltration.

Supply chain

mediumRefutedlow confidence

The install docs register the MCP server via `npx -y uxloom` with no version pin, so each launch runs whatever the latest published package is, auto-confirmed with -y; this is the artifact's own package and the documented install path.

claude mcp add uxloom -- npx -y uxloom
Why it was refuted

This is the artifact's own package in the documented fenced install instructions, a vendor-installer carve-out; it is not a hidden or third-party fetch.

Supply chain

mediumRefutedlow confidence

The server loads Playwright at runtime via an indirect `new Function` dynamic import, so a module that is not declared or pinned in package.json is resolved from the user's environment and bypasses static analysis; this is disclosed, and the specifier is fixed.

new Function("return import(...)")()
Why it was refuted

The optional Playwright load is explicitly documented (header and README), uses a fixed specifier, and degrades to null when absent; nothing is fetched or installed, so it is not a supply-chain concealment.

Agent hijacking

mediumRefutedlow confidence

The comments_list tool description tells the agent that reviewer-supplied comments are its work queue and to act on them each session, so untrusted comment text becomes a possible prompt-injection channel, although this fits the tool's declared review workflow.

they are your work queue
Why it was refuted

The description merely documents the tool's declared reviewer-comment workflow; telling the agent to process comments is the core capability, not a hidden hijack instruction.

Supply chain

lowRefutedlow confidence

The dev-only cold-start test launches the published package via an unpinned `uxloom@latest` through `npx -y`, which fetches and runs whatever the registry currently serves; this is the test's stated purpose, but it is unpinned remote code.

args: ["-y", "uxloom@latest"],
Why it was refuted

A dev-only test whose declared purpose is to launch the published package the way an agent's MCP config would; the unpinned latest is intentional and is not exposed to agents.

Coverage gaps 1

Parts of the artifact the static analysis could not fully examine.

no_dataflow_for_dynamic_code line 54: invoked code is not structurally extracted
packages/mcp-server/src/optional-browser.ts