Skip to content

feat(cli): offer scan model and reasoning upgrades - #806

Draft
daneschneider-oai wants to merge 7 commits into
mainfrom
codex/security-model-nudges-cli
Draft

feat(cli): offer scan model and reasoning upgrades#806
daneschneider-oai wants to merge 7 commits into
mainfrom
codex/security-model-nudges-cli

Conversation

@daneschneider-oai

@daneschneider-oai daneschneider-oai commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

Offer one model/effort nudge before scanning. Keep startup and prompts in the normal terminal until scan activity begins.

Changes

Use catalog-backed upgrades and share choices across matching scans. Check native ChatGPT authentication first; require TTY input and output for interactive UI.

Interaction and copy

Combine applicable sentences into one stderr warning:

codex-security: warning: {current_model} is designed for dynamic exploitation. You may get better vulnerability scanning results with {recommended_non_cyber_model}. {new_model} is available as an upgrade to {current_model} and may give better scanning results. The configured reasoning effort is {current_effort}. Use xhigh for the best scanning results.

Ask one confirmation for eligible changes:

  • Use {new_model} with xhigh reasoning for this scan?
  • Use {new_model} for this scan?
  • Use xhigh reasoning for this scan?

Default No. Yes applies the proposed changes for this command. Headless/JSON/CI runs warn without prompts or changes. Dry runs skip the lookup. Missing catalog metadata still permits the xhigh opt-in; explicitly unsupported efforts are excluded.

Detected sign-in failure:

Codex Security's stored ChatGPT sign-in is no longer available. Run 'codex-security login' and retry.

Testing

293 focused tests, real PTY checks, and bundled Codex 0.149.1 with synthetic local authentication responses. Typecheck and formatting passed.

Risk and rollout

Catalog failures remain advisory. Saved settings and cost limits are preserved. Authentication uses native conditional refresh.

Companion: plugin #805.

Public disclosure review

  • No customer, partner, prospect, or user identities, data, or identifying details are included.
  • No credentials, personal data, private source, scan findings, or nonpublic links or tickets are included.
  • I reviewed the branch name, title, description, commits, changes, comments, logs, screenshots, attachments, and links for public disclosure.

@github-actions github-actions Bot added the enhancement New feature or request label Sep 3, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review Completed 2026-09-04T20:11:57.806694Z 5281ef7 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@daneschneider-oai
daneschneider-oai marked this pull request as draft September 3, 2026 22:25
@daneschneider-oai
daneschneider-oai marked this pull request as ready for review September 3, 2026 23:48

@sylvesterkaczmarek sylvesterkaczmarek left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hi, the no-catalogue path treats an unknown model as supporting xhigh (model === undefined), so the CLI can still print “Use xhigh for the best scanning results” even when it could not load the catalogue or verify support. Could the warning keep the same “if your model supports it” qualifier instead of asserting xhigh for an unknown model?

@daneschneider-oai
daneschneider-oai marked this pull request as draft September 4, 2026 20:56

@mldangelo-oai mldangelo-oai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed exact draft head 5281ef76d3021a42b216aeac2e96831fa6fc7847. Two correctness issues and one cross-surface simplification are inline below. I did not repeat the existing unknown-model/xhigh feedback, which remains applicable.

let choice = choices.get(key);
if (choice === undefined) {
choice = choose(configuration, loadModels, signal);
choices.set(key, choice);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] Evict rejected selections from the shared cache

choices retains a rejected promise indefinitely. If the first selection for a configuration rejects during authentication discovery or confirmation, later component workers and bulk-scan retries reuse that rejection without invoking their own loader or prompt. Please preserve the useful in-flight and successful-choice caching, but remove the entry on rejection with an identity guard so an older promise cannot delete a replacement. Add a regression showing that a second call invokes a fresh loader and succeeds after the first rejects.

Comment thread sdk/typescript/src/cli.ts
: { maxCostUsd: options.maxCost }),
},
createSecurity: dependencies.createSecurity,
createSecurity: (config) =>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] Apply the accepted model choice to the whole component command

Passing chooseModel only into each CodexSecurity worker makes the accepted choice worker-local. With --auto, planning has already run with config before selection occurs, and cross-component matching later receives that same unchanged config. Accepting the offered upgrade therefore changes component scans and the dashboard but leaves planning and root-cause matching on the old model and effort, despite the README saying the choice applies to the current command. Please resolve selection once before component orchestration and pass one command-local effective config to planning, workers, matching, and the dashboard; add an integration test covering all three model-call stages.

);
let cyberWarning: string | undefined;
if (isNonAstraCyberModel(selectedModel?.model ?? model)) {
const defaultModel = availableModels?.find(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P3] Drive both guidance surfaces from one policy contract

getScanModelAdvice() duplicates the pure upgrade/default/cyber/reasoning policy also added in #805, and the implementations already diverge. For example, #805 can follow a cyber default's declared chain to a visible non-cyber successor, while this implementation filters out that default before traversal. Keep the package-specific app-server, authentication, and prompt adapters separate, but put the pure policy in a shared module if packaging permits, or at least run both implementations against shared conformance vectors. That prevents the two surfaces from producing different advice for the same catalog.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants