openai / openai/codex

Astra high cyber_policy during defensive SQLite snapshot repair after successful tool use

Open
#43,514 1 comment 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

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

The incident rollout records Codex core/CLI 0.153.4, originator Codex Desktop. The Desktop application's separate About/build version was not established from the incident records. OpenCodex transaction diagnostics record 2.45.0, running Bun 1.4.0, Linux x64. Current CLI observations corroborate the proxy version but do not substitute for incident metadata.

What subscription do you have?

Subscription plan and entitlement source were not captured. The user reports being verified in the Daybreak program and having access to Daybreak Blue for defensive work. This is user-reported access, not a verified entitlement result: the proxy export marks cyberAccessStatus, modelAccessStatus, subscriptionPlan, and entitlementSource unavailable/unknown.

What platform is your computer?

Linux x64 in the incident proxy record. Current uname -mprs: Linux 7.1.10-200.fc44.x86_64 x86_64 unknown (collection-time observation).

What issue are you seeing?

An apparent false-positive cyber_policy refusal interrupted an authorized defensive patch and regression-test workflow after successful tool use and a partial fix. The task was correcting a reviewed SQLite snapshot-integrity flaw in donadiosolutions/lcm PR #1192, specifically the raw-to-normalized source-binding review. The requested result was to reject substituted source bytes, preserve original databases, and satisfy the repository's strict tests and coverage. No live third-party target was involved in the captured tests.

Report identity / actual failed worker: 01a07c96-b991-7041-b77d-1001ff654b35 (codex://threads/01a07c96-b991-7041-b77d-1001ff654b35). The task API returns a null title; the exact thread/turn identifiers below identify the failed subagent. Immediate parent: 01a07bb6-a090-7e91-ac13-218f7198f14e. Root task Implement Epic #92: 01a07a24-dbc7-73a3-81ec-022fe4cf7d71. The root/session identity is not the failed child identity.

Recorded refusal: one distinct failed turn
Field Captured value
Failed turn 01a07c96-b9fc-74e2-a5f6-5eb506d339f3
Terminal timestamp 2026-09-07 16:03:42.355 UTC / 13:03:42.355 America/Sao_Paulo
Turn duration 374,410 ms; start second 1788796647, completion second 1788797022
Model / effort gpt-6-astra, high in Codex turn settings, forwarded wire, and returned response
Terminal code task_complete.error.codex_error_info = cyber_policy
Final answer No completed final assistant message; visible commentary/tool work occurred beforehand

Full terminal message:

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

Direct OpenCodex/OpenAI correlation
Role Local request Actual upstream response
Refused response ocx-3c44c4c8c3a685f8c2b22419a4532ed0 resp_08b0ccfcf7e1bc7f016a9ee020ff2487d2953250a4c92e0646
Immediately preceding successful response ocx-23a19005c5c447128594a4b9dae7df15 resp_0da761dad571ea41016a9ee00e449c87d289aec2ec341afe62

The failed request's previousResponseId and originalPreviousResponseId both equal the preceding success above. Its local transaction is ocx-txn-735992ff-b7c6-4e48-92ef-f164eb36671d. This is a direct join through captured codexThreadId and codexTurnId, not time proximity or a shared conversation hash. No OpenAI HTTP request ID / policy-event ID / trace ID was captured; local ocx-* IDs are not substitutes. The last Codex token-usage response ID belongs to the preceding success, not the refusal.

Routing and transaction facts
  • The failing transaction began at 16:02:39.864 UTC (epoch milliseconds 1788796959864); total request duration 62,497 ms. Codex recorded the failed turn at 16:03:42.355 UTC.
  • One attempt, one physical send, no reconnect recorded. The upstream WebSocket handshake succeeded with 101; upstream later produced response.failed / cyber_policy, mapped locally to terminal 400. This was not an HTTP-handshake 400.
  • requestedModel, resolvedModel, forwardedModel, and response model all identify gpt-6-astra. Caller and effective effort are high; local configured effort is medium from local_codex_root_config, but reasoning.effort on the wire and response effort are high.
  • authMode=forward, account selection source main. Configured tier default; response tier auto; fast mode not requested and tier confirmation unknown. No account identifier or credential is published.
  • continuationMode=local_replay, stateRestoreSource=previous_response_replay, stateRestored=true, previousResponseRewriteApplied=true.
  • One incoming tool-result item: 5,858 request bytes, 2,015 tool-result bytes. The proxy reconstructed 49 input items by replaying 48, forwarding 436,050 bytes, 14 tool calls, 14 tool results, 4 tool definitions, and 199,978 tool-result bytes. Metadata records 11 encrypted items and 8 reasoning items; their contents are intentionally excluded.
  • Response creation was captured at 16:02:42.071 UTC. The proxy records output delivery before failure and output item types reasoning/custom-tool-call; no hidden reasoning text is included. The last visible completed tool boundary was 16:02:39.610 UTC. The adjacency is not evidence that this tool or its wording caused classification.
  • Failed-response usage is unreported, with missing reason not_reported. This is not zero usage or zero billing. The previous successful response reported 92,878 input / 396 output / 93,274 total tokens, including 92,288 cached input. Turn totals are cumulative across calls, not the refused request's usage.
Visible workflow context

The source-owned brief explicitly asked for deterministic main/WAL pathname-swap regressions, then a minimal descriptor/byte-digest binding fix after the owner's gate release. It required preserving original source bytes/modes/WAL, using isolated tests, and forbade live-database/global installation/daemon/GitHub changes by the worker. The attached workflow-context.md preserves the brief with private paths normalized. The initial delegation envelope is not claimed to be available plaintext; the brief was visibly read through a tool.

The worker created local alternate SQLite content and used the existing file-operation injection seam to demonstrate a same-UID ABA substitution. This context is retained rather than removing the adversarial test details to make the incident appear less security-related. It was a local regression test for a reported integrity flaw, not deployment against another system.

Last visible commentary, copied from the rollout at 16:02:28.618 UTC:

Both regressions reproduced the defect: capture sealed "attacker" from an alternate main file and, independently, an alternate WAL. The owner has now released the production gate after the previous candidate’s complete CI passed. The minimal fix binds both copy stages to the authenticated witness and reuses the existing bounded copy/hash routine.

The next completed visible tool result showed 88 tests passed, but coverage still below the required 100%: statements 769/773 (99.48%), branches 529/533 (99.24%), functions 137/137 (100%), lines 663/664 (99.84%). The command's exit 1 was from coverage thresholds, not the later cyber_policy terminal. The model then failed during its next upstream request.

What steps can reproduce the bug?

This report describes the recorded sequence, not a newly reproduced model-policy failure. No request was resent to provoke another refusal.

  1. In Codex Desktop, use the recorded Astra/high route to implement the source-owned defensive task in workflow-context.md, for LCM PR #1192 at published commit a0bc6845617974824b9dd045320305b1a70039df.
  2. The task reads the reviewed finding and instructions, creates isolated main/WAL substitution regression tests, records their failures, and receives permission to implement the minimal source-authentication fix.
  3. It applies a partial patch, runs the snapshot suite with coverage, and gets 88 passing tests with remaining coverage gaps.
  4. The next directly matched request, using the previous-response chain above through OpenCodex local replay, is accepted over WebSocket and later terminates with cyber_policy.

The exact selected visible exchanges and source-owned brief are in the evidence packet. They are transcript history, not a reconstruction of the complete failed wire payload. The captured model context window is 828,400; cumulative turn token counters in codex-evidence.json span repeated calls and should not be interpreted as current context occupancy.

What is the expected behavior?

Please investigate whether this is a policy false positive for an authorized defensive integrity repair and regression-test workflow. If a different program/model entitlement is required, the error and model-selection behavior should explain the supported recovery path and apply the account's actual eligibility consistently.

The user subsequently stated that they are verified for Daybreak and requested Daybreak Blue at high effort. The captured error directs the user to Trusted Access for Cyber; it does not explicitly name Daybreak. Please verify the account/program routing using internal support correlation rather than treating either the user claim or absent local entitlement fields as proof of the authorization decision. No model switch was attempted as part of this evidence collection.

Additional information

Evidence packet: https://gist.github.com/bcdonadio/f757882a3c2805130ebfd36c87121d2c. evidence-guide.md documents selection, redactions, source coverage and SHA-256 hashes. The native proxy export contains all 17 directly matched requests: 14 completed, two transport-cancelled/unreported records with no recorded terminal status, and one failed in this worker turn. Native pseudonyms are accompanied by actual safe request/response IDs in exact-correlation.json so support can locate the refusal.

Important limitations:

  • Native export reports partial completeness and captureTruncated=true; droppedDiagnosticEventCount=0 does not mean full payload capture. The exporter omits routeDecision.candidates for all17 records and marks access/plan/policy identifiers unavailable. Source diagnostic field-availability truncation remains visible.
  • The collector matched one refusal across the worker's111-line rollout and17 directly matched proxy records. It recorded90,079 characters of automatic string truncation across its starting extract; the report only publishes selected reviewed visible records. The full native metadata export is separate.
  • No matching line was found in the existing proxy service.log for the exact failed worker/request/response identifiers. The canonical usage ledger is the positive proxy evidence source.
  • System/developer instructions, private reasoning, encrypted payloads, credentials, account identifiers and unrelated conversations are excluded. Private paths in visible context use placeholders. No hidden reasoning or replay store was decrypted/exported.
  • The task API also confirms the same failed thread/turn and error. The displayed task title is null, so this report uses exact thread/turn IDs rather than inventing a title.
  • The worker remains parked with two modified files and incomplete coverage/review/CI. Its parent PR is open; no merge or successful completion of the blocked repair is claimed. Reporting did not restart services, change diagnostics, execute historical commands, retry the refusal, or resume the repair.

Backend questions: Why was resp_08b0ccfcf7e1bc7f016a9ee020ff2487d2953250a4c92e0646 classified as cyber risk after this sequence? Did program/model entitlement or restored-context handling affect classification? Was any concrete payload boundary lost in the local-replay route? Can the product expose a clear supported recovery path without losing the partial patch and its validation evidence?

Evidence guide SHA-256: 1f7d29066de8eedc5eab5cbfc16711b0ae8740c8b37a59fde50fa5e2017ffea9.

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 evidence packet, evidence-guide.md, and exact-correlation.json; use the failed thread, turn, request, and response identifiers to trace the recorded refusal. Compare the documented routing and entitlement facts with the expected recovery behavior. Done means determining whether this was a false positive or documenting the supported authorization and model-selection path.

Written by the indexing model from the issue text.

Assessment

Tech stack
bun, rust, sqlite
Domain
authorization, security
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.