Skip to content

Enhance server, UI, and conversation features with various improvements#50

Closed
friuns2 wants to merge 22 commits intofriuns2:mainfrom
Pein2017:main
Closed

Enhance server, UI, and conversation features with various improvements#50
friuns2 wants to merge 22 commits intofriuns2:mainfrom
Pein2017:main

Conversation

@friuns2
Copy link
Copy Markdown
Owner

@friuns2 friuns2 commented Apr 13, 2026

No description provided.

@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Comprehensive enhancement with context-aware runtime selection, thread compacting, MCP support, and improved UI/UX

✨ Enhancement

Grey Divider

Walkthroughs

Description
• **Context-aware runtime selection**: Refactored model, reasoning effort, and speed mode selection
  to be per-thread instead of global with persistent storage
• **Thread compacting support**: Implemented thread context compaction functionality with API calls
  and UI state management
• **MCP tool calls and collaboration**: Added support for MCP tool calls and collaborative agent
  tool calls with new message types and UI components
• **Git worktree detection**: Implemented git worktree listing and selection with read-only mode for
  alternate worktrees
• **Session status overview**: Added API to expose session configuration details (model, reasoning,
  speed, MCP servers)
• **Custom host binding**: Added --host CLI option and --strict-local-auth flag for flexible
  server configuration
• **Secure transport detection**: Enhanced authentication with HTTPS detection via headers and
  configurable localhost trust
• **Message editing**: Implemented past message edit functionality with dedicated composer panel and
  rollback support
• **Slash commands**: Added /compact, /review, /fork, /resume, /model, /plan, /collab,
  /status, /mcp commands in composer
• **Thread filtering**: Added thread status filter (all/running/new) with localStorage persistence
  and mark-all-seen capability
• **Improved mobile detection**: Enhanced mobile layout detection with pointer capability checks and
  responsive adjustments
• **Settings UI refactor**: Restructured settings panel with session status, MCP management, quota
  tracking, and removed legacy account management
• **Live overlay enhancements**: Added activity summaries, background agents tracking, and timestamp
  updates
• **Symlink conversion**: Replaced symlink creation with plain file conversion logic in skills
  routes
• **Local launcher script**: New bash script for launching codexUI from local repository with Serena
  MCP compatibility
Diagram
flowchart LR
  A["User Settings"] -->|"Configure model,<br/>reasoning, speed"| B["Context-aware<br/>Runtime Selection"]
  B -->|"Per-thread storage"| C["useDesktopState"]
  D["Thread Operations"] -->|"Compact context"| E["compactThread API"]
  E -->|"Manage state"| C
  F["MCP Servers"] -->|"Tool calls"| G["Message Types"]
  H["Git Worktrees"] -->|"Select target"| I["ReviewPane"]
  I -->|"Read-only mode"| J["Alternate Worktree"]
  K["Composer"] -->|"Slash commands"| L["Enhanced UX"]
  M["Thread List"] -->|"Filter & organize"| N["Status Filter"]
  O["Session Config"] -->|"Display overview"| P["Settings Panel"]
Loading

Grey Divider

File Changes

1. src/composables/useDesktopState.ts ✨ Enhancement +1224/-124

Context-aware runtime selection and thread compacting support

• Refactored model, reasoning effort, and speed mode selection to be context-aware (per-thread)
 instead of global, with storage keys for each context
• Added support for MCP tool calls and collaborative agent tool calls with equality comparison
 functions
• Implemented thread compacting functionality with compactThread API call and UI state management
• Enhanced live message overlay tracking with timestamp updates and improved redundant message
 removal logic
• Added helper functions for file change summarization and tool summary text building
• Replaced legacy read state storage with seen-updated-at tracking and pending sync mechanism
• Added selectedThreadBusyPhase computed property to distinguish between turn execution and
 compacting states

src/composables/useDesktopState.ts


2. src/server/codexAppServerBridge.ts ✨ Enhancement +226/-16

Launch scope filtering and MCP tool call support

• Enhanced error message extraction to handle nested error arrays in aggregate error payloads
• Added MCP tool call item extraction in thread message text building
• Implemented launch scope filtering to restrict threads and operations to a specific directory
 scope
• Added Serena MCP wrapper command resolution from environment variables or repository structure
• Implemented fallback curl-based HTTP client for transcription when curl-impersonate is unavailable
• Added thread title cache filtering by allowed thread IDs for scoped access control

src/server/codexAppServerBridge.ts


3. src/cli/index.ts ✨ Enhancement +37/-11

