Skip to content

fix: protect remote web access and copy session paths#186

Merged
ymkiux merged 4 commits into
mainfrom
fix/remote-web-auth
Jun 3, 2026
Merged

fix: protect remote web access and copy session paths#186
ymkiux merged 4 commits into
mainfrom
fix/remote-web-auth

Conversation

@awsl233777
Copy link
Copy Markdown
Collaborator

@awsl233777 awsl233777 commented Jun 3, 2026

Summary

  • require token auth before serving the Web UI to non-loopback clients
  • keep loopback access unchanged for local development
  • accept browser-friendly Basic Auth in addition to existing Bearer/header token auth
  • return a Basic Auth challenge for unauthorized remote Web clients
  • add a Copy path action next to Copy link in the session browser preview actions
  • copy the current session record's existing absolute filePath without reconstructing it in the browser
  • add regression coverage for protected Web routes, token extraction, copy-path behavior, and session file path usability

Validation

  • npm run test:unitAll 585 tests passed
  • node tests/e2e/run.jsE2E_EXIT:0
  • copy-path path usability is covered in e2e:
    • Codex/Claude/Gemini listed session filePath values are absolute
    • copied target paths point to existing files
    • Codex copied path is readable and contains the session content
  • manual HTTP checks with temporary CODEXMATE_HTTP_TOKEN=web-auth-test-token server:
    • remote / without token → 401 Unauthorized
    • remote / with Bearer token → 200 OK
    • remote / with Basic token → 200 OK
    • remote /web-ui/app.js with Basic token → 200 OK
    • loopback / without token → 200 OK

Notes

Screenshots for the auth flow were captured locally under _artifacts/codexmate/auth-web-token-20260603-090421 and shared in the chat.

Summary by CodeRabbit

  • New Features

    • Basic HTTP authentication support now available alongside Bearer token authentication
    • Non-loopback clients accessing protected routes now subject to rate limiting and authorization checks with WWW-Authenticate challenge responses
    • Added "Copy Path" button in session preview to copy active session file path to clipboard
    • Session file paths now validated for existence and absolute path format
  • Chores

    • Version bumped to 0.0.42

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6eb687e3-9e98-4c50-bacf-ea9196be3703

📥 Commits

Reviewing files that changed from the base of the PR and between 3d24489 and 913853b.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • cli.js
  • package.json
  • tests/unit/web-run-host.test.mjs
✅ Files skipped from review due to trivial changes (1)
  • package.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/unit/web-run-host.test.mjs
📜 Recent review details
🔇 Additional comments (1)
cli.js (1)

10454-10456: LGTM!


📝 Walkthrough

Walkthrough

Request token extraction now accepts Basic auth; protected frontend paths are classified and the router enforces rate-limits and auth for non-loopback clients; tests and UI add a session file-path copy action with translations.

Changes

Web-Surface Path Authentication

Layer / File(s) Summary
Basic auth token extraction
cli.js
extractRequestToken decodes Authorization: Basic ..., extracting the password/token portion or full decoded value alongside existing Bearer handling.
Unauthorized challenge header
cli.js
assertRequestAuthorized failure now returns 401 with WWW-Authenticate: Basic realm="codexmate".
Protected web-surface path classifier
cli.js
isProtectedWebSurfacePath identifies frontend/UI routes that require special handling: /, /web-ui/*, /res/*.
Web server auth & rate-limit enforcement
cli.js
Router enforces rate-limiting and calls authorization for protected web-surface paths on non-loopback clients, returning 429 or 401 on failure.
Test harness DI and token tests
tests/unit/web-run-host.test.mjs
Harness extended with auth/path hooks and exposes extractRequestToken/assertRequestAuthorized for unit tests covering Bearer header, custom token header, and Basic auth formats.
Auth enforcement tests and instantiation updates
tests/unit/web-run-host.test.mjs
New tests assert auth required for non-loopback access to / and /web-ui/*, confirm loopback bypass, and update existing createWebServer instantiations to pass new hooks.

Session Path Copy UI

Layer / File(s) Summary
Session helper methods
web-ui/modules/app.methods.session-actions.mjs
Adds getSessionFilePath(session) and copySessionPath(session) which normalize and copy the session filePath using fallbackCopyText or navigator.clipboard and emit UI messages.
UI wiring and translations
web-ui/partials/index/panel-sessions.html, web-ui/res/web-ui-render.precompiled.js, web-ui/modules/i18n/locales/*
Adds a "copy path" button wired to copySessionPath and getSessionFilePath, and adds sessions.preview.copyPath (en/ja/zh) and related sessions.preview.copyLink entry for ja.
Unit & e2e tests for session path behavior
tests/unit/session-actions-standalone.test.mjs, tests/unit/web-ui-behavior-parity.test.mjs, tests/e2e/test-sessions.js
Unit tests for successful copy and missing-path error, parity whitelist updated to allow new methods, and e2e checks that session filePath entries are absolute and exist (Codex file content includes sessionId).
Package metadata
package.json
Bumps package version from 0.0.410.0.42.

Sequence Diagram

sequenceDiagram
  participant Client
  participant WebServer
  participant PathClassifier
  participant RateLimiter
  participant AuthValidator

  Client->>WebServer: GET / (with/without Authorization)
  WebServer->>PathClassifier: isProtectedWebSurfacePath(requestPath)
  PathClassifier-->>WebServer: true
  alt remoteAddress is non-loopback
    WebServer->>RateLimiter: check client rate
    RateLimiter-->>WebServer: pass/fail
    alt pass
      WebServer->>AuthValidator: assertRequestAuthorized(token)
      alt token valid (Bearer or Basic)
        AuthValidator-->>WebServer: authorized
        WebServer-->>Client: 200 OK (content)
      else token invalid/missing
        AuthValidator-->>WebServer: unauthorized
        WebServer-->>Client: 401 Unauthorized
      end
    else fail
      WebServer-->>Client: 429 Too Many Requests
    end
  else remoteAddress is loopback
    WebServer-->>Client: 200 OK (no auth)
  end
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly Related PRs

Suggested Reviewers

  • ymkiux
  • SurviveM

Poem

🐰 I nibble tokens, Basic or Bearer bright,
Guarding web-ui paths through day and night,
Loopback friends skip the hopping gate,
While sessions share paths with a copy-to-plate,
Hooray — a rabbit's tiny security delight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: protect remote web access and copy session paths' clearly and concisely summarizes the two main changes: adding authentication protection for remote web access and implementing a copy session path feature.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/remote-web-auth

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
tests/unit/web-run-host.test.mjs (2)

971-1033: 💤 Low value

Solid coverage of the deny + loopback-bypass paths. The loopback test in particular nicely asserts auth is never invoked (authCalled === false) rather than just checking the status.

Optional: the protected-path enforcement also has an authorized success branch (auth returns { ok: true } → content is served) and a 429 rate-limit branch (per cli.js request handler) that aren't exercised here. Consider adding a remote request where authorizeRequest returns { ok: true } to confirm the handler proceeds to serve the asset, locking in the full contract for this security-sensitive change.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/web-run-host.test.mjs` around lines 971 - 1033, Add a new unit
test that exercises the authorized-success branch for remote clients: using
createWebServerHarness provide an authorizeRequest that returns { ok: true }
(and an htmlReader or asset reader that returns known content), call
requestHandler with a remote socket (e.g., remoteAddress '192.0.2.10') and the
request URL for root or a web-ui asset, then assert response.statusCode is 200
and response.body equals the reader content and that errors remains empty;
reference createWebServerHarness, requestHandler, authorizeRequest,
htmlReader/createMockResponse to locate where to add this test.

813-830: 💤 Low value

Consolidate duplicated auth mocks.

isLoopbackRemoteAddress, writeJsonResponse, and isProtectedWebSurfacePath are defined inline here and again as standalone mock* helpers (Lines 888-910) with identical bodies. Reusing the standalone helpers keeps a single source of truth and avoids the two copies drifting apart.

Note: the standalone helpers are declared after this function, so either move them above createWebServerHarness or rely on function-declaration hoisting (they are referenced only at call time, so hoisting works).

♻️ Proposed consolidation
-        isLoopbackRemoteAddress(value) {
-            return value === '127.0.0.1' || value === '::1' || value === '::ffff:127.0.0.1';
-        },
+        isLoopbackRemoteAddress: mockIsLoopbackRemoteAddress,
         assertRequestAuthorized: authorizeRequest,
-        writeJsonResponse(res, statusCode, payload, headers = {}) {
-            const body = JSON.stringify(payload || {}, null, 2);
-            res.writeHead(statusCode, {
-                'Content-Type': 'application/json; charset=utf-8',
-                ...headers
-            });
-            res.end(body);
-        },
-        isProtectedWebSurfacePath(requestPath) {
-            return requestPath === '/'
-                || requestPath === '/web-ui/index.html'
-                || requestPath.startsWith('/web-ui/')
-                || requestPath.startsWith('/res/');
-        },
+        writeJsonResponse: mockWriteJsonResponse,
+        isProtectedWebSurfacePath: mockIsProtectedWebSurfacePath,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/web-run-host.test.mjs` around lines 813 - 830, Remove the
duplicated inline helper implementations inside createWebServerHarness and reuse
the existing standalone mock helpers instead: replace the inline
isLoopbackRemoteAddress, writeJsonResponse, and isProtectedWebSurfacePath with
calls to the corresponding mock helpers (mockIsLoopbackRemoteAddress,
mockWriteJsonResponse, mockIsProtectedWebSurfacePath). Ensure the standalone
mock helper declarations are visible at call time—either move those mock* helper
declarations above createWebServerHarness or rely on function-hoisting by
confirming they are function declarations (not const arrow functions) so
references resolve when tests run.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cli.js`:
- Around line 10964-10977: When handling protected web surface requests (in the
isProtectedWebSurfacePath branch) ensure 401 responses trigger a browser
Basic-auth prompt by adding a WWW-Authenticate header; modify the flow that
calls assertRequestAuthorized(req, res) so that if auth.ok is false and the
response status is 401 you call writeJsonResponse(res, 401, { error:
'Unauthorized' }, { 'WWW-Authenticate': 'Basic realm="Restricted"',
'Content-Type': 'application/json' }) (or update assertRequestAuthorized to
include that header on its 401 path) instead of returning a bare 401 JSON
response, preserving existing behavior for other statuses and keeping
rate-limiting logic unchanged.

---

Nitpick comments:
In `@tests/unit/web-run-host.test.mjs`:
- Around line 971-1033: Add a new unit test that exercises the
authorized-success branch for remote clients: using createWebServerHarness
provide an authorizeRequest that returns { ok: true } (and an htmlReader or
asset reader that returns known content), call requestHandler with a remote
socket (e.g., remoteAddress '192.0.2.10') and the request URL for root or a
web-ui asset, then assert response.statusCode is 200 and response.body equals
the reader content and that errors remains empty; reference
createWebServerHarness, requestHandler, authorizeRequest,
htmlReader/createMockResponse to locate where to add this test.
- Around line 813-830: Remove the duplicated inline helper implementations
inside createWebServerHarness and reuse the existing standalone mock helpers
instead: replace the inline isLoopbackRemoteAddress, writeJsonResponse, and
isProtectedWebSurfacePath with calls to the corresponding mock helpers
(mockIsLoopbackRemoteAddress, mockWriteJsonResponse,
mockIsProtectedWebSurfacePath). Ensure the standalone mock helper declarations
are visible at call time—either move those mock* helper declarations above
createWebServerHarness or rely on function-hoisting by confirming they are
function declarations (not const arrow functions) so references resolve when
tests run.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d43f7ee1-bb29-4269-a148-5ce19c042fc3

📥 Commits

Reviewing files that changed from the base of the PR and between 6ffef78 and cfff085.

📒 Files selected for processing (2)
  • cli.js
  • tests/unit/web-run-host.test.mjs
📜 Review details
🔇 Additional comments (4)
tests/unit/web-run-host.test.mjs (3)

723-728: LGTM!


912-917: LGTM!


1107-1110: LGTM!

Also applies to: 1228-1231, 1366-1369, 1548-1551

cli.js (1)

10415-10428: LGTM!

Also applies to: 10460-10465

Comment thread cli.js
@awsl233777 awsl233777 changed the title fix: require auth for remote web access fix: protect remote web access and copy session paths Jun 3, 2026
@awsl233777
Copy link
Copy Markdown
Collaborator Author

Updated this PR with the session-browser copy-path action.

Changes added in 3d24489:

  • Added Copy path next to Copy link in the session preview actions.
  • Copies the session item's existing absolute filePath; the browser does not reconstruct paths.
  • Disables the button when a session has no file path.
  • Added i18n labels and updated the precompiled Web UI render output.

Validation:

  • npm run test:unitAll 583 tests passed
  • node tests/e2e/run.jsE2E_EXIT:0
  • e2e now verifies listed Codex/Claude/Gemini session paths are absolute and point to existing files; Codex path is also read back to verify usable content.

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 3, 2026

@awsl233777 I'll review the updated PR including the new Copy path feature added in commit 3d24489. Triggering a full review now!

✅ Action performed

Full review finished.

@awsl233777
Copy link
Copy Markdown
Collaborator Author

Handled the CodeRabbit auth challenge feedback in 184e6d8.

Fixes:

  • Unauthorized remote Web requests now return WWW-Authenticate: Basic realm="codexmate", so browsers can present a Basic Auth prompt.
  • Added a remote authorized-success Web UI test.
  • Consolidated duplicated Web server auth mock helpers.

Validation:

  • npm run test:unitAll 585 tests passed
  • node tests/e2e/run.jsE2E_EXIT:0

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 3, 2026

@awsl233777 Great progress! The WWW-Authenticate: Basic realm="codexmate" header addition is a solid improvement — it enables browsers to natively prompt for credentials on 401 responses, making the auth flow much more user-friendly. I'll kick off a full review of the latest changes now!

✅ Action performed

Full review finished.

@ymkiux ymkiux merged commit 6cd3134 into main Jun 3, 2026
8 of 9 checks passed
@ymkiux ymkiux deleted the fix/remote-web-auth branch June 3, 2026 10:04
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