fix: proxy direct APNs HTTP2 sessions#74905
Conversation
|
Codex review: passed. Summary Reproducibility: yes. source-reproducible: current main Next step before merge Security Review detailsBest possible solution: Land the exact reviewed head after required checks and automerge gates pass, while keeping broader raw socket classification in #77126. Do we have a high-confidence way to reproduce the issue? Yes, source-reproducible: current main Is this the best way to solve the issue? Yes. The reviewed head is a narrow maintainable fix for APNs HTTP/2: keep the existing send API, isolate raw HTTP/2 in one allowlisted wrapper, and leave broader raw socket policy to #77126. What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 5efbb3078a15. |
1a92c5c to
aadd7b9
Compare
aadd7b9 to
65b9950
Compare
65b9950 to
6bce235
Compare
There was a problem hiding this comment.
Pull request overview
Routes direct APNs HTTP/2 delivery through OpenClaw’s managed proxy lifecycle by replacing the low-level APNs http2.connect() seam with a proxy-aware connection helper, and adds guardrails/tests to prevent future raw HTTP/2 usage that would bypass managed egress controls.
Changes:
- Introduce
connectApnsHttp2Session()to connect APNs HTTP/2 either directly or via a managed-proxy CONNECT tunnel (with APNs authority allowlisting). - Track active managed proxy URL/handle lifecycles centrally and enforce same-URL overlap semantics.
- Add regression tests plus lint/OpenGrep rules to prevent new production raw
node:http2imports /http2.connect()usage.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/infra/push-apns.ts | Switches APNs direct send path to use the new proxy-aware HTTP/2 session connector and shared cancel code constant. |
| src/infra/push-apns.test.ts | Adds an end-to-end test that verifies direct APNs HTTP/2 traffic is routed through the active managed proxy using CONNECT. |
| src/infra/push-apns-http2.ts | Adds the APNs HTTP/2 connection wrapper with authority allowlisting and managed-proxy integration. |
| src/infra/push-apns-http2.test.ts | Unit tests for direct-vs-proxied session establishment, env proxy ignore behavior, and authority rejection. |
| src/infra/net/proxy/proxy-lifecycle.ts | Integrates managed-proxy lifecycle with shared “active proxy state” tracking and overlap URL enforcement. |
| src/infra/net/proxy/proxy-lifecycle.test.ts | Adds coverage for exposed active proxy URL, same-URL overlapping handles, and rejection of conflicting URL overlap. |
| src/infra/net/proxy/active-proxy-state.ts | New module to track the single active managed proxy URL with handle-count lifecycle safety. |
| src/infra/net/http-connect-tunnel.ts | New CONNECT + TLS tunnel helper used to route APNs sessions through the managed proxy. |
| src/infra/net/http-connect-tunnel.test.ts | Unit tests for CONNECT request formatting, HTTPS proxy support, auth header behavior, and timeout handling. |
| security/opengrep/rules/openclaw-policy/no-raw-http2-connect.yml | Adds a policy rule flagging raw http2.connect() usage outside the approved wrapper. |
| security/opengrep/precise.yml | Updates compiled OpenGrep ruleset to include the new policy rule. |
| scripts/check-no-raw-http2-imports.mjs | Adds a local lint script preventing production node:http2 imports outside the wrapper file. |
| package.json | Wires in the new tmp lint check and includes it in the scripts lint pipeline. |
| docs/network.md | Documents the policy to use connectApnsHttp2Session() for APNs HTTP/2 so managed proxy routing applies. |
| CHANGELOG.md | Notes the behavior change: direct APNs HTTP/2 now honors managed proxy egress controls. |
ec5c471 to
64f48d5
Compare
1127b62 to
c67415e
Compare
4521f70 to
dab7c86
Compare
Summary: - This PR routes direct APNs HTTP/2 sends through an APNs allowlisted managed-proxy CONNECT wrapper, adds APNs proxy validation/docs/guardrails, and expands regression and live-test coverage. - Reproducibility: yes. source-reproducible: current main `sendApnsRequest()` still uses raw `http2.connect(au ... nly covers HTTP/global-agent/Undici hooks. I did not run a live APNs reproduction in this read-only review. Automerge notes: - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 APNs connections - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 with OpenGrep - PR branch already contained follow-up commit before automerge: lint: ban raw HTTP2 imports - PR branch already contained follow-up commit before automerge: fix: use managed proxy state for APNs - PR branch already contained follow-up commit before automerge: test: exercise APNs active proxy state - PR branch already contained follow-up commit before automerge: fix: reject conflicting managed proxy activation Validation: - ClawSweeper review passed for head dab7c86. - Required merge gates passed before the squash merge. Prepared head SHA: dab7c86 Review: openclaw#74905 (comment) Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com> Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Summary: - This PR routes direct APNs HTTP/2 sends through an APNs allowlisted managed-proxy CONNECT wrapper, adds APNs proxy validation/docs/guardrails, and expands regression and live-test coverage. - Reproducibility: yes. source-reproducible: current main `sendApnsRequest()` still uses raw `http2.connect(au ... nly covers HTTP/global-agent/Undici hooks. I did not run a live APNs reproduction in this read-only review. Automerge notes: - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 APNs connections - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 with OpenGrep - PR branch already contained follow-up commit before automerge: lint: ban raw HTTP2 imports - PR branch already contained follow-up commit before automerge: fix: use managed proxy state for APNs - PR branch already contained follow-up commit before automerge: test: exercise APNs active proxy state - PR branch already contained follow-up commit before automerge: fix: reject conflicting managed proxy activation Validation: - ClawSweeper review passed for head dab7c86. - Required merge gates passed before the squash merge. Prepared head SHA: dab7c86 Review: openclaw#74905 (comment) Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com> Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Summary: - This PR routes direct APNs HTTP/2 sends through an APNs allowlisted managed-proxy CONNECT wrapper, adds APNs proxy validation/docs/guardrails, and expands regression and live-test coverage. - Reproducibility: yes. source-reproducible: current main `sendApnsRequest()` still uses raw `http2.connect(au ... nly covers HTTP/global-agent/Undici hooks. I did not run a live APNs reproduction in this read-only review. Automerge notes: - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 APNs connections - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 with OpenGrep - PR branch already contained follow-up commit before automerge: lint: ban raw HTTP2 imports - PR branch already contained follow-up commit before automerge: fix: use managed proxy state for APNs - PR branch already contained follow-up commit before automerge: test: exercise APNs active proxy state - PR branch already contained follow-up commit before automerge: fix: reject conflicting managed proxy activation Validation: - ClawSweeper review passed for head dab7c86a7595a01b09c32395578e7c26a03f938d. - Required merge gates passed before the squash merge. Prepared head SHA: dab7c86a7595a01b09c32395578e7c26a03f938d Review: openclaw/openclaw#74905 (comment) Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com> Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Summary: - This PR routes direct APNs HTTP/2 sends through an APNs allowlisted managed-proxy CONNECT wrapper, adds APNs proxy validation/docs/guardrails, and expands regression and live-test coverage. - Reproducibility: yes. source-reproducible: current main `sendApnsRequest()` still uses raw `http2.connect(au ... nly covers HTTP/global-agent/Undici hooks. I did not run a live APNs reproduction in this read-only review. Automerge notes: - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 APNs connections - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 with OpenGrep - PR branch already contained follow-up commit before automerge: lint: ban raw HTTP2 imports - PR branch already contained follow-up commit before automerge: fix: use managed proxy state for APNs - PR branch already contained follow-up commit before automerge: test: exercise APNs active proxy state - PR branch already contained follow-up commit before automerge: fix: reject conflicting managed proxy activation Validation: - ClawSweeper review passed for head dab7c86a7595a01b09c32395578e7c26a03f938d. - Required merge gates passed before the squash merge. Prepared head SHA: dab7c86a7595a01b09c32395578e7c26a03f938d Review: openclaw/openclaw#74905 (comment) Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com> Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Summary: - This PR routes direct APNs HTTP/2 sends through an APNs allowlisted managed-proxy CONNECT wrapper, adds APNs proxy validation/docs/guardrails, and expands regression and live-test coverage. - Reproducibility: yes. source-reproducible: current main `sendApnsRequest()` still uses raw `http2.connect(au ... nly covers HTTP/global-agent/Undici hooks. I did not run a live APNs reproduction in this read-only review. Automerge notes: - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 APNs connections - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 with OpenGrep - PR branch already contained follow-up commit before automerge: lint: ban raw HTTP2 imports - PR branch already contained follow-up commit before automerge: fix: use managed proxy state for APNs - PR branch already contained follow-up commit before automerge: test: exercise APNs active proxy state - PR branch already contained follow-up commit before automerge: fix: reject conflicting managed proxy activation Validation: - ClawSweeper review passed for head dab7c86a7595a01b09c32395578e7c26a03f938d. - Required merge gates passed before the squash merge. Prepared head SHA: dab7c86a7595a01b09c32395578e7c26a03f938d Review: openclaw/openclaw#74905 (comment) Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com> Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Summary: - This PR routes direct APNs HTTP/2 sends through an APNs allowlisted managed-proxy CONNECT wrapper, adds APNs proxy validation/docs/guardrails, and expands regression and live-test coverage. - Reproducibility: yes. source-reproducible: current main `sendApnsRequest()` still uses raw `http2.connect(au ... nly covers HTTP/global-agent/Undici hooks. I did not run a live APNs reproduction in this read-only review. Automerge notes: - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 APNs connections - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 with OpenGrep - PR branch already contained follow-up commit before automerge: lint: ban raw HTTP2 imports - PR branch already contained follow-up commit before automerge: fix: use managed proxy state for APNs - PR branch already contained follow-up commit before automerge: test: exercise APNs active proxy state - PR branch already contained follow-up commit before automerge: fix: reject conflicting managed proxy activation Validation: - ClawSweeper review passed for head dab7c86. - Required merge gates passed before the squash merge. Prepared head SHA: dab7c86 Review: openclaw#74905 (comment) Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com> Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Summary: - This PR routes direct APNs HTTP/2 sends through an APNs allowlisted managed-proxy CONNECT wrapper, adds APNs proxy validation/docs/guardrails, and expands regression and live-test coverage. - Reproducibility: yes. source-reproducible: current main `sendApnsRequest()` still uses raw `http2.connect(au ... nly covers HTTP/global-agent/Undici hooks. I did not run a live APNs reproduction in this read-only review. Automerge notes: - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 APNs connections - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 with OpenGrep - PR branch already contained follow-up commit before automerge: lint: ban raw HTTP2 imports - PR branch already contained follow-up commit before automerge: fix: use managed proxy state for APNs - PR branch already contained follow-up commit before automerge: test: exercise APNs active proxy state - PR branch already contained follow-up commit before automerge: fix: reject conflicting managed proxy activation Validation: - ClawSweeper review passed for head dab7c86. - Required merge gates passed before the squash merge. Prepared head SHA: dab7c86 Review: openclaw#74905 (comment) Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com> Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Summary: - This PR routes direct APNs HTTP/2 sends through an APNs allowlisted managed-proxy CONNECT wrapper, adds APNs proxy validation/docs/guardrails, and expands regression and live-test coverage. - Reproducibility: yes. source-reproducible: current main `sendApnsRequest()` still uses raw `http2.connect(au ... nly covers HTTP/global-agent/Undici hooks. I did not run a live APNs reproduction in this read-only review. Automerge notes: - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 APNs connections - PR branch already contained follow-up commit before automerge: test: guard raw HTTP2 with OpenGrep - PR branch already contained follow-up commit before automerge: lint: ban raw HTTP2 imports - PR branch already contained follow-up commit before automerge: fix: use managed proxy state for APNs - PR branch already contained follow-up commit before automerge: test: exercise APNs active proxy state - PR branch already contained follow-up commit before automerge: fix: reject conflicting managed proxy activation Validation: - ClawSweeper review passed for head dab7c86. - Required merge gates passed before the squash merge. Prepared head SHA: dab7c86 Review: openclaw#74905 (comment) Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com> Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Summary
http2.connect()seamsecureConnect/ALPN validation, and regression testshttp2.connect()Test Plan
OPENCLAW_LOCAL_CHECK=0 pnpm test src/infra/net/http-connect-tunnel.test.ts src/infra/push-apns-http2.test.ts src/infra/push-apns.test.ts src/infra/net/proxy/proxy-lifecycle.test.ts src/infra/net/proxy/proxy-validation.test.ts src/cli/proxy-cli.runtime.test.ts src/cli/proxy-cli.test.ts test/scripts/run-additional-boundary-checks.test.tspnpm lint:tmp:no-raw-http2-importsscripts/run-opengrep.sh --error -- src/infra/net/http-connect-tunnel.ts src/infra/push-apns-http2.ts src/infra/push-apns.tspnpm exec oxfmt --check --threads=1 src/infra/net/http-connect-tunnel.ts src/infra/net/http-connect-tunnel.test.ts src/infra/push-apns.test.ts src/infra/net/proxy/active-proxy-state.ts docs/network.md CHANGELOG.md scripts/run-additional-boundary-checks.mjs test/scripts/run-additional-boundary-checks.test.tspnpm check:no-conflict-markers && git diff --check origin/main...HEAD && git merge-tree origin/main HEADOPENCLAW_LOCAL_CHECK=0 pnpm check:changedopenclaw-proxy-lab: CONNECT toapi.sandbox.push.apple.com:443, TLS ALPNh2, Node HTTP/2 session connected through proxyNotes
HTTPS_PROXY/HTTP_PROXYdiscovery.http://andhttps://proxy endpoints and waits for the target TLS socket to negotiateh2before handing it to HTTP/2.