Custom host binding and password source tracking

• Refactored password resolution to return structured object with source metadata (disabled,
 explicit, env, generated)
• Added --host CLI option to bind server to specific network interface instead of hardcoded
 0.0.0.0
• Added --strict-local-auth flag to enforce password authentication even for localhost connections
• Extracted listenWithFallbackOnHost function to support custom host binding
• Updated access URL generation to respect custom host configuration
• Enhanced password display logic to show source information (env, explicit, or generated)

src/cli/index.ts


View more (25)
4. src/server/reviewGit.ts ✨ Enhancement +107/-2

Git worktree detection and listing support

• Added ReviewWorktreeTarget type to represent git worktree information
• Implemented listReviewWorktreeTargets function to parse git worktree list output with branch
 detection
• Added helper functions for branch name normalization and worktree label building
• Integrated worktree targets into buildReviewSnapshot to include available git worktrees in
 review data

src/server/reviewGit.ts


5. src/api/codexGateway.ts ✨ Enhancement +83/-2

Session status overview and thread compacting API

• Added SessionStatusOverview type to expose session configuration details (model, reasoning
 effort, speed mode, MCP servers)
• Implemented getSessionStatusOverview function to read and format current session configuration
• Added reloadMcpServerConfig function to trigger MCP server configuration reload
• Added compactThread export function to initiate thread context compaction
• Added helper functions readStringArray and formatConfigScalar for configuration parsing
• Enhanced review snapshot normalization to include worktree targets and path normalization

src/api/codexGateway.ts


6. src/server/httpServer.ts ✨ Enhancement +4/-1

Localhost trust configuration support

• Added trustLocalhost option to ServerOptions type
• Updated auth session creation to pass trustLocalhost configuration for conditional localhost
 trust

src/server/httpServer.ts


7. src/components/content/ComposerSkillPicker.vue ✨ Enhancement +2/-1

Customizable search placeholder in skill picker

• Added searchPlaceholder prop to allow customizable search input placeholder text
• Updated placeholder binding to use prop value with fallback to generic 'Search...' text

src/components/content/ComposerSkillPicker.vue


8. src/components/layout/DesktopLayout.vue Formatting +1/-1

Responsive mobile drawer width adjustment

• Updated mobile drawer width constraint from fixed max-w-80 to responsive w-[min(92vw,28rem)]
 for better mobile layout

src/components/layout/DesktopLayout.vue


9. src/api/normalizers/v2.ts ✨ Enhancement +93/-1

Add MCP tool call and reasoning message type support

• Added McpToolCallData import and new normalizeMcpToolCallStatus() function to normalize MCP
 tool call status values
• Enhanced toUiMessages() to handle reasoning type items by extracting and filtering
 summary/content text
• Added support for mcpToolCall message type with server, tool, status, and result/error text
 fields
• Added support for collabAgentToolCall message type with agent states, receiver threads, and
 collaboration metadata

src/api/normalizers/v2.ts


10. src/server/skillsRoutes.ts ✨ Enhancement +37/-30

Replace symlink creation with plain file conversion logic

• Removed unused imports (readlink, symlink) from fs/promises
• Refactored ensureCodexAgentsSymlinkToSkillsAgents() to ensureCodexAgentsFilesArePlainFiles()
 to convert symlinks to plain files instead of creating them
• Added getPathState() helper to check if paths are files, missing, or unsafe
 (symlinks/directories)
• Moved function call earlier in startup sequence before checking GitHub token

src/server/skillsRoutes.ts


11. src/server/authMiddleware.ts ✨ Enhancement +25/-5

Add secure transport detection and configurable localhost trust

• Added DEFAULT_TRUST_LOCALHOST constant and AuthSessionOptions type for configurable localhost
 trust
• Added requestUsesSecureTransport() function to detect HTTPS via x-forwarded-proto header
• Updated isAuthorizedByRequestLike() to accept trustLocalhost parameter
• Enhanced Set-Cookie header to include Secure flag when using HTTPS

src/server/authMiddleware.ts


12. src/types/codex.ts ✨ Enhancement +47/-0

Add MCP, collaboration, and worktree target type definitions

• Added McpToolCallData type with server, tool, status, and text fields for MCP tool execution
• Added CollabAgentStateData and CollabToolCallData types for collaborative agent tool calls
• Added UiReviewWorktreeTarget type for git worktree selection in review pane
• Extended UiMessage with optional mcpToolCall and collabToolCall fields
• Extended UiLiveOverlay with activity summary, background agents, and updated timestamp
• Extended UiReviewSnapshot with worktreeTargets array

