openai / openai/codex

Astra medium cyber_policy refusals: direct upstream response IDs and expanded replay/transport diagnostics

Open
#43,390 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app bug safety-check
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Prompt/context enrichment added with explicit user authorization: The diagnostic package now includes 64 visible user-role prompt messages, 42 recent visible tool/message exchanges, the immutable public campaign workflow, earlier context concerning unauthorized CPU stress and its containment, a bounded replay-state inventory, and 14 deduplicated historical root policy failures. See the prompt-enrichment follow-up for the exact immediate tool-result mapping, redactions, source provenance, and retained-state limitations. These are source excerpts, not an invented complete refused wire body.

What version of the Codex App are you using (From “About Codex” dialog)?

Desktop upstream build 26.901.51231, verified from installed package/build metadata rather than the About dialog. Community Linux RPM 2026.09.05.230300-1.fc41.x86_64. The affected rollout segment records Codex core 0.153.4. Expanded OpenCodex transaction diagnostics are included below.

Sanitized diagnostic package, including the full expanded transaction export and exact response-ID supplement.

What subscription do you have?

ChatGPT Pro, corroborated by plan_type: "pro" in the incident records. As reported in #42906, I use Pro 20x and have completed Cyber / Daybreak Blue verification. Those facts do not establish which entitlement the backend applied to these requests; the report distinguishes captured access metadata from unavailable backend policy information.

What platform is your computer?

Fedora Linux 44 Workstation; uname -mprs: Linux 7.1.10-200.fc44.x86_64 x86_64 unknown.

What issue are you seeing?

Three consecutive Astra-medium continuation turns terminated with cyber_policy during authorized bug-triage and PR-delivery coordination. This report adds newly captured proxy diagnostics for the recent sequence, rather than relying only on the preceding successful response IDs and approximate timing used in earlier reports.

  • Task title: Triage and fix all bugs.
  • Thread: codex://threads/01a07404-4b56-7562-bfc5-cc87a041a0f1.
  • Repository / campaign: donadiosolutions/lcm, Epic #968.
  • Related: #43131, which covers earlier Astra-low failures in this same task; #42906, an earlier root-coordinator incident; and #43320, a different task's Astra-high subagent refusal.

The user explicitly requested a new report for this newly instrumented sequence. A shared root cause with the related reports is not established. The apparent misclassification concerns ordinary corrective software work in my own repository, including triage, review evidence, PR merges, and retaining campaign state—not an instruction to attack a third-party system.

Exact recent failures

All timestamps in this table are UTC on 2026-09-07. Locally, the failures occurred at 04:54:08, 04:57:22, and 04:59:13 in America/Sao_Paulo (UTC−03:00).

Attempt Turn ID Task-start event Policy terminal event Recorded duration
1 01a07ada-567a-7223-91f6-9c02f39abb0a 07:52:04.490Z 07:54:08.739Z 124249 ms — 2m 4.249s
2 01a07adc-f0e0-7ee3-83e7-36975f793d0f 07:54:55.103Z 07:57:22.013Z 146911 ms — 2m 26.911s
3 01a07adf-57eb-7793-818f-6dc2b394dab1 07:57:32.541Z 07:59:13.125Z 100585 ms — 1m 40.585s

All three turn_context records identify gpt-6-astra, effort medium. The corresponding settings events identify provider openai and service tier default. Each terminal event is task_complete, with last_agent_message: null and error.codex_error_info: "cyber_policy". The Desktop task API independently returned these same three turn IDs with status failed, and the task itself as systemError at inspection.

This content was flagged for possible cybersecurity risk. If this seems wrong, try rephrasing your request. To get authorized for security work, join the Trusted Access for Cyber program: https://chatgpt.com/cyber

These are three root-turn terminations. User wording refers to triage refusals, but that wording alone is not evidence that a particular triage worker caused these failures.

What the coordinator was actually doing

The campaign had expanded, with explicit user instructions, beyond the original 37-Bug inventory. The recent work involved keeping existing PR owners active, verifying completed triage, preserving evidence/review budgets, merging approved corrections, and capturing the next batch of native Bug issues. The original campaign skill at the initial task revision describes the underlying maintenance/review workflow; later user-directed scope additions are part of the retained context.

Attempt 1: The user asked why work had stopped. The coordinator read open-PR states and the saved campaign counters and started reconciling live owner activity. The readback included existing delivery progress and blocked/dirty PRs; this was not a fresh attack or security-assessment prompt. The policy error interrupted the continuation after visible progress.

Attempt 2: The user requested another attempt. The coordinator read the S6 triage barrier and confirmed that all 25 new reports and duplicate adjudication were complete: 21 reproducible and four closed as nonreproducible, with no missing report or exceptional blocker in that barrier. It preserved completed triage rather than repeating it, updated the campaign record to 143 total/triaged, checked PR #1169's approved head and checks, and submitted its merge through GitHub's required asynchronous endpoint after the normal GraphQL merge rejected the stacked-PR operation. The async endpoint returned pending, a normal enqueued-merge result. The coordinator then inspected active owner assignments before the next cyber_policy termination.

