| const logger = require('../../utils/logger') |
| const { CLIENT_DEFINITIONS } = require('../clientDefinitions') |
|
|
| |
| |
| |
| |
| class CodexCliValidator { |
| |
| |
| |
| static getId() { |
| return CLIENT_DEFINITIONS.CODEX_CLI.id |
| } |
|
|
| |
| |
| |
| static getName() { |
| return CLIENT_DEFINITIONS.CODEX_CLI.name |
| } |
|
|
| |
| |
| |
| static getDescription() { |
| return CLIENT_DEFINITIONS.CODEX_CLI.description |
| } |
|
|
| |
| |
| |
| |
| |
| static validate(req) { |
| try { |
| const userAgent = req.headers['user-agent'] || '' |
| const originator = req.headers['originator'] || '' |
| const sessionId = req.headers['session_id'] |
|
|
| |
| |
| |
| |
| const codexCliPattern = /^(codex_vscode|codex_cli_rs)\/[\d\.]+/i |
| const uaMatch = userAgent.match(codexCliPattern) |
|
|
| if (!uaMatch) { |
| logger.debug(`Codex CLI validation failed - UA mismatch: ${userAgent}`) |
| return false |
| } |
|
|
| |
| |
| const strictValidationPaths = ['/openai', '/azure'] |
| const needsStrictValidation = |
| req.path && strictValidationPaths.some((path) => req.path.startsWith(path)) |
|
|
| if (!needsStrictValidation) { |
| |
| logger.debug(`Codex CLI detected for path: ${req.path}, allowing access`) |
| return true |
| } |
|
|
| |
| const clientType = uaMatch[1].toLowerCase() |
| if (originator.toLowerCase() !== clientType) { |
| logger.debug( |
| `Codex CLI validation failed - originator mismatch. UA: ${clientType}, originator: ${originator}` |
| ) |
| return false |
| } |
|
|
| |
| if (!sessionId || sessionId.length <= 20) { |
| logger.debug(`Codex CLI validation failed - session_id missing or too short: ${sessionId}`) |
| return false |
| } |
|
|
| |
| if ( |
| req.path && |
| (req.path.includes('/openai/responses') || req.path.includes('/azure/response')) |
| ) { |
| if (!req.body || !req.body.instructions) { |
| logger.debug(`Codex CLI validation failed - missing instructions in body for ${req.path}`) |
| return false |
| } |
|
|
| const expectedPrefix = |
| 'You are Codex, based on GPT-5. You are running as a coding agent in the Codex CLI' |
| if (!req.body.instructions.startsWith(expectedPrefix)) { |
| logger.debug(`Codex CLI validation failed - invalid instructions prefix for ${req.path}`) |
| logger.debug(`Expected: "${expectedPrefix}..."`) |
| logger.debug(`Received: "${req.body.instructions.substring(0, 100)}..."`) |
| return false |
| } |
|
|
| |
| if (req.body.model && req.body.model !== 'gpt-5-codex') { |
| logger.debug(`Codex CLI validation warning - unexpected model: ${req.body.model}`) |
| |
| } |
| } |
|
|
| |
| logger.debug(`Codex CLI validation passed for UA: ${userAgent}`) |
| return true |
| } catch (error) { |
| logger.error('Error in CodexCliValidator:', error) |
| |
| return false |
| } |
| } |
|
|
| |
| |
| |
| |
| static compareVersions(v1, v2) { |
| const parts1 = v1.split('.').map(Number) |
| const parts2 = v2.split('.').map(Number) |
|
|
| for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) { |
| const part1 = parts1[i] || 0 |
| const part2 = parts2[i] || 0 |
|
|
| if (part1 < part2) return -1 |
| if (part1 > part2) return 1 |
| } |
|
|
| return 0 |
| } |
|
|
| |
| |
| |
| static getInfo() { |
| return { |
| id: this.getId(), |
| name: this.getName(), |
| description: this.getDescription(), |
| icon: CLIENT_DEFINITIONS.CODEX_CLI.icon |
| } |
| } |
| } |
|
|
| module.exports = CodexCliValidator |
|
|