From 71c57ea647fbc376d1207f11d851c09504c9c02d Mon Sep 17 00:00:00 2001 From: bitkyc08-arch Date: Tue, 25 Aug 2026 10:37:05 +0900 Subject: [PATCH 1/4] release: v2.32.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f73ed2d0e5..063ecfe73e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@bitkyc08/opencodex", - "version": "2.32.0", + "version": "2.32.1", "description": "Universal provider proxy for OpenAI Codex & Claude Code — use any LLM with Codex CLI/App/SDK and Claude Code", "type": "module", "main": "./bin/package-main.mjs", From ec51e42d745d2645bcb22cb67855fa053ba1778e Mon Sep 17 00:00:00 2001 From: bitkyc08-arch Date: Tue, 25 Aug 2026 20:25:22 +0900 Subject: [PATCH 2/4] release: v2.33.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 063ecfe73e..6f8499ffbf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@bitkyc08/opencodex", - "version": "2.32.1", + "version": "2.33.0", "description": "Universal provider proxy for OpenAI Codex & Claude Code — use any LLM with Codex CLI/App/SDK and Claude Code", "type": "module", "main": "./bin/package-main.mjs", From aaa9eaf37058965373dc42d1ca344e987950b6b6 Mon Sep 17 00:00:00 2001 From: JUN Date: Wed, 2 Sep 2026 18:43:29 +0900 Subject: [PATCH 3/4] fix(release): pass the bump job's permissions through the reusable-workflow call (#3262) Both v2.40.0 release dispatches (33615174183 preview, 33615177849 main) died at startup_failure: a workflow_call cannot grant its callee more than the calling job holds, and dev-version-bump.yml's job declares contents+pull- requests write. #3129 wired the call but never dispatched a release, so this is its first live run. The caller job now declares exactly the callee's two permissions; no other job in release.yml gains anything. Co-authored-by: jun (cherry picked from commit 7ce0ba51834740d7b4d5ec4793f6572d84624409) --- .github/workflows/release.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 458bb67e0a..261aece1d1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -67,6 +67,14 @@ jobs: bump-dev-version: needs: publish if: ${{ inputs.dry-run != true }} + # A reusable-workflow CALL cannot grant the callee more than the calling job holds, + # and GitHub refuses the whole run at startup when the called workflow's own job + # declares permissions the caller did not pass down ("startup_failure", runs + # 33615174183 / 33615177849 — the first dispatches since #3129 wired this call). + # The callee's job declares exactly these two; nothing else in this file gains them. + permissions: + contents: write + pull-requests: write uses: ./.github/workflows/dev-version-bump.yml with: released-version: v${{ inputs.version }} From bae06747bb10947d422e72863b1e4fa579d7bfca Mon Sep 17 00:00:00 2001 From: luvs01 Date: Thu, 3 Sep 2026 14:48:52 +0900 Subject: [PATCH 4/4] docs(security): harden generic management proxies --- .../src/content/docs/guides/remote-hub.md | 23 ++++++++++++++----- structure/05_gui-and-management-api.md | 7 +++--- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/docs-site/src/content/docs/guides/remote-hub.md b/docs-site/src/content/docs/guides/remote-hub.md index 16ef574ab1..d36bda0704 100644 --- a/docs-site/src/content/docs/guides/remote-hub.md +++ b/docs-site/src/content/docs/guides/remote-hub.md @@ -77,7 +77,7 @@ ocx config set hostname 100.64.0.10 ocx config set hub.managementPublicOrigin '"https://hub-name.tailnet-name.ts.net"' ocx config set corsAllowOrigins '["http://localhost:10100"]' ocx config set hub.managementIngress '{"enabled":true,"port":10101}' -ocx config set remoteGui.allowedTailscaleUsers '["operator@example.com"]' +ocx config set remoteGui.allowedTailscaleUsers '[]' # Generate/read this in a protected operator shell or secret manager. # It is a data-admission token, not a provider credential. @@ -115,7 +115,14 @@ tailscale serve status Set `hub.managementPublicOrigin` to the exact HTTPS origin shown by Serve. Add the operator's exact Tailscale login to `remoteGui.allowedTailscaleUsers`; an empty list means no remote identity can mint -a session. Verify both directions: +a session. Enable that allowlist only when Tailscale Serve is the process forwarding to the +management ingress: + +```bash +ocx config set remoteGui.allowedTailscaleUsers '["operator@example.com"]' +``` + +Verify both directions: ```bash # Negative: the loopback-only port must not be reachable through the node's tailnet address. @@ -138,8 +145,10 @@ tailscale cert hub-name.tailnet-name.ts.net ``` Protect the private key, renew it through Tailscale's supported mechanism, and proxy only to -`127.0.0.1:10101`. A generic TLS proxy does not supply trustworthy Tailscale identity. Do not -fabricate `Tailscale-User-*` headers; use the single-use, origin-bound pairing flow instead. +`127.0.0.1:10101`. A generic TLS proxy does not supply trustworthy Tailscale identity. Keep +`remoteGui.allowedTailscaleUsers` empty, and configure the proxy to remove or reject every incoming +`Tailscale-User-*` header before forwarding. Preserving client-supplied identity headers is unsafe; +do not merely avoid adding new ones. Use the single-use, origin-bound pairing flow instead. ## Headless OAuth @@ -231,14 +240,16 @@ docker compose run --rm hub bun run src/cli/index.ts config set runtimeRole hub docker compose run --rm hub bun run src/cli/index.ts config set hostname 0.0.0.0 docker compose run --rm hub bun run src/cli/index.ts config set hub.managementPublicOrigin '"https://hub-name.tailnet-name.ts.net"' docker compose run --rm hub bun run src/cli/index.ts config set hub.managementIngress '{"enabled":true,"port":10101}' -docker compose run --rm hub bun run src/cli/index.ts config set remoteGui.allowedTailscaleUsers '["operator@example.com"]' +docker compose run --rm hub bun run src/cli/index.ts config set remoteGui.allowedTailscaleUsers '[]' docker compose up -d ``` Do not put a token in `ARG`, `ENV`, `COPY`, Compose YAML, image history, or the command line. Do not mount the Docker socket, host home, Codex home, SSH agent, or provider-key files. Publish only port `10100`. A management ingress bound to `127.0.0.1:10101` inside the container is reachable only by a -TLS/tailnet frontend in the same network namespace; never publish `10101` as a shortcut. +TLS/tailnet frontend in the same network namespace; never publish `10101` as a shortcut. Keep the +allowlist empty and use pairing for a generic frontend. If a Tailscale Serve sidecar is the process +forwarding to `10101`, set the exact operator allowlist only after that topology is in place. After the container is healthy, run a separate readiness promotion check: diff --git a/structure/05_gui-and-management-api.md b/structure/05_gui-and-management-api.md index ff75b15e88..2b8468f620 100644 --- a/structure/05_gui-and-management-api.md +++ b/structure/05_gui-and-management-api.md @@ -70,9 +70,10 @@ Tailscale identity headers authorize session issuance only when the request arri listener and the exact login appears in `remoteGui.allowedTailscaleUsers`. The public listener and the unauthenticated data-loopback listener always pass `trustedTailscaleIngress: false`, regardless of `Host`, `Origin`, `Forwarded`, `X-Forwarded-*`, or `Tailscale-User-*` values. A generic TLS proxy -cannot establish that identity and uses the existing single-use, digest-only, origin-bound pairing -exchange. Pairing accepts no admin/data credential substitute and consumes a grant only after the -full origin predicate succeeds. +cannot establish that identity: its deployment must keep the Tailscale allowlist empty, remove or +reject every client-supplied `Tailscale-User-*` header, and use the existing single-use, digest-only, +origin-bound pairing exchange. Pairing accepts no admin/data credential substitute and consumes a +grant only after the full origin predicate succeeds. The server issues a local in-memory session for five minutes or a remote session for twelve hours, with 128 live sessions maximum. Every session is bound to the exact server and browser origins;