Skip to content

Harden Iris security boundaries#1

Merged
divshekhar merged 10 commits into
syrin-labs:mainfrom
karthiknagpuri:codex/security-hardening
Jun 17, 2026
Merged

Harden Iris security boundaries#1
divshekhar merged 10 commits into
syrin-labs:mainfrom
karthiknagpuri:codex/security-hardening

Conversation

@karthiknagpuri

@karthiknagpuri karthiknagpuri commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • lock the browser bridge to loopback by default, add origin checks and timing-safe pairing-token authentication, require WSS for remote browser connections, and bound pending/authenticated connections, payloads, rates, and event memory
  • validate protocol messages, safely serialize and redact browser data, hide sensitive form values, restrict navigation to HTTP(S), and block destructive controls unless explicitly confirmed
  • make dangerous-action confirmation one-shot across recordings, replays, flows, healing, crawling, WebMCP, and native input; correct replay/heal runtime error classification
  • repair CI package filters and E2E harness arguments, upgrade vulnerable build dependencies, and add high-severity dependency auditing

Verification

  • pnpm test: all monorepo tasks passed (10 protocol, 394 server, 269 browser tests)
  • pnpm build
  • pnpm lint
  • pnpm typecheck
  • pnpm format:check
  • pnpm audit --audit-level high: no known vulnerabilities
  • browser E2E: 14/14 specs passed
  • git diff --check

Summary by CodeRabbit

  • New Features

    • Added MCP proxy mode for Claude Code integration with auto-daemon startup
    • Introduced dangerous-action confirmation gating for destructive operations
    • Added token-based pairing for non-localhost connections
    • Implemented version info, update checking, and rollback tools
    • Enhanced session auto-selection with multi-session health scoring
    • Added project run history tracking and diff support
    • Improved flow recording/replay parameter naming
  • Bug Fixes

    • Fixed E2E test timeouts and demo server readiness checks
    • Improved flow replay error/drift distinction
    • Enhanced session disconnection handling
  • Documentation

    • Expanded README with comprehensive installation guide
    • Added complete SKILL.md setup and testing workflow documentation
    • Updated CHANGELOG with v0.5.0 release notes
  • Chores

    • Bumped all package versions to 0.5.0
    • Updated dependencies and test configurations
    • Enhanced CI/CD workflow verification steps

divshekhar and others added 4 commits June 14, 2026 21:46
iris_inspect: component.name was required string but babel-plugin source
data is absent when the plugin is not configured — made optional.

iris_clock: ok field was required boolean but the browser side does not
always return it — made optional.

Both bugs surfaced during end-to-end stress testing against the demo app
and caused MCP -32602 output validation errors on every call.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The glow border, cursor tracking, and narration HUD now appear as soon
as the demo app loads with Iris connected, without needing ?present in
the URL. Add ?nopresent to suppress for clean screen recordings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…arrate MCP validation

- Transport: add onConnected callback, fires when WebSocket to bridge opens
- iris.ts: call sessionStart() on onConnected so the glow border + HUD appear
  immediately when the agent connects, not only on the first tool call
- iris_narrate handler: wrap result to include ok:true so MCP output schema
  validation passes (structuredContent must contain the required ok field)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 352c2325-c36b-4bd4-b0c2-de5877020f84

📥 Commits

