D3 network-egress purity — lexical binding enforcement - #64
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6dd6a36411
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ba636b23ae
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c71f3266c7
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 86e4b9fffe
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d9c0dc665c
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f2b4387cbc
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6bf1d64764
ℹ️ 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".
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ag7ZrUfkkKnbh6YxLU1fLQ
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8ca0a1fdc5
ℹ️ 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".
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ag7ZrUfkkKnbh6YxLU1fLQ
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6bff9a4081
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 17d4f71af4
ℹ️ 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".
|
@codex security review Perform a deep adversarial review of PR #64 at EXACT CURRENT HEAD only. Do not limit review to the newest commit or changed hunk. Audit the complete finite D3 purity mechanism in
For each candidate finding:
IMPORTANT BOUNDARY: D3 is a bounded static source policy, NOT a runtime sandbox. Do NOT demand:
Do not report bypasses that require crossing that explicitly unsupported boundary. Focus on finding ALL remaining defects inside the currently claimed finite grammar |
|
Codex Review: Didn't find any major issues. Bravo. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QEL8ik1ZCmm33Ej982kReA
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c698af0af2
ℹ️ 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".
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0138GjJx3nbN2K7NhuMU2poe
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a6781d8a28
ℹ️ 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".
|
@coderabbitai review |
|
|
@codex review |
|
@coderabbitai review |
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a6781d8a28
ℹ️ 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".
| // rejects a shadowed `const g = globalThis`, and the escaped alias is never traced. | ||
| if ( | ||
| (ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) && | ||
| isGlobalReceiver(node) && |
There was a problem hiding this comment.
Fold static keys before forwarding global authority
Fresh evidence beyond the earlier direct constructed-hop fix is that this new forwarding branch still relies on the literal-only isGlobalReceiver: const g = globalThis['global' + 'This']; g.fetch('https://example.com') makes NET, RC, and HA all return false while g is the real global object and the call performs outbound egress. The computed key is considered statically harmless by the other checks, and the later local receiver g is not tracked, so apply the same bounded static-key resolution used by NET when recognizing a forwarded self-reference.
Useful? React with 👍 / 👎.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0138GjJx3nbN2K7NhuMU2poe
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4835b19798
ℹ️ 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".
| if (isCreateServerCall(node)) { | ||
| for (const arg of (node as ts.CallExpression).arguments) { | ||
| const handler = binderUnwrap(arg); | ||
| if (ts.isArrowFunction(handler) || ts.isFunctionExpression(handler)) { |
There was a problem hiding this comment.
Track sockets passed to custom IncomingMessage constructors
When createServer receives an IncomingMessage class in its options, Node constructs that class with the live connection socket, but this pass records only parameters of function arguments passed directly to createServer. Consequently, http.createServer({ IncomingMessage: Capture } as any, ...) can use Capture's constructor parameter to call destroy() and then connect() outbound without mentioning any banned socket property, and all three current purity detectors accept the source. Treat the custom request constructor as another socket-delivery entry point.
Useful? React with 👍 / 👎.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fj88FKnrXXioWzdngyDcSG
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e40e8c9d81
ℹ️ 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".
| if (isCreateServerCall(node)) { | ||
| for (const arg of (node as ts.CallExpression).arguments) { | ||
| const handler = binderUnwrap(arg); | ||
| if (ts.isArrowFunction(handler) || ts.isFunctionExpression(handler)) { |
There was a problem hiding this comment.
Inspect named createServer request handlers
When the request listener is passed by reference, this collector ignores its parameters because it only recognizes inline arrow/function expressions. For example, function handler(req) { const key = (req.url ?? '').slice(1); const s = req[key]; s.destroy(); setTimeout(() => s.connect(80, 'example.com'), 50) } http.createServer(handler) passes all three purity detectors; a request for /socket then recovers the live inbound socket and reconnects it outbound. Resolve binder-visible function declarations used as listeners, or reject non-inline listeners so Rule A2 cannot be bypassed.
Useful? React with 👍 / 👎.
| const optionsObject = binderUnwrap(arg); | ||
| if (!ts.isObjectLiteralExpression(optionsObject)) continue; |
There was a problem hiding this comment.
Reject aliased createServer constructor options
Fresh evidence beyond the prior direct-object constructor comment is that storing the options first still bypasses the new rule: const options = { IncomingMessage: Capture }; http.createServer(options as any, ...) passes NET, RC, and HA because the argument is an identifier rather than an object literal, while Node still invokes Capture with the live socket and its constructor can destroy and reconnect it outbound. Trace binder-resolved constant option objects, or fail closed on non-literal createServer options.
Useful? React with 👍 / 👎.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CdLcbXZMib9vDjZ7Lgr8gy
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 430f11d370
ℹ️ 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".
| const optionsObject = resolveCreateServerArgument(arg); | ||
| if (!ts.isObjectLiteralExpression(optionsObject)) continue; | ||
| for (const prop of optionsObject.properties) { | ||
| if (!ts.isPropertyAssignment(prop) && !ts.isShorthandPropertyAssignment(prop)) continue; |
There was a problem hiding this comment.
Inspect constructor-option accessors
Fresh evidence beyond the earlier direct/aliased constructor-option reports is that this property-kind filter skips getters: http.createServer({ get IncomingMessage() { return Capture; } } as any, () => {}) passes all three purity detectors. Node reads the getter and constructs the returned class with the live connection socket, so Capture can destroy and reconnect that socket outbound; inspect accessor keys such as IncomingMessage and ServerResponse alongside ordinary property assignments.
Useful? React with 👍 / 👎.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0168Ff8rrLX6K8yWx8WhwrUY
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 345b9e34a2
ℹ️ 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".
| // resolve to an ObjectLiteralExpression and stays outside the proof (frozen positive model). | ||
| const optionsObject = resolveCreateServerArgument(arg); | ||
| if (!ts.isObjectLiteralExpression(optionsObject)) continue; | ||
| for (const prop of optionsObject.properties) { |
There was a problem hiding this comment.
Reject inherited createServer constructor options
Fresh evidence after the direct, aliased, and getter option fixes is that http.createServer({ __proto__: { IncomingMessage: Capture } } as any, ...) still passes usesOutboundNetwork: this loop examines only the top-level object properties, while Node reads the inherited options.IncomingMessage and constructs Capture with the live connection socket. The constructor can then destroy and reconnect that socket outbound, so reject prototype-bearing option shapes or inspect statically supplied prototypes for the reserved constructor keys.
Useful? React with 👍 / 👎.
| for (const arg of (node as ts.CallExpression).arguments) { | ||
| const handler = resolveCreateServerArgument(arg); | ||
| if (ts.isArrowFunction(handler) || ts.isFunctionExpression(handler) || ts.isFunctionDeclaration(handler)) { | ||
| for (const param of handler.parameters) { |
There was a problem hiding this comment.
Track request objects accessed through arguments
When a non-arrow request listener has no declared parameters and reads arguments[0], this collector records no request/response symbol because it only iterates handler.parameters. For example, createServer(function () { const req = arguments[0]; const s = req[(req.url ?? '').slice(1)]; ... }) passes usesOutboundNetwork, yet a request for /socket recovers the live socket and can reconnect it outbound. Treat the listener's arguments binding as another request-delivery source or reject this access form.
Useful? React with 👍 / 👎.
Stacked validation PR — OPEN / READY / unmerged. Merge is out of scope for this reconciliation gate.
Stack
cockpit/d3-readonly-dashboard-host5ae2b786ad6dc4653286d4c2b50e1fd705daa974(untouched)repair/d3-network-egress-puritya6781d8a2859cce8282a61724770fedf3967972dtests/cockpit-host/purity.test.tsScope
Bounded static source-policy enforcement for the D3 read-only cockpit host boundary (
src/cockpit-host/): a single-parse, finite AST guard that decides importless network globals (fetch/WebSocket), thenode:httppositive model (onlycreateServerallowed), runtime code-generation (RC), and hidden-builtin acquisition (HA) by lexical binding identity, not identifier text. This is a development-time source policy, not a runtime sandbox.History (condensed)
The detector began by replacing name-text decisions with a bounded lexical environment/scope-stack model (fixing shadowing false-positives NET-S1 and the missed-egress false-negative NET-S2), then closed a long series of laundering variants surfaced by review: node:http client/
Agent/ClientRequestmembers, dynamic-import bindings, nested/assignment destructuring, computed & template-substitution socket-registrar keys, statically-folded global self-reference hops (globalThis.globalThis,globalThis['global'+'This']), reflective reads (Reflect.get), and — most recently — forwarding of a recognized free-global self-reference value (const g = [globalThis.globalThis][0]; g.fetch(…)), closed by the RC v4 global-object self-reference forwarding closure in the head commita6781d8("fix(cockpit): reject forwarded global authority").Latest exact-head evidence
33443908648), head_shaa6781d8…, jobverify→ SUCCESS.a6781d8(Manual request).tests/cockpit-host/purity.test.ts: SHA25625d1115c774555be5d546ba2a1407f0333cdabde5ef756968438e5f7deae063e, 452778 bytes.git diff --checkall PASS.Review-thread reconciliation (exact HEAD
a6781d8)All 45 review threads resolved (0 unresolved). Of the 17 previously-unresolved threads, 14 are FIXED — each witness was re-run through the current detectors and is now rejected (
usesOutboundNetwork/usesRuntimeCodeGeneration= true), covered by the committed regression suite. BLOCKING_CURRENT_IN_BOUNDARY_COUNT = 0 — no current, in-boundary blocking egress defect remains.Explicit carried obligations (non-blocking, deferred)
globalThis.valueOf().fetch(…): CURRENT / P2, but outside the frozen finite boundary. Sound closure needs CallExpression / intrinsic method-return semantic modeling (an open-ended family, defeated by monkey-patching), which the adopted bounded source policy excludes. Deferred; the.call/.applyidentity variants are already closed by the forwarding rule.import type { request }+typeof requestis over-rejected: CURRENT / P3, a false-positive precision item (not an egress path), used by no production host source. Deferred.typeof EventSource === 'undefined'unless--experimental-eventsource, which the cockpit-host/CI launch paths do not enable). The finite network-global surface tracks only runtime-present importless globals; adding it on the@types/nodedeclaration alone would exceed the actual runtime. Flag-conditional / deferred.All in-boundary blocking findings have been repaired; remaining items are the explicitly-scoped carried obligations above. This PR remains unmerged.