Add authenticated managed-profile browser - #52
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0399bb581b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
| }); | ||
|
|
||
| app.get("/api/browser/read", requireAuth, async (req: Request, res: Response) => { |
There was a problem hiding this comment.
Isolate the managed profile from unrelated tenants
In the documented multi-user Replit/self-hosted deployments, this route accepts any valid JWT, while MANAGED_ROOT, the Chrome process, and all target IDs are process-global and have no user or organization ownership check. Consequently, a user from another organization—or a low-privilege team member—can call /api/browser/read to retrieve pages from the host user's authenticated profile, and can also use the similarly protected import/open routes to replace or control that shared session. Restrict this capability to the local profile owner or isolate profiles and targets per authorized tenant.
Useful? React with 👍 / 👎.
| const current = await browserStatus(); | ||
| if (current.running) return current; |
There was a problem hiding this comment.
Verify the debugger belongs to the managed process
When another Chrome or CDP-compatible service is already listening on the fixed port (9222 by default), browserStatus() reports it as running and this early return skips launching the isolated MANAGED_ROOT profile. The subsequent open/read calls then enumerate and evaluate pages in that unrelated browser, potentially exposing the user's normal authenticated session. Use a dedicated dynamically allocated port and retain or authenticate the launched process rather than trusting any /json/version responder.
Useful? React with 👍 / 👎.
| "next-themes": "^0.4.6", | ||
| "passport": "^0.7.0", | ||
| "passport-local": "^1.0.0", | ||
| "passport-local": "^0.7.0", |
There was a problem hiding this comment.
Restore the locked passport-local dependency range
Changing this range to ^0.7.0 without updating the lockfile breaks clean deployment installs: the checked-in root lock entry still requires ^1.0.0 and resolves passport-local 1.0.0, which does not satisfy the new range. Since the documented production build uses npm ci, it cannot install from the committed manifest and lockfile as a consistent dependency set; restore the prior range or regenerate both files with an actually resolvable version.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Security Review
Here are some automated security review suggestions for this pull request.
Reviewed commit: 0399bb581b
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
| app.post("/api/browser/profile/import", requireAuth, async (req: Request, res: Response) => { | ||
| const parsed = importSchema.safeParse(req.body || {}); | ||
| if (!parsed.success) return res.status(400).json({ message: parsed.error.issues.map((issue) => issue.message).join(", ") }); | ||
| try { | ||
| const result = await importExistingChromeProfile(parsed.data.profileName); |
There was a problem hiding this comment.
Security: Bind managed Chrome profiles to one tenant
When this runs on a host with a usable Chrome profile, any authenticated account—including a viewer in another tenant—can import that OS user's profile, then use /open and /read to retrieve authenticated page text. All routes use only requireAuth; the profile/CDP state is process-global and no req.user ownership check exists. Require explicit local approval and privileged RBAC, and allocate and authorize browser state per user or organization.
Useful? React with 👍 / 👎.
Adds a local managed Chrome profile runtime so ZYRA can reuse authenticated browser sessions for HTTP/HTTPS navigation and page reads. The profile stays on the user's machine; credential export, raw-cookie export, password extraction, file/javascript URLs, and consequential autonomous browser actions are not exposed. Includes authenticated API routes, tests, sensitive-response logging suppression, and documentation.