Conversation
There was a problem hiding this comment.
4 issues found across 18 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="tests/test_codex_auth.py">
<violation number="1" location="tests/test_codex_auth.py:53">
P2: Missing assertion on `credential.refresh_token` (and `credential.account_id`) for the returned object. The test verifies these fields in the saved file but not on the credential returned to the caller, so a bug where the returned object carries stale values would go undetected.</violation>
</file>
<file name="kong/llm/codex_auth.py">
<violation number="1" location="kong/llm/codex_auth.py:97">
P1: Credentials file is written with default permissions (world-readable). The refresh token and access token are sensitive — restrict the file to owner-only (`0o600`) to prevent other users on the system from reading them.</violation>
</file>
<file name="tests/test_cli.py">
<violation number="1" location="tests/test_cli.py:181">
P2: Missing return-value assertion. Every other test in `TestCreateLLMClient` captures the result and checks `isinstance(client, ...)`, but this test discards the return value. Add the assertion to verify `create_llm_client` actually returns the `CodexClient` instance.</violation>
</file>
<file name="kong/llm/codex_client.py">
<violation number="1" location="kong/llm/codex_client.py:297">
P1: SSE parser silently drops the last event if the stream doesn't end with a trailing blank line. After the `while True` loop exits (on EOF), any remaining `data_lines` are never flushed. If `response.completed` is the final event and it lacks a trailing blank line, `completed_response` will be `None` and the request will fail.</violation>
</file>
Since this is your first cubic review, here's how it works:
- cubic automatically reviews your code and comments on bugs and improvements
- Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
- Add one-off context when rerunning by tagging
@cubic-dev-aiwith guidance or docs links (includingllms.txt) - Ask questions if you need clarification on any suggestion
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
There was a problem hiding this comment.
1 issue found across 5 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="kong/llm/codex_auth.py">
<violation number="1" location="kong/llm/codex_auth.py:98">
P2: TOCTOU race: credentials are briefly world-readable between `write_text` and `chmod`. The file is created with the default umask (often `0o644`) before permissions are tightened. Use `os.open` with explicit mode to avoid the window.
For example, write via a file descriptor opened with `0o600` so the file never has open permissions.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| auth_path = current.auth_path or codex_auth_path() | ||
| auth_path.parent.mkdir(parents=True, exist_ok=True) | ||
| auth_path.write_text(json.dumps(updated, indent=2), encoding="utf-8") | ||
| _restrict_auth_file_permissions(auth_path) |
There was a problem hiding this comment.
P2: TOCTOU race: credentials are briefly world-readable between write_text and chmod. The file is created with the default umask (often 0o644) before permissions are tightened. Use os.open with explicit mode to avoid the window.
For example, write via a file descriptor opened with 0o600 so the file never has open permissions.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At kong/llm/codex_auth.py, line 98:
<comment>TOCTOU race: credentials are briefly world-readable between `write_text` and `chmod`. The file is created with the default umask (often `0o644`) before permissions are tightened. Use `os.open` with explicit mode to avoid the window.
For example, write via a file descriptor opened with `0o600` so the file never has open permissions.</comment>
<file context>
@@ -95,6 +95,7 @@ def refresh_codex_credential(credential: CodexCredential | None = None) -> Codex
auth_path = current.auth_path or codex_auth_path()
auth_path.parent.mkdir(parents=True, exist_ok=True)
auth_path.write_text(json.dumps(updated, indent=2), encoding="utf-8")
+ _restrict_auth_file_permissions(auth_path)
return CodexCredential(
</file context>
Summary
This adds a first-class
codexprovider to Kong, backed by the ChatGPT Codex OAuth flow instead of the standard OpenAI API.What changed
LLMProvider.CODEXCodexClientfor ChatGPT Codex backend requestscodex_authhelpers for loading and refreshing local Codex OAuth credentialskong setup, provider resolution, endpoint probing, and CLI messagingopenaiandcustomprovider behavior intactWhy
Kong previously could reuse a local Codex login only as a credential source for the normal OpenAI API path. That still fails for accounts without OpenAI API billing.
This change adds a real Codex-backed path so users can run Kong through their local ChatGPT/Codex login directly.
Verification
uv run pytest -q448 passedSummary by cubic
Adds a first-class
codexprovider that talks to the ChatGPT Codex backend via OAuth, independent of the OpenAI API. Users can run Kong with a local ChatGPT login; setup, probing, routing, and usage reporting were updated (tokens only, no cost).New Features
LLMProvider.CODEXand a Codex client with SSE streaming, tool-calling, token usage, and OAuth auto-refresh on 401s.codex_authloads/refreshes from~/.codex/auth.json(override withCODEX_HOME);openai_authnow auto-resolvesOPENAI_API_KEY, Codex API key, or Codex OAuth; the OpenAI client re-resolves credentials dynamically.codexandAnthropic + Codex, shows credential source labels, and guides to runcodex; provider labels/help updated; default Codex model isgpt-5-codex; clearer errors when Codex login is missing or when OpenAI uses Codex OAuth without API billing.codexas non-billable (token counts only; exports mark cost tracking off); README adds Codex sign-in (codex),CODEX_HOME, separate billing notes, and--provider codexexamples.Migration
openaiandcustombehavior unchanged.codexto sign in, thenkong setupand choosecodex(orAnthropic + Codex).openairuns via Codex OAuth and requests fail, enable OpenAI API billing or setOPENAI_API_KEY.Written for commit 300ad95. Summary will update on new commits.