src/types/codex.ts


13. src/composables/useMobile.ts ✨ Enhancement +33/-8

Improve mobile layout detection with pointer capability checks

• Added NARROW_LAYOUT_BREAKPOINT constant (640px) for better mobile detection
• Refactored detectMobileLayout() to check both viewport width and coarse pointer capability
• Enhanced media query listeners to track width, pointer type, and window resize events
• Added visualViewport resize listener for better mobile viewport handling

src/composables/useMobile.ts


14. src/App.vue ✨ Enhancement +718/-597

Refactor settings UI and add message editing, session status, and MCP management

• Removed account management UI (login, switch, remove accounts) and related state/functions
• Removed Telegram bot configuration and GitHub trending projects toggle from settings
• Removed dictation language selector from settings panel
• Added session status overview section showing model, reasoning, speed, collab, approval, and
 sandbox settings
• Added MCP servers configuration section with reload capability
• Added quota/limits display section with 5-hour and weekly limit tracking
• Added past message edit functionality with dedicated composer panel and rollback support
• Added thread status filter (all/running/new) and mark-all-seen capability
• Added /slash-command support for review, fork, resume, status, and mcp commands
• Restructured settings panel for mobile with backdrop, header handle, and scrollable body
• Enhanced mobile detection to always show trending projects

src/App.vue


15. src/components/sidebar/SidebarThreadTree.vue ✨ Enhancement +278/-55

Add thread status filtering and improve thread organization UI

• Added pinned section label and thread status filter UI (all/running/new tabs)
• Added threadStatusFilter state with localStorage persistence
• Added visibleUnreadThreadIds computed property and mark-all-seen functionality
• Enhanced thread sorting to prioritize running/unread threads with timestamp fallback
• Removed pin button from thread rows; added pin/unpin option to context menu
• Updated thread indicator to show only running/unread states with accessibility labels
• Added "Show N more" label to expand buttons showing hidden thread count
• Updated empty state messages based on active filters

src/components/sidebar/SidebarThreadTree.vue


16. src/components/content/ReviewPane.vue ✨ Enhancement +104/-11

Add git worktree selection and read-only mode for alternate worktrees

• Added worktree target selector dropdown when multiple git worktrees are available
• Added selectedTargetCwd state and isViewingAlternateWorktree computed property
• Disabled review actions and findings tab when viewing alternate worktrees (read-only mode)
• Added informational banner when viewing alternate worktrees
• Added worktree target label to review summary display
• Added normalizeComparablePath() helper for consistent path comparison

src/components/content/ReviewPane.vue


17. src/components/content/QueuedMessages.vue ✨ Enhancement +43/-2

Display model and reasoning settings in queued messages

• Added modelId, reasoningEffort, and speedMode fields to QueuedMessageRow type
• Added getRuntimeSummary() function to display model, reasoning, and speed settings
• Added runtime summary display below queued message text
• Added helper functions formatModelLabel() and formatReasoningLabel() for consistent formatting

src/components/content/QueuedMessages.vue


18. src/components/content/ThreadConversation.vue ✨ Enhancement +894/-68

Enhanced conversation UI with tool calls, reasoning, and live overlay improvements

• Added support for MCP tool calls and collaboration tool calls as new message types with dedicated
 UI components and expansion/collapse functionality
• Enhanced message visibility filtering with hiddenWorkedToolIds and hiddenLiveRuntimeMessageIds
 computed properties to manage message display during worked and live runtime states
• Added reasoning message type support with a new reasoning-card component for displaying thinking
 summaries
• Refactored worked section to display mixed activities (commands, MCP tools, collab tools) instead
 of just commands, with activity count metadata
• Added live overlay enhancements including status text, activity details list, and background
 agents section with status tracking
• Implemented user message edit button with showEditUserMessageButton and editUserMessage
 functionality
• Added live overlay clock timer to track and display update staleness with computed
 liveOverlayStatusText
• Refactored scroll state management with buildScrollState helper and improved scroll restoration
 logic with mode parameter

src/components/content/ThreadConversation.vue


19. src/components/content/ThreadComposer.vue ✨ Enhancement +597/-167

Added slash commands, inline edit mode, and improved composer UX

• Added inline edit mode support with appearance prop and conditional rendering of controls based
 on isInlineEdit state
• Implemented slash command system with /compact, /review, /fork, /resume, /model,
 /plan, /collab, /status, /mcp commands