Reviewing files that changed from the base of the PR and between 68c3b56 and d31e624.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (96)
  • .github/workflows/ci.yml
  • .mcp.json
  • CHANGELOG.md
  • README.md
  • SKILL.md
  • apps/demo/.claude/settings.json
  • apps/demo/.env.example
  • apps/demo/.mcp.json
  • apps/demo/package.json
  • apps/demo/src/iris-dev.ts
  • apps/demo/src/vite-env.d.ts
  • apps/demo/vite.config.ts
  • apps/e2e/run-ci.sh
  • apps/e2e/specs/next-smoke-test.mjs
  • apps/e2e/specs/p3a-test.mjs
  • apps/e2e/specs/p3b-test.mjs
  • apps/e2e/specs/project-history-test.mjs
  • apps/e2e/specs/real-world-tests.mjs
  • apps/e2e/specs/spa-nav-realinput-test.mjs
  • apps/next-smoke/.env.example
  • apps/next-smoke/app/iris-dev.tsx
  • docs/flows.md
  • package.json
  • packages/babel-plugin/package.json
  • packages/browser/package.json
  • packages/browser/src/actions/actions.effect.test.ts
  • packages/browser/src/actions/actions.interactions.test.ts
  • packages/browser/src/actions/actions.ts
  • packages/browser/src/commands/commands.test.ts
  • packages/browser/src/commands/commands.ts
  • packages/browser/src/dom/a11y.security.test.ts
  • packages/browser/src/dom/a11y.ts
  • packages/browser/src/iris.session.test.ts
  • packages/browser/src/iris.ts
  • packages/browser/src/observers/console.ts
  • packages/browser/src/presenter/presenter.test.ts
  • packages/browser/src/registry/stores.test.ts
  • packages/browser/src/registry/stores.ts
  • packages/browser/src/security/serialization.test.ts
  • packages/browser/src/security/serialization.ts
  • packages/browser/src/timers/native-timers.interval.test.ts
  • packages/browser/src/transport/transport.security.test.ts
  • packages/browser/src/transport/transport.ts
  • packages/eslint-plugin/package.json
  • packages/iris/package.json
  • packages/next/package.json
  • packages/protocol/package.json
  • packages/protocol/src/constants.ts
  • packages/protocol/src/index.ts
  • packages/protocol/src/messages.test.ts
  • packages/protocol/src/messages.ts
  • packages/protocol/src/security.test.ts
  • packages/protocol/src/security.ts
  • packages/protocol/src/types.ts
  • packages/react/package.json
  • packages/server/.env.example
  • packages/server/package.json
  • packages/server/src/bridge.security.test.ts
  • packages/server/src/bridge.ts
  • packages/server/src/cli.test.ts
  • packages/server/src/cli.ts
  • packages/server/src/crawl/crawl-tools.ts
  • packages/server/src/crawl/crawl.ts
  • packages/server/src/events/predicate.test.ts
  • packages/server/src/events/predicate.ts
  • packages/server/src/events/ring-buffer.test.ts
  • packages/server/src/events/ring-buffer.ts
  • packages/server/src/flows/flow-replay.test.ts
  • packages/server/src/flows/flow-replay.ts
  • packages/server/src/flows/flow-tools.ts
  • packages/server/src/flows/flows.heal.test.ts
  • packages/server/src/flows/recordings.test.ts
  • packages/server/src/flows/replay.ts
  • packages/server/src/flows/tools.flow-replay.test.ts
  • packages/server/src/http-server.ts
  • packages/server/src/index.ts
  • packages/server/src/input/real-input.test.ts
  • packages/server/src/input/real-input.ts
  • packages/server/src/input/tools.real-input.test.ts
  • packages/server/src/mcp-proxy.ts
  • packages/server/src/mcp.ts
  • packages/server/src/project/project-store.test.ts
  • packages/server/src/server-version.ts
  • packages/server/src/session/session.test.ts
  • packages/server/src/session/session.ts
  • packages/server/src/tools/browser-tools.ts
  • packages/server/src/tools/tool-names.ts
  • packages/server/src/tools/tools.ts
  • packages/server/src/update/update-checker.ts
  • packages/server/src/update/update-tools.ts
  • packages/server/src/update/updater.ts
  • packages/test/package.json
  • scripts/integration-test.mjs
  • skill/README.md
  • skill/SKILL.md
  • turbo.json

📝 Walkthrough

Walkthrough

This change adds an MCP proxy CLI flow, update-management tools, stricter browser and server transport/security checks, dangerous-action confirmation during actions and replay, revised session selection, broader integration and e2e coverage, and updated app wiring, docs, release notes, and workspace configuration.

Changes

Iris 0.5.0 platform changes

