A review session your agent can join. Share a build at a stable URL; reviewers click the element they mean; an agent reads the source behind it, resizes their preview, and replies in the thread — over WebMCP, MCP and a JSON CLI.
Drift inferred · capture-to-capture
No drift recorded — single capability capture; advisories appear once its surface changes.
transport stdio counts 8 tools · 0 res
· 0 prompts
permission surface via code analysis
tools
-
create_preview
-
get_comment
-
get_preview_info
-
list_comments
-
list_versions
-
reply_to_comment
-
resolve_comment
-
update_preview
prompt-surface
shipped agent-instruction files + hidden-content / dangerous-code findings —
quoted from the analyzed source
analyzed commit 348bde5 · analyzer v33 · 19h ago
danger signals5
- dynamic code execution new Function() liha-app-live-preview-348bde5/apps/api/test/notify.test.ts :461
expect(() => new Function(source), path).not.toThrow(); - suspicious endpoint 169.254.169.254 (cloud metadata) liha-app-live-preview-348bde5/apps/api/test/notify.test.ts :163
'https://169.254.169.254/latest/meta-data/', - suspicious endpoint 169.254.169.254 (cloud metadata) liha-app-live-preview-348bde5/packages/shared/src/url.test.ts :24
'http://169.254.169.254/latest/meta-data/', - suspicious endpoint 100.100.100.200 (cloud metadata) liha-app-live-preview-348bde5/packages/shared/src/url.test.ts :25
'http://100.100.100.200/', - suspicious endpoint 93.184.216.34 liha-app-live-preview-348bde5/packages/shared/src/url.test.ts :58
'https://93.184.216.34/',
evidence-backed
findings quoted directly from the published source artifact — not inferred
code files: 185
filesystem 23
- fs (weak) liha-app-live-preview-348bde5/apps/api/test/content-origin.test.ts :1
import { readFileSync } from 'node:fs'; - fs (weak) liha-app-live-preview-348bde5/apps/api/test/harness.ts :1
import { readFileSync, readdirSync } from 'node:fs'; - fs (weak) liha-app-live-preview-348bde5/apps/web/src/lib/unseen.test.ts :1
import { readFileSync } from 'node:fs'; - fs (weak) liha-app-live-preview-348bde5/apps/web/src/og.test.ts :1
import { readFileSync } from 'node:fs'; - fs (weak) liha-app-live-preview-348bde5/apps/web/src/styles.test.ts :1
import { readFileSync } from 'node:fs'; - fs (weak) liha-app-live-preview-348bde5/packages/cli/src/cli.test.ts :1
import { readFileSync } from 'node:fs'; - fs liha-app-live-preview-348bde5/packages/cli/src/client.ts :1
import { readFile } from 'node:fs/promises'; - fs liha-app-live-preview-348bde5/packages/cli/src/files.ts :1
import { readdir, stat } from 'node:fs/promises'; - fs liha-app-live-preview-348bde5/packages/cli/src/project.ts :2
import { existsSync } from 'node:fs'; - fs liha-app-live-preview-348bde5/packages/mcp/src/api.ts :15
* cast is safe: `fs.readFile` never returns a SharedArrayBuffer-backed buffer. - fs liha-app-live-preview-348bde5/packages/mcp/src/credentials.ts :3
import { mkdir, readFile, writeFile } from 'node:fs/promises'; - fs (weak) liha-app-live-preview-348bde5/packages/mcp/src/server.test.ts :1
import { readFileSync } from 'node:fs';
show 11 more
- fs liha-app-live-preview-348bde5/packages/mcp/src/workspace.ts :1
import { existsSync } from 'node:fs'; - fs (weak) liha-app-live-preview-348bde5/scripts/deploy.mjs :24
import fs from 'node:fs'; - fs (weak) liha-app-live-preview-348bde5/scripts/make-og.mjs :17
import { stat } from 'node:fs/promises'; - fs liha-app-live-preview-348bde5/video/tools/build-subtitles-ja.ts :3
import { mkdir, readFile, writeFile } from 'node:fs/promises'; - fs liha-app-live-preview-348bde5/video/tools/build-subtitles.ts :3
import { mkdir, readFile, writeFile } from 'node:fs/promises'; - fs liha-app-live-preview-348bde5/video/tools/generate-narration-ja.mjs :3
import { mkdtemp, mkdir, readFile, rm } from 'node:fs/promises'; - fs liha-app-live-preview-348bde5/video/tools/generate-narration.ts :3
import { mkdir, mkdtemp, readFile, rename, rm, unlink, writeFile } from 'node:fs/promises'; - fs liha-app-live-preview-348bde5/video/tools/record.mjs :13
import { readFileSync, mkdirSync } from 'node:fs'; - fs liha-app-live-preview-348bde5/video/tools/scene-02-publish.mjs :1
import { cp, mkdtemp, rm } from 'node:fs/promises'; - fs liha-app-live-preview-348bde5/video/tools/scene-05-same-url.mjs :1
import { cp, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'; - fs liha-app-live-preview-348bde5/video/tools/scene-06-product.mjs :2
import { rm } from 'node:fs/promises';
shell / exec 8
- shell liha-app-live-preview-348bde5/packages/cli/src/project.ts :1
import { spawn } from 'node:child_process'; - shell (weak) liha-app-live-preview-348bde5/scripts/lib/cloudflare.mjs :3
import { spawn } from 'node:child_process'; - shell liha-app-live-preview-348bde5/video/tools/generate-narration-ja.mjs :6
import { spawnSync } from 'node:child_process'; - shell liha-app-live-preview-348bde5/video/tools/generate-narration.ts :4
import { spawnSync } from 'node:child_process'; - shell liha-app-live-preview-348bde5/video/tools/record.mjs :15
import { spawnSync } from 'node:child_process'; - shell liha-app-live-preview-348bde5/video/tools/scene-02-publish.mjs :4
import { spawnSync } from 'node:child_process'; - shell liha-app-live-preview-348bde5/video/tools/scene-05-same-url.mjs :4
import { spawnSync } from 'node:child_process'; - shell liha-app-live-preview-348bde5/video/tools/terminal-capture.mjs :2
import { spawn, spawnSync } from 'node:child_process';
network 40
- net liha-app-live-preview-348bde5/apps/api/src/app.ts :1447
const asset = await env.ASSETS.fetch( - net liha-app-live-preview-348bde5/apps/api/src/content.ts :27
// The app needs to read these bytes with fetch(): pdf.js renders a PDF from - net liha-app-live-preview-348bde5/apps/api/src/env.ts :37
ASSETS?: { fetch(request: Request): Promise<Response> }; - net liha-app-live-preview-348bde5/apps/api/src/google.ts :159
const response = await fetch(TOKEN, { - net liha-app-live-preview-348bde5/apps/api/src/index.ts :9
async fetch(request: Request, env: Env, ctx: DeferredWork): Promise<Response> { - net liha-app-live-preview-348bde5/apps/api/src/notification-site.ts :199
const response = await fetch(API + path, { - net liha-app-live-preview-348bde5/apps/api/src/push.ts :98
const response = await fetch(endpoint, { - net liha-app-live-preview-348bde5/apps/api/src/url-import.ts :51
const response = await fetcher.fetch( - net (weak) liha-app-live-preview-348bde5/apps/api/test/accounts.test.ts :40
await server.fetch(path, { - net (weak) liha-app-live-preview-348bde5/apps/api/test/comment-idempotency.test.ts :16
const response = await app.fetch('/api/previews', { - net (weak) liha-app-live-preview-348bde5/apps/api/test/content-origin.test.ts :205
const response = await server.fetch('/api/previews', { - net (weak) liha-app-live-preview-348bde5/apps/api/test/flow.test.ts :23
const response = await server.fetch('/api/previews', {
show 28 more
- net (weak) liha-app-live-preview-348bde5/apps/api/test/harness.ts :99
fetch(path: string, init?: RequestInit): Promise<Response>; - net (weak) liha-app-live-preview-348bde5/apps/api/test/limits.test.ts :13
return server.fetch('/api/previews', { - net (weak) liha-app-live-preview-348bde5/apps/api/test/notify.test.ts :38
server.fetch('/api/push/subscribe', { - net (weak) liha-app-live-preview-348bde5/apps/api/test/retention.test.ts :58
expect((await server.fetch(`/api/previews/${preview.slug}`)).status).toBe(200); - net (weak) liha-app-live-preview-348bde5/apps/api/test/review-host.test.ts :42
const response = await server.fetch('/api/previews', { - net (weak) liha-app-live-preview-348bde5/apps/api/test/security.test.ts :14
const response = await server.fetch('/api/previews', { - net (weak) liha-app-live-preview-348bde5/apps/api/test/threads.test.ts :9
const response = await server.fetch('/api/previews', { method: 'POST', ...uploadBody([PAGE]) }); - net (weak) liha-app-live-preview-348bde5/apps/api/test/url-import.test.ts :158
const anyone = await server.fetch(`/api/previews/${created.preview.slug}/versions/from-url`, { - net (weak) liha-app-live-preview-348bde5/apps/web/e2e/a11y.spec.ts :28
const response = await fetch(`${API}/api/previews`, { - net (weak) liha-app-live-preview-348bde5/apps/web/e2e/account.spec.ts :143
const response = await fetch(`${API}/api/previews/${slug}/comments`, { - net (weak) liha-app-live-preview-348bde5/apps/web/e2e/artifact-types.spec.ts :36
const response = await fetch(`${API}/api/previews`, { - net (weak) liha-app-live-preview-348bde5/apps/web/e2e/comments.spec.ts :29
const response = await fetch(`${API}/api/previews`, { - net (weak) liha-app-live-preview-348bde5/apps/web/e2e/focus.spec.ts :17
await fetch(`${API}/api/previews`, { method: 'POST', headers: asNewClient(), body: form }) - net (weak) liha-app-live-preview-348bde5/apps/web/e2e/i18n.spec.ts :25
const response = await fetch(`${API}/api/previews`, { - net (weak) liha-app-live-preview-348bde5/apps/web/e2e/review-loop.spec.ts :33
const response = await fetch(`${API}/api/previews`, { - net liha-app-live-preview-348bde5/apps/web/src/components/PdfStage.tsx :60
const response = await fetch(version.contentUrl ?? ''); - net liha-app-live-preview-348bde5/apps/web/src/lib/api.ts :65
response = await fetch(`${API_URL}${path}`, { - net liha-app-live-preview-348bde5/apps/web/src/routes/PreviewRoute.tsx :480
const response = await fetch(target); - net (weak) liha-app-live-preview-348bde5/packages/cli/src/cli.test.ts :146
const content = await fetch(`${server.url}/content/${data.slug as string}/1/index.html`).then( - net liha-app-live-preview-348bde5/packages/cli/src/client.ts :68
response = await fetch(`${this.options.apiUrl}${path}`, { - net liha-app-live-preview-348bde5/packages/mcp/src/api.ts :56
const response = await fetch(`${this.options.apiUrl}${path}`, { - net (weak) liha-app-live-preview-348bde5/packages/mcp/src/server.test.ts :108
const posted = (await fetch(`${api.url}/api/previews/${slug}/comments`, { - net (weak) liha-app-live-preview-348bde5/scripts/deploy.mjs :734
const response = await fetch(`https://${config.apiHost}/api/health`); - net (weak) liha-app-live-preview-348bde5/scripts/lib/cloudflare.mjs :84
const response = await fetch(`https://api.cloudflare.com/client/v4${endpoint}`, { - net (weak) liha-app-live-preview-348bde5/scripts/verify-deployment.mjs :127
if (!url.hostname.endsWith('.localhost')) return fetch(url, init); - net (weak) liha-app-live-preview-348bde5/video/tools/fixture.mjs :62
const response = await fetch(`${API}/api/previews`, { - net liha-app-live-preview-348bde5/video/tools/generate-narration.ts :337
response = await fetch('https://generativelanguage.googleapis.com/v1beta/interactions', { - net liha-app-live-preview-348bde5/video/tools/scene-06-product.mjs :20
const response = await fetch(`${apiUrl}${path}`, {
secrets 6
- secrets (weak) liha-app-live-preview-348bde5/packages/cli/src/cli.test.ts :69
delete process.env.LIHA_OWNER_TOKEN; - secrets liha-app-live-preview-348bde5/packages/cli/src/context.ts :81
flagString(args, 'token') ?? process.env.LIHA_OWNER_TOKEN ?? credential?.ownerToken; - secrets (weak) liha-app-live-preview-348bde5/packages/mcp/src/server.test.ts :53
delete process.env.LIHA_OWNER_TOKEN; - secrets liha-app-live-preview-348bde5/packages/mcp/src/server.ts :104
ownerToken: credential?.ownerToken ?? process.env.LIHA_OWNER_TOKEN, - secrets (weak) liha-app-live-preview-348bde5/scripts/deploy.mjs :196
let token = process.env.CLOUDFLARE_API_TOKEN?.trim(); - secrets liha-app-live-preview-348bde5/video/tools/generate-narration.ts :397
const apiKey = process.env.GEMINI_API_KEY;
tool registrations 8
- get_preview_info liha-app-live-preview-348bde5/packages/mcp/src/server.ts :126
- list_comments liha-app-live-preview-348bde5/packages/mcp/src/server.ts :157
- get_comment liha-app-live-preview-348bde5/packages/mcp/src/server.ts :183
- list_versions liha-app-live-preview-348bde5/packages/mcp/src/server.ts :214
- create_preview liha-app-live-preview-348bde5/packages/mcp/src/server.ts :242
- update_preview liha-app-live-preview-348bde5/packages/mcp/src/server.ts :295
- reply_to_comment liha-app-live-preview-348bde5/packages/mcp/src/server.ts :331
- resolve_comment liha-app-live-preview-348bde5/packages/mcp/src/server.ts :375
declared dependencies 3
- playwright@1.62.1
- prettier@^3.4.2
- typescript@^5.7.3
perm:untrusted 1
- untrusted (weak) liha-app-live-preview-348bde5/packages/cli/src/cli.test.ts :146
const content = await fetch(`${server.url}/content/${data.slug as string}/1/index.html`).then(