Skip to content

fix(security): detach replay checkpoint appends from shared prototypes - #4402

Merged
kojiwakayama merged 4 commits into
mainfrom
security/finding-163-checkpoint-serialization-isolation
Sep 3, 2026
Merged

fix(security): detach replay checkpoint appends from shared prototypes#4402
kojiwakayama merged 4 commits into
mainfrom
security/finding-163-checkpoint-serialization-isolation

Conversation

@kojiwakayama

@kojiwakayama kojiwakayama commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

The direct-stream provider replay checkpoint persister is constructed after ensureProjectDiscovery() has dynamically imported tenant project code into the shared realm (src/server/handlers/request/agent-stream.handler.ts:1137 discovery, :1185 persister creation). The persister captured JSON.stringify at module load, but capturing the function does not neutralize the dynamic toJSON lookup the algorithm performs on every object and array it visits, nor the property reads it routes through accessors. The append body was assembled from ordinary object literals ({ events: [createProviderReplayCheckpointEvent(checkpoint)] }, and createProviderReplayCheckpointEvent returns a plain { type, ...checkpoint }), all inheriting from Object.prototype. Project code could therefore install Object.prototype.toJSON during discovery and have it invoked when a checkpoint is persisted: the hook receives the private checkpoint — including opaque Anthropic provider blocks and thinking signatures the parse layer deliberately treats as private — and can return a replacement object that becomes the JSON body POSTed to /runs/{runId}/events with the host's opaque Authorization: Bearer <runEventAppendToken>. That is a confused-deputy path for forging or corrupting private durable run events without ever learning the token, and it crosses exactly the host-vs-tenant credential boundary this file was written to defend.

Finding

  • Codex finding id: 3621532baba88191a4317ffda38102e7 (finding 163, "Prototype poisoning controls privileged checkpoint appends")
  • Severity: low
  • Introduced in: 8ca99ad3119d18011c4611949d4e2446ebbe954f ("fix(agent): persist direct-stream replay checkpoints", fix(agent): persist direct-stream replay checkpoints #4312)
  • Affected: src/internal-agents/provider-replay-checkpoint-persister.ts (append body serialization), reached from src/server/handlers/request/agent-stream.handler.ts with event shapes from src/agent/runtime/provider-replay.ts

Re-verified on origin/main (78ec40a9f): the persister was untouched since the introducing commit, no serialization hardening exists (git log -S toJSON finds none), and no open PR covers it.

Fix

Serialize the privileged append body from containers no tenant prototype can reach, rather than from ambient object literals:

  • Capture the structural intrinsics (Object.create, Object.setPrototypeOf, Object.getOwnPropertyDescriptor, Reflect.ownKeys, Array.isArray) alongside the credential-touching intrinsics already captured at module load.
  • Deep-copy the validated checkpoint event into null-prototype objects and null-prototype arrays before handing it to the captured JSON.stringify. With no prototype, there is no inherited toJSON to resolve and no inherited index accessor to fire; arrays are detached before entries are written.
  • Copy only own enumerable data properties with string keys, matching what JSON.stringify serializes. Accessors are read from the descriptor and skipped, so no getter reachable from the checkpoint runs during serialization.
  • Reproduce JSON.stringify's own omission semantics (undefined/function/symbol dropped in objects, null in arrays) so the bytes are unchanged for well-formed checkpoints, and fail closed on anything it could not represent.
  • Bound the copy with the existing MAX_PROVIDER_REPLAY_RAW_METADATA_DEPTH / MAX_PROVIDER_REPLAY_RAW_METADATA_NODES limits, so a malformed or cyclic checkpoint raises DURABLE_RUN_EVENT_PERSISTENCE_FAILED instead of recursing unbounded.

No behavior change for well-formed checkpoints: the emitted body is byte-identical.

Test evidence

Two regression tests added next to the existing boundary tests in src/internal-agents/provider-replay-checkpoint-persister.test.ts:

  • "never resolves an inherited toJSON hook while building the append body" — installs a toJSON hook on the prototype chain of the checkpoint's providerBlocks array, providerBlockPositions array, block wrapper and opaque block, then asserts the hook is never invoked, that the body is byte-identical to the un-poisoned append, and that the forged marker never reaches the wire. (Poisoning the object's own prototype chain exercises the same dynamic toJSON lookup as Object.prototype.toJSON while keeping the unit hermetic, which the repo's semantic unit-boundary gate requires.)
  • "never invokes a getter reachable from the checkpoint while serializing" — installs an enumerable getter on the opaque block and asserts it is never called and its value never appears in the body.

Both tests fail on the pre-fix serialization (verified by temporarily restoring the old JSON.stringify call: FAILED | 0 passed (4 steps) | 1 failed (2 steps)) and pass with the fix.

Commands run locally (Deno repo — no pnpm/biome/vitest here; used the equivalents from the lint-typecheck / format jobs in .github/workflows/cicd.yml):

  • deno fmt --check src/internal-agents/ — clean (19 files)
  • deno lint src/internal-agents/ — clean (19 files)
  • deno check src/internal-agents/provider-replay-checkpoint-persister.ts — clean
  • deno task test:file src/internal-agents/provider-replay-checkpoint-persister.test.tsok | 1 passed (6 steps) | 0 failed
  • deno task test:file over src/internal-agents/{ag-ui-sse,run-stream,control-plane-auth}.test.ts, src/agent/runtime/provider-replay{,-emission}.test.ts, src/server/handlers/request/agent-stream.handler.test.tsok | 8 passed (248 steps) | 0 failed
  • deno task lint:anti-slop — baseline ok; deno task lint:test-semantic-dispositions — ok; deno task lint:module-boundaries — ok; deno task lint:dependency-boundaries — ok; deno task lint:skipped-tests — ok; deno task lint:ban-test-only — none found

https://claude.ai/code/session_01QfWNMiUhvWMKWi6BGfVdY3

Summary by CodeRabbit

  • Bug Fixes
    • Improved reliability and security when persisting provider replay checkpoints.
    • Prevented application-defined object behavior from altering checkpoint data during storage.
    • Checkpoint metadata that cannot be safely serialized, or exceeds supported size limits, now fails with a clear persistence error instead of producing potentially corrupted data.
    • Preserved checkpoint content more accurately across nested objects, arrays, and supported JSON values.

The direct-stream checkpoint persister is created after
ensureProjectDiscovery() has loaded tenant project code into the shared
realm. It captured JSON.stringify up front, but capturing the function
does not neutralize the dynamic `toJSON` lookup it performs on every
object and array it visits, nor the property reads it routes through
accessors. The append body was built from ordinary object literals, so
project code could install Object.prototype.toJSON during discovery,
receive the private checkpoint (opaque Anthropic replay blocks and
thinking signatures), and return a replacement object that became the
JSON body sent to /runs/{runId}/events under the host's opaque
run-event append token — a confused-deputy path for forging or
corrupting private durable events without ever learning the token.

Rebuild the append body out of null-prototype objects and arrays before
serializing it, using intrinsics captured at module load: own
enumerable data properties only (accessors are never invoked), string
keys only, and bounded by the existing provider replay depth and node
limits so a malformed checkpoint fails closed instead of recursing.
JSON.stringify then has no tenant-reachable prototype to consult.

Claude-Session: https://claude.ai/code/session_01QfWNMiUhvWMKWi6BGfVdY3

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kojiwakayama has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 2, 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
📝 Code Review 🔄 Running since 2026-09-03T05:44:16.052510Z 8c0ecb5 New commits
🔒 Security Review Completed 2026-09-03T05:48:43.030954Z 8c0ecb5 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.

@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

Next included review available in 20 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Team

Run ID: 5252c5cc-8dd4-4cd6-9605-4ff792669f8c

📥 Commits

Reviewing files that changed from the base of the PR and between c979b63 and 8c0ecb5.

📒 Files selected for processing (3)
  • src/internal-agents/provider-replay-checkpoint-persister.test.ts
  • src/internal-agents/provider-replay-checkpoint-persister.ts
  • tests/integration/semantic-unit-boundary/src/internal-agents/provider-replay-checkpoint-persister-intrinsics.test.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Team

Run ID: 9b456393-7688-421a-a397-2543572c262e

📥 Commits

Reviewing files that changed from the base of the PR and between 78ec40a and c979b63.

📒 Files selected for processing (2)
  • src/internal-agents/provider-replay-checkpoint-persister.test.ts
  • src/internal-agents/provider-replay-checkpoint-persister.ts

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The checkpoint persister now detaches checkpoint data before JSON serialization. It protects against prototype and accessor hooks, enforces metadata limits, and adds extensive failure and serialization tests.

Changes

Checkpoint persistence hardening

Layer / File(s) Summary
Detached value serialization
src/internal-agents/provider-replay-checkpoint-persister.ts
The persister captures intrinsics, ignores inherited hooks and accessors, rebuilds values in null-prototype containers, and enforces depth and node limits.
Append body construction
src/internal-agents/provider-replay-checkpoint-persister.ts
The append handler serializes a detached checkpoint event before sending the request body.
Persistence behavior validation
src/internal-agents/provider-replay-checkpoint-persister.test.ts
Tests cover hostile object behavior, JSON fidelity, limits, cancellation, timeouts, and transport failures.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: 🔵 Low · up to c979b

The security hardening is mergeable, but primitive-heavy checkpoints can still pass persistence limits and fail when read back. This is a bounded compatibility risk that should remain tracked.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main security change: detaching replay checkpoint appends from shared prototypes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch security/finding-163-checkpoint-serialization-isolation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread src/internal-agents/provider-replay-checkpoint-persister.ts Outdated

Copy link
Copy Markdown
Contributor

Review: 83/100 — solid, well-targeted security fix; one off-by-one edge case and a test-coverage gap on the new fail-closed path

Summary: This correctly neutralizes the confused-deputy path (poisoned Object.prototype.toJSON/accessors reachable after tenant discovery forging the checkpoint append body) by rebuilding the append body out of null-prototype containers using descriptor-based reads, all sourced from intrinsics captured at module load — consistent with the file's existing pattern. Two regression tests exercise the actual exploit shape (prototype toJSON hook, reachable getter) and both are shown to fail pre-fix.

Strengths

  • Root-causes the bug correctly: capturing JSON.stringify alone doesn't stop its dynamic toJSON lookup or accessor reads — the fix addresses that directly rather than patching symptoms.
  • Uses getOwnPropertyDescriptor throughout instead of property access, so no getter on the checkpoint's reachable object graph is ever invoked, even one defined as an own property (not just via prototype).
  • Faithfully reproduces JSON.stringify's omission semantics (undefined/function/symbol dropped from objects, null in arrays, string-keys-only, insertion order via Reflect.ownKeys) so well-formed checkpoints stay byte-identical.
  • Regression tests directly target the described attack (prototype toJSON hook and a reachable getter on the opaque block), assert the forged marker/leak never reaches the wire body, and are demonstrated to fail against the pre-fix code.

Concerns

  • Off-by-one depth bound vs. the upstream validator it claims to reuse. detachJsonValue rejects a container once depth >= MAX_PROVIDER_REPLAY_RAW_METADATA_DEPTH (64), but snapshotValue's beginValue (the existing bound this PR says it reuses, in json-snapshot.ts) only rejects once depth > maxDepth. That means a checkpoint with container nesting at exactly the boundary the upstream validator accepts (depth index 64) will now fail at persistence time with DURABLE_RUN_EVENT_PERSISTENCE_FAILED, contradicting the "byte-identical for well-formed checkpoints" claim for that edge case. Worth aligning to depth > MAX_...DEPTH (or documenting the intentional narrowing) so a checkpoint that was valid upstream doesn't fail downstream.
  • The new fail-closed path itself isn't tested. The PR description calls out that malformed/cyclic checkpoints now raise DURABLE_RUN_EVENT_PERSISTENCE_FAILED instead of recursing unbounded, bounded by the depth/node budget — but no test exercises that (e.g., a checkpoint exceeding MAX_PROVIDER_REPLAY_RAW_METADATA_DEPTH, or a bigint/other non-JSON-representable value). Given this is new failure-mode behavior on a privileged persistence path, it should have direct coverage, not just the two prototype-poisoning tests.
  • Node-budget semantics diverge from the "existing" limit it cites. budget.nodes here is decremented only for object/array containers, whereas MAX_PROVIDER_REPLAY_RAW_METADATA_NODES is defined and enforced elsewhere (json-snapshot.ts's beginValue) by counting every visited value, including leaves. Not exploitable in practice (checkpoints reaching this code have already passed the stricter upstream count), but the reuse is looser than it appears and worth a one-line comment noting the divergence so a future reader doesn't assume parity.

Actionable for the concerns above: change the depth guard to depth > MAX_PROVIDER_REPLAY_RAW_METADATA_DEPTH to match beginValue's semantics, and add a test asserting a checkpoint that exceeds the depth/node bound (or contains a bigint) fails closed with DURABLE_RUN_EVENT_PERSISTENCE_FAILED rather than throwing an unrelated error or hanging.

None of these undermine the core fix — the confused-deputy path is closed and the primary regression tests are good. The depth off-by-one is the only one I'd want addressed before merge; the rest are nice-to-haves.


Generated by Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0a68abee3b

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/internal-agents/provider-replay-checkpoint-persister.ts Outdated
Comment thread src/internal-agents/provider-replay-checkpoint-persister.ts Outdated
Comment thread src/internal-agents/provider-replay-checkpoint-persister.ts Outdated
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

📦 Client bundle boundary

Entrypoint Modules Source size Server leaks
src/index.client.ts 288 2271 KiB ✅ 0

A server module in a client graph aborts hydration in the browser. New leaks fail CI; known leaks are tracked in scripts/lint/client-bundle-baseline.json to burn down.

@codecov

codecov Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.26168% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...nal-agents/provider-replay-checkpoint-persister.ts 96.26% 1 Missing and 3 partials ⚠️

📢 Thoughts on this report? Let us know!

Review follow-ups on the replay checkpoint serializer:

- `Object.getOwnPropertyDescriptor` returns an ordinary object that
  inherits from `Object.prototype`, and a data descriptor owns neither
  `get` nor `set`. Reading those fields therefore resolved through the
  shared prototype, letting tenant code installed during discovery run an
  accessor with the descriptor as `this` — enough to observe the opaque
  provider block and rewrite `this.value` before it reached the append.
  Descriptor fields are now probed with a captured `hasOwnProperty`,
  matching the snapshot validator in json-snapshot.ts.
- `Reflect.ownKeys` hands back an ordinary array, so walking it with
  `for...of` resolved `Symbol.iterator` through `Array.prototype`. A
  tenant hook there could read the private field names and drop, reorder,
  or never finish yielding them. The reflected keys are now traversed by
  index through own data properties.
- The depth bound rejected containers at exactly
  MAX_PROVIDER_REPLAY_RAW_METADATA_DEPTH while the snapshot validator
  behind parseProviderReplayCheckpointEvent rejects only past it, so a
  checkpoint could load successfully and then fail its next append. Both
  layers now use root-at-zero `depth > maxDepth`.

Adds regression coverage for each (all three fail against the previous
code), plus tests for the append body's remaining failure paths: the
JSON.stringify omission parity, the non-serializable, depth and node
bounds, an already-cancelled run, the append timeout, and an opaque
transport failure.

Claude-Session: https://claude.ai/code/session_01QfWNMiUhvWMKWi6BGfVdY3

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kojiwakayama has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

@codex review

@gitar-bot

gitar-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown

Note

Automatic reviews are paused because your trial's included automatic processing has been used for this period. Upgrade now, or comment "Gitar review" to run a review anytime.
Learn more

Code Review ✅ Approved 1 resolved / 1 findings

Hardens checkpoint serialization to block prototype-poisoning attacks where tenant code could intercept private run events via Object.prototype.toJSON hooks installed during discovery. Deep-copies the checkpoint into null-prototype containers before stringification, reads only own enumerable data properties, and bounds the copy operation with the existing metadata depth/node limits. Resolves the depth bound mismatch with the parse-back layer. No behavior change for well-formed checkpoints; regression tests verify the hook is never invoked and the wire payload is byte-identical.

✅ 1 resolved
Edge Case: Persister depth bound is stricter than the parse-back layer

📄 src/internal-agents/provider-replay-checkpoint-persister.ts:96-98
detachJsonValue throws when depth >= MAX_PROVIDER_REPLAY_RAW_METADATA_DEPTH for a container (persister lines 96-98), so it rejects containers at depth 64. The snapshot layer used by parseProviderReplayCheckpointEvent on the whole event uses the looser depth > maxDepth and only throws at depth 65 (src/provider/runtime-loader/json-snapshot.ts:369, root at depth 0). Both walk the whole event from root depth 0, so a well-formed checkpoint with a container nested at exactly depth 64 will pass validation/parse-back but fail to persist with DURABLE_RUN_EVENT_PERSISTENCE_FAILED, contradicting the PR's byte-identical/no-behavior-change claim. Reachable only by extreme nesting (real provider blocks are shallow), hence minor. Align the check with the snapshot layer by using depth > MAX_PROVIDER_REPLAY_RAW_METADATA_DEPTH.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Important

Your trial ends in 6 days — upgrade now to keep code review, CI analysis, auto-apply, custom automations, and more.

Was this helpful? React with 👍 / 👎 | Gitar

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: c979b6390d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

`lint:test-semantic-dispositions` rejects a `src/**` unit test that
mutates shared-realm prototypes, and the two new regression cases install
accessors on `Object.prototype` and replace
`Array.prototype[Symbol.iterator]`. They move to the existing
tests/integration/semantic-unit-boundary intrinsics suite for this module
rather than growing the migration inventory.

Claude-Session: https://claude.ai/code/session_01QfWNMiUhvWMKWi6BGfVdY3

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kojiwakayama has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b4bd197787

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/internal-agents/provider-replay-checkpoint-persister.ts Outdated
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: b4bd197787

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Hoisting the append body out of the request's try block moved it outside
the failure sanitizer. Copying a checkpoint still runs exotic member code
— a Proxy trap reached through `Reflect.ownKeys` or
`getOwnPropertyDescriptor` — so a tenant-controlled throw escaped into
run error handling instead of surfacing as
DURABLE_RUN_EVENT_PERSISTENCE_FAILED, which is what happened before this
PR when `JSON.stringify` ran inline inside that block.

Serialization is now guarded: this module's own typed failures pass
through unchanged, everything else becomes the opaque persistence error.
The slug test the request catch already performed is factored into
`isPersistenceFailure` and shared by both sites. Regression test uses a
checkpoint carrying a Proxy whose `ownKeys` trap throws a secret-bearing
error and asserts neither the secret nor the append survives.

Claude-Session: https://claude.ai/code/session_01QfWNMiUhvWMKWi6BGfVdY3

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kojiwakayama has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: 8c0ecb5faf

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@sonarqubecloud

sonarqubecloud Bot commented Sep 3, 2026

Copy link
Copy Markdown

@kojiwakayama
kojiwakayama added this pull request to the merge queue Sep 3, 2026
Merged via the queue into main with commit ed88419 Sep 3, 2026
57 checks passed
@kojiwakayama
kojiwakayama deleted the security/finding-163-checkpoint-serialization-isolation branch September 3, 2026 08:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants