Skip to content

Codex Cookbook bearer routes have an inconsistent admin boundary #5676

Description

@RaresKeY

Prerequisites

  • I searched open issues and discussions and did not find an existing report of this bug.
  • This is not a security vulnerability. (Vulnerabilities go to GitHub Security Advisories — see SECURITY.md.)
  • I am running the latest code from the dev branch (the default branch you get on clone, where fixes land first) and the bug still reproduces there. Please git pull the latest dev before filing.

Install Method

Manual Python install (pip / venv)

Operating System

Linux

Steps to Reproduce

  1. On current dev, create an API token with the advertised cookbook:read or cookbook:launch scope.
  2. Call the scoped /api/codex/cookbook/* routes with that bearer token.
  3. Observe an inconsistent boundary: some routes fall back into the cookie-session admin gate, while others expose shared task, host, preset, log, tmux, or lifecycle state directly to the token.

Expected Behaviour

Cookbook model installation, launch, SSH host control, task logs, saved commands, and stored deployment credentials should remain inside the existing trusted, operator-controlled in-app/admin boundary. API tokens and the shipped Codex/Claude integrations should consume inference through the model APIs and endpoints the user has already configured, not administer model deployment through a second bearer-token layer.

Every request presenting an Odysseus API bearer credential or valid internal-tool credential to /api/codex/cookbook/* should fail closed before reading Cookbook state or configuration and before touching credentials, files, the network, SSH, tmux, processes, or endpoint records. New API tokens should not advertise or accept Cookbook scopes. Existing tokens may retain inert legacy scope strings until the operator rotates or revokes them; no destructive token migration should guess at provenance.

Actual Behaviour

Current dev advertises cookbook:read and cookbook:launch as mintable API-token scopes and ships agent instructions for them. The route family mixes handlers that reject the API pseudo-user with handlers that can inspect or control shared Cookbook state after only the scope check. This makes the effective authority difficult to explain, review, and maintain, particularly around stored credentials and remote process lifecycle.

Logs / Screenshots

The behavior is deterministic at the route authorization boundary and can be covered with focused no-side-effect handler regressions; no runtime log is required.

Model / Backend (if relevant)

Not relevant.

Are you willing to submit a fix?

Yes — I can open a PR

Additional Information

Proposed focused correction:

  • reject raw Odysseus bearer and valid internal-tool credentials before authentication or request-body work, with route and handler backstops for stamped principals before any state, configuration, credential, filesystem, network, SSH, tmux, process, or endpoint access;
  • keep direct Cookbook and /api/model/* routes available to the existing trusted in-app/admin callers;
  • remove cookbook:read and cookbook:launch from the mintable token scope catalog and token-management UI;
  • remove Cookbook administration commands and claims from the shipped Codex and Claude bearer-token helpers and documentation;
  • leave existing token rows intact, with any legacy Cookbook scope strings inert.

Acceptance criteria:

  • Every request presenting an Odysseus bearer or valid internal-tool credential to the duplicate Cookbook route family returns a non-enumerating 403 before side effects.
  • New tokens cannot be minted with Cookbook scopes and the UI does not advertise them.
  • The shipped Codex and Claude bundles do not instruct agents to inspect or deploy models through Cookbook routes.
  • Existing trusted in-app/admin callers retain the current Cookbook and direct model-management behavior.
  • Generic /api/v1/chat, /api/models, configured model endpoints, and unrelated Codex/Claude tools remain unchanged.
  • Focused tests prove the bearer rejection happens before state, credential, network, shell, process, and endpoint access.

This reports a documented scope and product-authority mismatch, not access beyond a credential's advertised authority. Separately, #3149 should keep this route family absent from its centralized bearer-capability manifest as defense in depth; that manifest change is not part of this focused fix.

Related: parent stabilization tracker #5674 and default-deny API-token capability tracker #3149.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingready for reviewDescription complete — ready for maintainer review

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions