Summary
scanApprovalPolicy() does not use the same selected-profile precedence as the other effective Codex settings.
Model, reasoning effort, and provider resolution all prefer an explicitly configured value in the selected profile over the root value. Approval policy instead computes:
return config["approval_policy"] === "never" ||
selectedScanProfile(config)?.["approval_policy"] === "never"
? "never"
: "on-request";
If the root config says approval_policy = "never" and the selected profile explicitly says approval_policy = "on-request", this returns "never" rather than the selected profile's value.
Impact
This is not display-only. The resolved value is passed to codex.startThread({ approvalPolicy }), written into the scan recipe/preflight configuration, and projected into scanRuntimeCodexConfig().
A selected profile therefore cannot restore on-request approvals when the root config is more restrictive, even though profile-specific model/provider settings already override their root counterparts.
Expected behavior
If the selected profile has its own approval_policy, resolve that value first. Otherwise fall back to the root setting. Codex Security only needs to distinguish the supported never and on-request outcomes.
Suggested fix
Mirror scanModelProvider()/scanModelConfiguration() precedence for approval_policy, and add regression cases for both directions:
- root
never, selected profile on-request -> on-request;
- root
on-request, selected profile never -> never.
Summary
scanApprovalPolicy()does not use the same selected-profile precedence as the other effective Codex settings.Model, reasoning effort, and provider resolution all prefer an explicitly configured value in the selected profile over the root value. Approval policy instead computes:
If the root config says
approval_policy = "never"and the selected profile explicitly saysapproval_policy = "on-request", this returns"never"rather than the selected profile's value.Impact
This is not display-only. The resolved value is passed to
codex.startThread({ approvalPolicy }), written into the scan recipe/preflight configuration, and projected intoscanRuntimeCodexConfig().A selected profile therefore cannot restore on-request approvals when the root config is more restrictive, even though profile-specific model/provider settings already override their root counterparts.
Expected behavior
If the selected profile has its own
approval_policy, resolve that value first. Otherwise fall back to the root setting. Codex Security only needs to distinguish the supportedneverandon-requestoutcomes.Suggested fix
Mirror
scanModelProvider()/scanModelConfiguration()precedence forapproval_policy, and add regression cases for both directions:never, selected profileon-request->on-request;on-request, selected profilenever->never.