Attempt 3: The coordinator acknowledged the user's S7 expansion instruction, dispatched the next triage lead, recorded the S7 capture request and PR #1169's merged state, and waited for worker progress. Its last completed collaboration wait was at 07:58:47.805Z; the policy termination occurred about 25 seconds later. These are the observed surrounding actions, not proof that any one tool result or phrase triggered the decision.

The case matters because meaningful state changes and completed maintenance work occur before termination. Recovery must preserve the campaign state and avoid duplicate triage, merges, or worker assignments.

Preceding Codex responses and quota/context metadata

These are preceding successful response IDs, not the rejected request IDs. The expanded proxy evidence below separately identifies whatever rejection-side IDs were actually captured.

Turn Preceding response ID Usage-record timestamp (UTC) Input / cached input / output
Attempt 1 resp_07e522e76220928e016a9e6d5fbc6487d284d5f8877c97c5d6 07:53:13.881Z 355260 / 355072 / 69
Attempt 2 resp_0e9e42af43cfc72e016a9e6e3b9a5c87d2abcbac4cb48c1763 07:56:53.466Z 361170 / 360448 / 96
Attempt 3 resp_0165f0285ef29911016a9e6ea0cc8c87d2b9f18e7877f0915c 07:58:38.537Z 362637 / 362496 / 37

The recorded context window is 828400. The last token-count metadata around the failures reports weekly-window (10080 minutes) usage of 95%, 96%, and 96%, plan_type: "pro", rate_limit_reached_type: null, and spend_control_reached: null. These are policy-coded failures near substantial quota consumption, not evidence of a quota-exhaustion response. The preceding successful token counts must not be treated as exact rejected-request size or billed failed-request usage.

Continuation-state prelude

At 07:51:13.138Z, an earlier turn (01a07ad9-88f9-7e70-9e6a-e6991aac1043) ended with a different error: codex_error_info: "other", wrapping invalid_request_error and the message:

OpenAI forward continuation state is unavailable or expired; start a new session instead of reusing this previous_response_id.

The same logical thread then has additional rollout segments, including the one with session-header timestamp 07:51:58.459Z that contains the three policy failures. This is a separate error class and useful recovery/context provenance, not a fourth cyber_policy event or proof that the continuation-state error caused the refusals.

Direct rejection-side correlation from the expanded proxy log

These are the upstream response IDs of the refused transactions themselves. The proxy captures them from response.created and retains them after response.failed, even though the failed requests report no usage. Each transaction directly records the matching diagnostics.codexThreadId and diagnostics.codexTurnId, so the join to the Codex failure is no longer inferred solely from timestamps/token counts.

Attempt Local proxy request ID Captured upstream response ID for the refused transaction
1 ocx-c43dc7febd754375354b064d3bf5d107 resp_00c706c2bd949183016a9e6d6b5de887d2b61389a9f47acbf1
2 ocx-c8e8d9d85999246af2861ae7b507e9db resp_06833f62a9c136f2016a9e6e46e19487d28d28784af0e8c572
3 ocx-83c8a0f1cba9b33da50ca0945e472bc5 resp_03305ded277571b5016a9e6eb9c5ec87d2a66a42761feefecb

For each transaction, previousResponseId and originalPreviousResponseId exactly equal the corresponding preceding Codex response ID in the earlier table. correlationConfidence is direct, with client/upstream field provenance. codexSessionId equals the logical thread ID. The captured clientRequestId also equals that thread ID, so it must not be treated as a unique upstream HTTP request ID. An upstreamRequestId is not present; the upstream response IDs above are the new diagnostic anchors.

Request lifecycle: connection accepted, response created, then upstream failure
Captured field (UTC, 2026-09-07) Attempt 1 Attempt 2 Attempt 3
Proxy received request 07:53:14.157Z 07:56:53.769Z 07:58:48.310Z
Upstream request sent (summary field) 07:53:14.420Z 07:56:53.978Z 07:58:48.869Z
Response created / first event 07:53:18.397Z 07:56:58.753Z 07:58:51.542Z
Upstream terminal observed 07:54:08.724Z 07:57:18.561Z 07:59:13.112Z
response.failed / last event 07:54:08.730Z 07:57:18.565Z 07:59:13.115Z
Downstream terminal sent 07:54:08.732Z 07:57:18.566Z 07:59:13.116Z
Proxy finalized 07:54:08.736Z 07:57:18.570Z 07:59:13.120Z
Codex task terminal 07:54:08.739Z 07:57:22.013Z 07:59:13.125Z
Total proxy duration 54590 ms 24812 ms 24818 ms
Derived upstream duration 54310.003 ms 24587.954 ms 24245.813 ms
Derived downstream delivery lag 7.659 ms 5.031 ms 4.204 ms

The fine-grained timestamps describe separate capture points; event-array send timestamps can differ slightly from the summary's send timestamp. Elapsed values are recorded derivations, not substituted wall-clock differences. The second task terminal follows its proxy failure by several seconds, overlapping the persisted S7 steering message; the direct turn-ID match establishes correlation independently of that delay.

All three record websocketHandshakeStatus: 101 and upstreamRequestAccepted: true, then errorOrigin: "upstream", terminalSource: "upstream", upstreamErrorCode: "cyber_policy", errorEnvelopeSchema: "response.error", and lastEventType: "response.failed". terminalEventType is separately recorded as error. The legacy status: 400 / terminalMappedStatus: 400 is thus a terminal mapping, not a failed WebSocket handshake.

The lifecycle includes response.output_item.added before the failure, and outputItemCountsByType reports one function_call in each transaction. duplicateTerminalSuppressed: true means duplicate terminal handling was suppressed; it is not evidence of extra rejected requests. Each failed transaction records one attempt and one send, with no recovery kinds. Detailed send, wire, connection, and event metadata is preserved in the evidence package.

Retained-context replay and request shape

The proxy records continuationMode: "local_replay", resumeMode: "local_replay", stateRestoreSource: "previous_response_replay", stateRestored: true, previousResponseUsed: true, and contextTransformationKinds: ["previous_response_replay"] on all three refusals.

Shape field Attempt 1 Attempt 2 Attempt 3
Inbound request bytes 2783 2874 2447
Inbound input items / tool results 1 / 1 1 / 1 1 / 1
Replayed items 2261 2286 2301
Reconstructed input items 2262 2287 2302
Forwarded request bytes 2418810 2455497 2468808
Inbound tool-result bytes 0 0 46
Connection age (ms) 49137.174 107199.549 72738.623
Connection generation 2991 3046 3088
Request sequence on connection 4 7 5

Each transaction therefore carries one new tool-result item while the proxy reconstructs thousands of retained items into a roughly 2.4 MB forwarded request. These are byte and item counts, not token counts. The inbound shape's zero tool definitions/messages/attachments does not mean the reconstructed upstream request lacked the retained conversation or tools. The first two toolResultBytes: 0 values are the logger's measured values, not independent proof that no tool result content existed.

connectionReused is true in each record; parallelToolCalls false, streamingRequested true, and storeRequested false. Different connection generations show these were not all the same live connection. No complete raw upstream request/response bodies are published. The user-authorized prompt supplement separately supplies the available visible prompt and tool content. The recorded replay behavior is particularly useful to investigate alongside the preceding continuation-state error, but this report does not establish that reconstruction, context size, or connection reuse caused the policy decision.

Routing, effective effort, tier, runtime, and access metadata

The records identify a native OpenAI route and openai-responses adapter. Requested/resolved/response model is gpt-6-astra. A useful distinction is now visible:

  • Client callerEffort: medium.
  • Local configuredEffort: high, source local_codex_root_config.
  • Actual emitted wire field reasoning.effort: "medium", preserved in the request, attempt, and physical-send records; effectiveEffort is medium.
  • Upstream response responseEffort: medium.
  • Shared captured request-settings revision: settings_4f45e15cb9a6f882 (a derived local identifier).

The local high default must not be misreported as the effective effort for these medium turns. The original per-attempt wire fields and tier outcomes are included in the package. Configured service tier is default; response tier is auto; tier confirmation remains unknown. No backend Cyber entitlement follows from those fields.

Runtime facts are now captured in each incident transaction: OpenCodex 2.45.0, Bun 1.4.0, Linux, x64, diagnostic schema/capture version 1. authMode is forward; account selection source is explicit_selector. Account-specific identifiers are redacted or consistently pseudonymized. upstreamHostname: "chatgpt" is the captured classification, not a verified fully qualified hostname. method: "POST" and upstreamContentType: "text/event-stream" are retained adapter metadata; the independently captured actual transport fields and handshake identify WebSocket.

Capture completeness and unavailable fields

All three diagnostic records have captureTruncated: true, despite droppedDiagnosticEventCount: 0. The exported availability map marks forwardedModel as truncated at the transport boundary and its own nested fieldAvailability entry as redacted, source persistence. The underlying ledger entry inspected locally marked that availability representation as truncated before export; the published export's redacted marker is preserved as written. Thus the expanded schema did not yield every possible populated field in these particular records, and zero dropped events is not proof of an untruncated diagnostic record.

errorType and the diagnostic errorMessage are marked redacted; the ordinary sanitized terminal error and Codex event still preserve the refusal wording. persistedAt / recordPersisted are marked not observed even though these records were retrieved from the ledger—those markers are not evidence that the retrieved rows failed to persist.

The captured availability data explicitly leaves policy-event ID, subscription plan, entitlement source, Cyber access status/program, model access status, policy-rule ID, and billed-usage source unknown upstream. Several client hierarchy and proxy build/catalog fields are unsupported or not observed. No specific policy stage, rule, trace ID, or HTTP request ID is claimed without a captured value. Failed usage is unreported / usageMissingReason: "not_reported", and usagePartial: false; do not interpret this as zero billed usage. The detailed availability maps and export gap list are included for OpenAI to assess the limits of the evidence.

What steps can reproduce the bug?

This is the exact observed continuation sequence in a long-running task, not a deterministic minimal reproduction from an empty task. No additional refusal was deliberately triggered while collecting this report.

  1. Resume the existing authorized maintenance campaign on Astra medium. The visible request in attempt 1 was:
    Why is there no work running YET AGAIN??
    
  2. After the first policy termination, continue with:
    Please try again. Triage work triggered refusals yet again.
    
    During that turn, the user also instructed:
    Continue as you were so I can reproduce the problem and report properly to OpenAI. Nothing changes.
    
    The user subsequently added:
    Also, expand the set to S7 now.
    
    The S7 message was persisted at 07:57:22.006Z, immediately before the second turn's terminal event; its recorded position must not be taken as proof of causal triggering.
  3. Continue with:
    Try again
    
    The root records the S7 request, waits for workers, and the third policy failure occurs.

The task API returned no item entries for these three failed turns in the inspected response, but the local rollout contains the visible requests, commentary, tool activity, usage records, and terminal errors summarized here. No missing content was invented from that empty API item list. A later continuation, turn 01a07ae2-1606-7193-8e46-e297fe630bcb, ran from 08:00:32.300Z to 08:02:36.308Z and completed without a recorded terminal error. The final API readback showed the task idle. This later non-error completion does not erase the three failures and is not evidence of a permanent fix or full campaign completion.

What is the expected behavior?

Authorized maintenance and PR-delivery coordination should proceed without being incorrectly classified as prohibited cybersecurity activity. Apply the actual model/account Cyber entitlement correctly, preserve completed work, and expose stable non-sensitive diagnostic IDs for policy rejections so support can inspect the exact decision. Existing Cyber enrollment should be reflected in actionable guidance.

Additional information

The environment uses a custom community Linux Desktop package with authenticated-proxy and shared-app-server integrations. Its upstream package SHA-256 is 62580188d87c3d3a9369dab7c73b42a8a32518d4df8a2d5bae6466ddeac5c05e. The core version and model facts above are recorded by the incident itself. Local approval/sandbox settings (never, danger-full-access) concern tool/filesystem execution, not backend Cyber access.

The new transaction diagnostics are intended to preserve observed protocol facts, including explicit unavailability. Having a schema field does not mean OpenAI exposed a value for this request. The report does not infer an entitlement, policy rule, trigger stage, or billing result from missing data.

For backend investigation, please prioritize the three exact refused upstream response IDs and their directly captured Codex turn IDs. Compare the reconstructed conversation and previous_response_replay behavior with the original continuation requests; verify the actual Cyber entitlement and classification boundary; distinguish the successfully accepted WebSocket connection from the later response.failed; and determine whether the policy decisions concern input, emitted output, or another monitored boundary. The observable local high default versus medium wire/response effort and the capture-truncation markers should also be accounted for. These are investigation questions, not claims of root cause.

The support bundle selects all three exact request IDs and retains each selected record. It reports exportCompleteness: "partial", with two explicit gap entries: log_coverage (omittedRecordCount: 0) and projection_omission for routeDecision.candidates (omittedRecordCount: 3). Its coverage bounds encompass the selected time window, but the log-coverage marker is preserved rather than dismissed. The export's partial status is separate from each record's capture truncation. The native exporter pseudonymizes client/upstream correlation IDs; an explicitly labeled exactSafeCorrelation supplement restores only the exact request, Codex turn, and upstream/previous response IDs copied from those same persisted rows, so OpenAI can find the incidents. Account identity remains redacted/pseudonymized.

Sanitized diagnostic package, including the full expanded transaction export and exact response-ID supplement includes all three selected transactions, lifecycle events, attempt/send records, request-shape counters, runtime and access metadata, availability maps, export gaps, and selected Codex events. The package README records SHA-256 checksums. The original native exporter output was retained with only the explicitly labeled exact-safe-ID extension; no upstream IDs were invented.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the expanded diagnostic package and the linked related issues, using the three upstream response IDs and matching turn IDs as the correlation anchors. The payload names no Codex source file, failing test, or implementation entry point; the work is complete only when a reproducible cause and an agreed corrective change for these policy terminations are identified.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.