• Refactored skill picker to unified menu system supporting both slash commands and skills with
 menuMode and menuOptions computed properties
• Added IME composition handling with isImeComposing state and isImeConfirmEnter detection for
 proper keyboard input handling
• Enhanced keyboard submit logic with resolveKeyboardSubmitMode to support Tab key for queuing and
 improved mode determination
• Added context usage badge display with auto-compact threshold calculation and tone-based styling
• Added compact button and improved submit button labels/titles based on current state
• Implemented draft persistence control with shouldPersistDraft and persistDraft prop
• Added mobile responsive styles with adjusted layout, sizing, and menu positioning

src/components/content/ThreadComposer.vue


20. src/components/content/ComposerDropdown.vue ✨ Enhancement +57/-2

Added mobile menu positioning and exposed dropdown control methods

• Added positionMenuForMobile function to reposition dropdown menu on mobile devices with proper
 viewport calculations
• Exposed openMenu and closeMenu methods via defineExpose for programmatic menu control
• Added mobile-specific styles to position dropdown menu as fixed element with proper left/right
 constraints

src/components/content/ComposerDropdown.vue


21. src/components/sidebar/SidebarThreadControls.vue ✨ Enhancement +10/-0

Added mobile responsive styling for thread controls

• Added mobile responsive styles with adjusted gap and button sizing for screens under 640px width

src/components/sidebar/SidebarThreadControls.vue


22. src/components/content/ContentHeader.vue ✨ Enhancement +15/-0

Added mobile responsive styling for content header

• Added mobile responsive styles with adjusted height, padding, font size, and gap for screens under
 640px width

src/components/content/ContentHeader.vue


23. scripts/codexapp-current-dir.sh ⚙️ Configuration changes +319/-0

New local repository launcher script with MCP support

• New bash script for launching codexUI from a local repository clone with Serena MCP compatibility
• Configures environment variables for local development including CODEX_HOME,
 TELEGRAM_DEFAULT_CWD, and proxy settings
• Handles dependency installation and artifact building with staleness detection
• Supports optional cloudflared tunnel forwarding with token file and password authentication
• Provides command-line options for host, port, tunnel configuration, and authentication modes

scripts/codexapp-current-dir.sh


24. src/style.css ✨ Enhancement +36/-0

Added dark mode styles for mobile settings and filters

• Added dark mode styles for sidebar settings mobile header, handle, title, and close button
• Added dark mode styles for settings key-value metadata text
• Added dark mode styles for thread status filter buttons, counts, and actions

src/style.css


25. README.md 📝 Documentation +23/-0

Added documentation for local repository launcher

• Added new section documenting local repository launcher with Serena MCP compatibility
• Documented launcher features including environment variable configuration, thread scoping, and MCP
 integration
• Listed relevant bundled files for the launcher setup

README.md


26. scripts/serena-python-bootstrap/sitecustomize.py ⚙️ Configuration changes +19/-0

New Python bootstrap shim for pyright compatibility

• New Python module providing install_pyright function for bootstrap shim compatibility
• Installs custom pyright._utils module to handle pyright distribution discovery from sys.path

scripts/serena-python-bootstrap/sitecustomize.py


27. scripts/serena-mcp-wrapper.py Additional files +405/-0

...

scripts/serena-mcp-wrapper.py


28. tests.md Additional files +328/-5

...

tests.md


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Apr 13, 2026

Code Review by Qodo

🐞 Bugs (2)   📘 Rule violations (0)   📎 Requirement gaps (0)
🐞\ ⛨ Security (2)

Grey Divider


Action required

1. Spoofable Secure auth cookie 🐞
Description
requestUsesSecureTransport() trusts the client-controlled x-forwarded-proto header even though
the Express app does not enable trust proxy, so a plain-HTTP client can force the login handler to
set a Secure cookie that the browser will never send back over HTTP (breaking auth). This can
cause users to be stuck in the login page even with the correct password.
Code

src/server/authMiddleware.ts[R28-37]

+function requestUsesSecureTransport(req: Request): boolean {
+  if (req.secure) return true
+  const forwardedProto = req.headers['x-forwarded-proto']
+  if (typeof forwardedProto === 'string') {
+    return forwardedProto.split(',').some((value) => value.trim().toLowerCase() === 'https')
+  }
+  if (Array.isArray(forwardedProto)) {
+    return forwardedProto.some((value) => value.trim().toLowerCase() === 'https')
+  }
+  return false
Evidence
requestUsesSecureTransport() considers x-forwarded-proto=https sufficient to treat the request
as secure, and that result is used to append ; Secure to the auth cookie. However, the server
constructs the Express app without configuring trust proxy, so x-forwarded-proto is not a
trusted signal and can be spoofed by clients, leading to a Secure cookie being set on non-TLS
requests (cookie will not be returned by browsers over HTTP).

src/server/authMiddleware.ts[28-37]
src/server/authMiddleware.ts[141-146]
src/server/httpServer.ts[72-86]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`src/server/authMiddleware.ts` sets the auth cookie with the `Secure` attribute based on `requestUsesSecureTransport()`, which currently trusts `x-forwarded-proto`. Because the Express app in `src/server/httpServer.ts` does not configure `trust proxy`, `x-forwarded-proto` must be treated as untrusted user input; spoofing it can cause the server to set a `Secure` cookie on an HTTP connection, breaking subsequent authentication.

### Issue Context
- If the app is not behind a trusted reverse proxy, `x-forwarded-proto` is client-controlled.
- If the app *is* behind a trusted reverse proxy, Express should be configured to trust that proxy so `req.secure` becomes the canonical signal.

### Fix Focus Areas
- src/server/authMiddleware.ts[28-37]
- src/server/authMiddleware.ts[141-146]
- src/server/httpServer.ts[72-86]

### Desired fix
- Stop directly trusting `x-forwarded-proto` unless the server is explicitly configured to trust proxies.
 - Simplest safe change: make `requestUsesSecureTransport` return `req.secure` only.
 - If proxy support is required: add an explicit `trustProxy`/`behindProxy` option, call `app.set('trust proxy', ...)` in `createServer`, and then rely on `req.secure` (which will incorporate `x-forwarded-proto` only when trusted).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Symlink read during repair 🐞
Description
ensureCodexAgentsFilesArePlainFiles() identifies symlinks/non-files as "unsafe" via lstat(), but
then calls readFile(codexAgentsPath) before removing the unsafe path, which follows symlinks and
reads the target content. That content can then be written into AGENTS.md and later
committed/pushed during skills sync, unintentionally persisting sensitive file contents.
Code

src/server/skillsRoutes.ts[R1022-1032]

+  await mkdir(skillsDir, { recursive: true })
+  let content = ''
  try {
-    const current = await lstat(codexAgentsPath)
-    if (current.isSymbolicLink()) {
-      const existingTarget = await readlink(codexAgentsPath)
-      if (existingTarget === relativeTarget) return
+    content = await readFile(codexAgentsPath, 'utf8')
+  } catch {
+    try {
+      content = await readFile(skillsAgentsPath, 'utf8')
+    } catch {
+      content = ''
    }
+  }
Evidence
The repair logic marks any non-regular file (including symlinks) as unsafe using lstat(), but
still reads codexAgentsPath via readFile() before deleting it—readFile() follows symlinks. The
resulting content is written back into AGENTS.md, and the skills sync flow stages and commits
the repo (including AGENTS.md), which can persist and potentially push the unintended contents to
the configured remote.

src/server/skillsRoutes.ts[999-1042]
src/server/skillsRoutes.ts[841-918]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`ensureCodexAgentsFilesArePlainFiles()` is meant to remediate "unsafe" AGENTS.md paths (symlinks, directories, etc.), but it currently reads from `codexAgentsPath` even when that path was classified as unsafe. Because `readFile()` follows symlinks, this dereferences the unsafe path and can ingest arbitrary file contents.

### Issue Context
- `getPathState()` uses `lstat()` and returns `unsafe` for any non-regular file.
- The current implementation reads `codexAgentsPath` first regardless of state, then deletes and rewrites files.
- Downstream, skills sync stages/commits the working tree, which can persist/push `AGENTS.md`.

### Fix Focus Areas
- src/server/skillsRoutes.ts[999-1042]
- src/server/skillsRoutes.ts[841-918]

### Desired fix
- Never `readFile()` from a path that is classified as `unsafe`.
- Choose content only from safe sources:
 - If `codexAgentsState === 'file'`, read `codexAgentsPath`.
 - Else if `skillsAgentsState === 'file'`, read `skillsAgentsPath`.
 - Else use empty string.
- Optionally, cap file size read to avoid large-file issues.
- Then perform the removal + rewrite for any unsafe path(s) using the chosen safe `content`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines +28 to +37
function requestUsesSecureTransport(req: Request): boolean {
if (req.secure) return true
const forwardedProto = req.headers['x-forwarded-proto']
if (typeof forwardedProto === 'string') {
return forwardedProto.split(',').some((value) => value.trim().toLowerCase() === 'https')
}
if (Array.isArray(forwardedProto)) {
return forwardedProto.some((value) => value.trim().toLowerCase() === 'https')
}
return false
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Spoofable secure auth cookie 🐞 Bug ⛨ Security

requestUsesSecureTransport() trusts the client-controlled x-forwarded-proto header even though
the Express app does not enable trust proxy, so a plain-HTTP client can force the login handler to
set a Secure cookie that the browser will never send back over HTTP (breaking auth). This can
cause users to be stuck in the login page even with the correct password.
Agent Prompt
### Issue description
`src/server/authMiddleware.ts` sets the auth cookie with the `Secure` attribute based on `requestUsesSecureTransport()`, which currently trusts `x-forwarded-proto`. Because the Express app in `src/server/httpServer.ts` does not configure `trust proxy`, `x-forwarded-proto` must be treated as untrusted user input; spoofing it can cause the server to set a `Secure` cookie on an HTTP connection, breaking subsequent authentication.

### Issue Context
- If the app is not behind a trusted reverse proxy, `x-forwarded-proto` is client-controlled.
- If the app *is* behind a trusted reverse proxy, Express should be configured to trust that proxy so `req.secure` becomes the canonical signal.

### Fix Focus Areas
- src/server/authMiddleware.ts[28-37]
- src/server/authMiddleware.ts[141-146]
- src/server/httpServer.ts[72-86]

### Desired fix
- Stop directly trusting `x-forwarded-proto` unless the server is explicitly configured to trust proxies.
  - Simplest safe change: make `requestUsesSecureTransport` return `req.secure` only.
  - If proxy support is required: add an explicit `trustProxy`/`behindProxy` option, call `app.set('trust proxy', ...)` in `createServer`, and then rely on `req.secure` (which will incorporate `x-forwarded-proto` only when trusted).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +1022 to +1032
await mkdir(skillsDir, { recursive: true })
let content = ''
try {
const current = await lstat(codexAgentsPath)
if (current.isSymbolicLink()) {
const existingTarget = await readlink(codexAgentsPath)
if (existingTarget === relativeTarget) return
content = await readFile(codexAgentsPath, 'utf8')
} catch {
try {
content = await readFile(skillsAgentsPath, 'utf8')
} catch {
content = ''
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Symlink read during repair 🐞 Bug ⛨ Security

ensureCodexAgentsFilesArePlainFiles() identifies symlinks/non-files as "unsafe" via lstat(), but
then calls readFile(codexAgentsPath) before removing the unsafe path, which follows symlinks and
reads the target content. That content can then be written into AGENTS.md and later
committed/pushed during skills sync, unintentionally persisting sensitive file contents.
Agent Prompt
### Issue description
`ensureCodexAgentsFilesArePlainFiles()` is meant to remediate "unsafe" AGENTS.md paths (symlinks, directories, etc.), but it currently reads from `codexAgentsPath` even when that path was classified as unsafe. Because `readFile()` follows symlinks, this dereferences the unsafe path and can ingest arbitrary file contents.

### Issue Context
- `getPathState()` uses `lstat()` and returns `unsafe` for any non-regular file.
- The current implementation reads `codexAgentsPath` first regardless of state, then deletes and rewrites files.
- Downstream, skills sync stages/commits the working tree, which can persist/push `AGENTS.md`.

### Fix Focus Areas
- src/server/skillsRoutes.ts[999-1042]
- src/server/skillsRoutes.ts[841-918]

### Desired fix
- Never `readFile()` from a path that is classified as `unsafe`.
- Choose content only from safe sources:
  - If `codexAgentsState === 'file'`, read `codexAgentsPath`.
  - Else if `skillsAgentsState === 'file'`, read `skillsAgentsPath`.
  - Else use empty string.
- Optionally, cap file size read to avoid large-file issues.
- Then perform the removal + rewrite for any unsafe path(s) using the chosen safe `content`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Codex and others added 9 commits April 14, 2026 03:46
Consolidate live stage summaries into the conversation timeline, hide redundant stage summary rows, and normalize reasoning effort values to the currently supported set.
Rework the composer control layout for mobile, keep Enter-to-send disabled on mobile, and hide the desktop review affordance from narrow layouts.
Track the new openspec change set in git and update manual verification coverage for the timeline and mobile composer work.
@friuns2 friuns2 closed this Apr 24, 2026
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