Layer / File(s) Summary
Protocol and transport safety foundations
packages/protocol/src/*, packages/browser/src/security/*, packages/browser/src/transport/*, packages/browser/src/dom/*, packages/browser/src/registry/*, packages/browser/src/observers/console.ts
Adds transport limits and security helpers, tightens message schemas, sanitizes serialized payloads, redacts sensitive DOM and store values, and validates browser transport input and output behavior.
Browser connection and guarded actions
packages/browser/src/iris.ts, packages/browser/src/actions/*, packages/browser/src/commands/*, apps/demo/src/*, apps/demo/vite.config.ts, apps/next-smoke/app/iris-dev.tsx, apps/e2e/specs/*real*, apps/e2e/specs/spa-nav-realinput-test.mjs
Adds non-localhost connection policy and token support, guards dangerous browser actions and WebMCP calls, validates navigation URLs, and updates demo and Next smoke client wiring plus related tests.
Server bridge, MCP proxy, and session orchestration
packages/server/src/bridge*, packages/server/src/cli*, packages/server/src/mcp-proxy.ts, packages/server/src/http-server.ts, packages/server/src/index.ts, packages/server/src/session/*, .mcp.json, apps/demo/.mcp.json, scripts/integration-test.mjs
Introduces iris mcp daemon probing and proxy startup, per-connection MCP servers, stricter bridge handshake and origin/token checks, revised session resolution, and end-to-end MCP and session integration scenarios.
Replay, native input, and tool execution hardening
packages/server/src/flows/*, packages/server/src/tools/*, packages/server/src/crawl/*, packages/server/src/input/*, packages/server/src/events/*, docs/flows.md, apps/e2e/specs/p3*.mjs, apps/e2e/specs/project-history-test.mjs, apps/e2e/run-ci.sh
Threads dangerous-action confirmation through replay, crawl, and native input, updates replay/heal error reporting, adjusts tool schemas and responses, adds deterministic screenshots and buffer sizing, and expands replay and runtime tests.
Update and version management tools
packages/server/src/update/*, packages/server/src/tools/tool-names.ts, packages/protocol/src/constants.ts, scripts/integration-test.mjs
Adds version-info, apply-update, and rollback tools, cached update manifest handling, install-strategy detection, and integration checks for guarded update operations.
Release docs and workspace configuration
README.md, SKILL.md, CHANGELOG.md, .github/workflows/ci.yml, package.json, turbo.json, packages/*/package.json, packages/server/.env.example, apps/demo/.claude/settings.json
Updates installation and skill documentation, records the 0.5.0 release, adjusts CI and workspace test wiring, bumps package versions and scripts, and adds setup-oriented config examples and hooks.

Sequence Diagram(s)

sequenceDiagram
  participant Client as MCP Client
  participant CLI as iris mcp
  participant Daemon as Iris Daemon
  participant SSE as MCP SSE Session

  Client->>CLI: launch stdio proxy
  CLI->>Daemon: probe daemon port
  alt daemon absent
    CLI->>Daemon: spawn _daemon
    CLI->>Daemon: wait for readiness
  end
  CLI->>SSE: open SSE connection
  SSE-->>CLI: endpoint event
  Client->>CLI: send JSON-RPC request
  CLI->>SSE: POST request to session
  SSE-->>CLI: message event
  CLI-->>Client: write JSON-RPC response
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~110 minutes

Poem

🐇 I thumped on the bridge and the proxy woke,
Then replay learned when not to poke.
Tokens tucked in and secrets redacted,
Sessions chose wisely, no longer distracted.
A carrot for docs, a clover for tests—
Iris 0.5.0 hops with its best.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

divshekhar and others added 3 commits June 15, 2026 22:33
…root

- iris mcp: auto-starts daemon if not running, proxies stdio↔SSE
- New MCP tools: iris_version_info, iris_apply_update, iris_rollback
- SKILL.md moved to repo root (was skill/SKILL.md) — shorter URL
- Removed skill/README.md; skill/ directory cleaned up
- README Installation section updated: skill-first flow, all 7 harness configs, URLs point to root SKILL.md
- SKILL.md auto-detects setup vs test mode via .iris.json presence
- Q6 (headed/headless), Q7 (harness selection) added to setup flow
- .iris.json written after setup; dev:iris script added to demo app
- All-throttled session auto-selection: picks freshest heartbeat instead of throwing
- IRIS_TESTING_PORT = 4310 isolated from user dev port
- iris mcp --drive <url> flag for Playwright-owned browser

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@divshekhar

Copy link
Copy Markdown
Contributor

Hi @karthiknagpuri ,
The branch has some conflicts can you resolve it? Will merge it after testing it.

divshekhar and others added 3 commits June 17, 2026 22:44
…iris into karthiknagpuri-codex/security-hardening

# Conflicts:
#	packages/server/src/bridge.ts
The MCP SDK pulls hono transitively at 4.12.23, which is vulnerable to a
high-severity CORS issue (wildcard origin reflected with credentials).
Pin via pnpm override to 4.12.25 so `pnpm audit --audit-level high` passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The presenter overlay (HUD + border glow) is mounted on the page when the
SDK connects with present:true, and its activity log / border state change
with every command. capturePage was including it, so a fresh screenshot of
an unchanged page no longer matched its baseline — the e2e visual-test diff
came back at ~1% (12k px) and tripped its maxRatio:0.01 gate on CI.

Apply Playwright's per-shot `style` to hide [data-iris-overlay] and
`animations: 'disabled'` so captures reflect the app, not Iris chrome.
Same-page diff is now ratio=0, changed=0. Both real-input providers route
through capturePage, so the fix is centralized.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@divshekhar divshekhar marked this pull request as ready for review June 17, 2026 17:46
@divshekhar divshekhar merged commit ff54d8d into syrin-labs:main Jun 17, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants