feat: add Codex OAuth voice-to-text input#4174
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
| setState("requesting"); | ||
| try { | ||
| const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); | ||
| if (operation !== operationRef.current) { |
There was a problem hiding this comment.
🟡 Medium chat/ComposerVoiceInput.tsx:109
startRecording only checks operationRef after getUserMedia resolves, so a pending microphone permission request is not cancelled when voice input becomes unavailable mid-prompt. If the composer becomes disabled or Codex OAuth becomes unavailable while the browser permission dialog is open, granting permission still starts recording and can later insert a transcription even though voice input is no longer available. The getUserMedia call is awaited without a cancellation path, so the stale operation check on line 109 only fires after the promise resolves — by then the user has already interacted with the permission prompt. Consider checking unavailableReason (or props.disabled / props.hasCodexOauth) again after getUserMedia resolves, before creating and starting the MediaRecorder.
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/chat/ComposerVoiceInput.tsx around line 109:
`startRecording` only checks `operationRef` after `getUserMedia` resolves, so a pending microphone permission request is not cancelled when voice input becomes unavailable mid-prompt. If the composer becomes disabled or Codex OAuth becomes unavailable while the browser permission dialog is open, granting permission still starts recording and can later insert a transcription even though voice input is no longer available. The `getUserMedia` call is awaited without a cancellation path, so the stale operation check on line 109 only fires after the promise resolves — by then the user has already interacted with the permission prompt. Consider checking `unavailableReason` (or `props.disabled` / `props.hasCodexOauth`) again after `getUserMedia` resolves, before creating and starting the `MediaRecorder`.
| headers: OptionalBearerHeaders, | ||
| payload: Schema.Struct({ | ||
| providerInstanceId: ProviderInstanceId, | ||
| audio: Schema.Uint8ArrayFromBase64, |
There was a problem hiding this comment.
🟠 High src/environmentHttp.ts:559
The /api/voice/transcribe endpoint accepts audio: Schema.Uint8ArrayFromBase64 with no size bound before decoding. An authenticated caller can submit an arbitrarily large base64 string, forcing the server to buffer the entire request body and allocate the decoded Uint8Array before the 25 MB check in transcribeCodexAudio runs. Sufficiently large requests exhaust server memory and crash the process. Consider enforcing a maximum request body size or a base64-string length constraint (e.g. Schema.isMaxLength) before the Uint8Array decode step.
🤖 Copy this AI Prompt to have your agent fix this:
In file @packages/contracts/src/environmentHttp.ts around line 559:
The `/api/voice/transcribe` endpoint accepts `audio: Schema.Uint8ArrayFromBase64` with no size bound before decoding. An authenticated caller can submit an arbitrarily large base64 string, forcing the server to buffer the entire request body and allocate the decoded `Uint8Array` before the 25 MB check in `transcribeCodexAudio` runs. Sufficiently large requests exhaust server memory and crash the process. Consider enforcing a maximum request body size or a base64-string length constraint (e.g. `Schema.isMaxLength`) before the `Uint8Array` decode step.
ApprovabilityVerdict: Needs human review 2 blocking correctness issues found. This PR introduces a new voice input feature with new API endpoints and UI components. An unresolved HIGH severity comment identifies a potential DoS vulnerability in the transcribe endpoint where unbounded request bodies are decoded before size validation. New feature scope plus security concern warrants human review. You can customize Macroscope's approvability policy. Learn more. |
What Changed
Why
This brings Codex-style dictation to the web composer without requiring a separate API key or client-selected transcription model. Authentication stays server-side and reuses the user’s existing Codex OAuth session.
UI Changes
Adds a microphone button beside the composer’s send action, with recording, transcribing, disabled, and error states.
Checklist
Note
Add voice-to-text transcription via Codex OAuth to the chat composer
POST /api/voice/transcribeendpoint to the environment HTTP API, defined in environmentHttp.ts and served by http.ts, gated byAuthOrchestrationOperateScope.auth.json, validates audio (max 25 MB), and posts tohttps://chatgpt.com/backend-api/transcribe.MediaRecorder, sends it to the transcription endpoint, and inserts the result at the cursor.EnvironmentHttpForbiddenError.📊 Macroscope summarized efb05ad. 5 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted
🗂️ Filtered Issues
No issues evaluated.