Skip to content

iOS Security Stack 3/5: Runtime Security Guards#33031

Merged
mbelinky merged 3 commits intomainfrom
stack/ios-sec-03-security-guards
Mar 3, 2026
Merged

iOS Security Stack 3/5: Runtime Security Guards#33031
mbelinky merged 3 commits intomainfrom
stack/ios-sec-03-security-guards

Conversation

@mbelinky
Copy link
Copy Markdown
Contributor

@mbelinky mbelinky commented Mar 3, 2026

Part 3/5 of iOS security stack (split from #31979).

Scope

  • Gate env-var API key usage behind DEBUG-only behavior
  • Tighten deep-link rate limiting
  • Cap WebSocket message size in shared gateway channel path

Files

  • apps/ios/Sources/Model/NodeAppModel.swift
  • apps/ios/Sources/Voice/TalkModeManager.swift
  • apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayChannel.swift

Stack

  • Base: Part 2/5 (stack/ios-sec-02-concurrency-locks)
  • Next PR: Part 4/5 (stack/ios-sec-04-tts-fallback)

@openclaw-barnacle openclaw-barnacle bot added app: ios App: ios size: XS maintainer Maintainer-authored PR labels Mar 3, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 3, 2026

Greptile Summary

This PR introduces three targeted runtime security improvements to the iOS app stack:

  1. NodeAppModel.swift — Deep-link rate-limit interval raised from 1 s to 5 s. The logic is sound; timestamps are only updated on accepted prompts, not on throttled ones.

  2. TalkModeManager.swift — Env-var ELEVENLABS_API_KEY fallback is correctly gated behind #if DEBUG, preventing Release builds from reading environment variables. The refactored structure preserves identical DEBUG semantics while improving security.

  3. GatewayChannel.swift — WebSocket maximumMessageSize capped at 4 MB (down from 16 MB). The change is correctly applied.

All three changes are straightforward security tightening with no apparent regressions.

Confidence Score: 4/5

  • All three changes are straightforward security improvements with correct implementation. Safe to merge.
  • The deep-link rate limit and TTS env-var DEBUG gating are clean, well-implemented security changes with zero regression risk. The WebSocket message size reduction is correctly applied but lacks explicit validation documentation; however, the implementation itself is sound.
  • apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayChannel.swift — While the 4 MB limit is correctly applied, it would benefit from documentation of why this specific value was chosen relative to actual gateway payload sizes.

Last reviewed commit: 64ce1a1

Copy link
Copy Markdown

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

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: 64ce1a11d4

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

let task = self.webSocketTask(with: url)
// Avoid "Message too long" receive errors for large snapshots / history payloads.
task.maximumMessageSize = 16 * 1024 * 1024 // 16 MB
task.maximumMessageSize = 4 * 1024 * 1024 // 4 MB
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep iOS websocket cap above chat.history response budget

Lowering task.maximumMessageSize to 4 MB in the default URLSession websocket path introduces a transport mismatch with current gateway responses: chat.history is still capped at 6 MB (src/gateway/server-constants.ts, used in src/gateway/server-methods/chat.ts). On non-TLS iOS connections that use this codepath, any history payload between 4 MB and 6 MB will now fail with "Message too long" and can drop the channel, which breaks consumers like Talk Mode polling chat.history.

Useful? React with 👍 / 👎.

@mbelinky mbelinky force-pushed the stack/ios-sec-02-concurrency-locks branch from 2d676d6 to 4e15a3d Compare March 3, 2026 15:19
@mbelinky mbelinky force-pushed the stack/ios-sec-03-security-guards branch from 64ce1a1 to 0477d46 Compare March 3, 2026 15:19
Copy link
Copy Markdown

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

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: 0477d466a4

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

return
}

self.presentAgentDeepLinkPrompt(prompt)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Clear queued prompt before presenting a fresh deep link

Presenting a prompt in the elapsed >= promptIntervalSeconds path does not clear any previously queued prompt, so an older queued request can still be delivered later by deliverQueuedAgentDeepLinkPrompt(). This can happen when a queued task wakes around the 5s boundary but a new deep link is handled first on the main actor; the user then sees and may approve a stale request after handling the newer one, which reorders confirmations and can submit outdated content.

Useful? React with 👍 / 👎.

@mbelinky mbelinky force-pushed the stack/ios-sec-02-concurrency-locks branch from 4e15a3d to b69e706 Compare March 3, 2026 15:25
@mbelinky mbelinky force-pushed the stack/ios-sec-03-security-guards branch from 0477d46 to 7504ea2 Compare March 3, 2026 15:25
@mbelinky mbelinky force-pushed the stack/ios-sec-02-concurrency-locks branch from b69e706 to 0727b96 Compare March 3, 2026 15:43
@mbelinky mbelinky force-pushed the stack/ios-sec-03-security-guards branch from 7504ea2 to 136ec0d Compare March 3, 2026 15:43
@mbelinky mbelinky force-pushed the stack/ios-sec-02-concurrency-locks branch from 0727b96 to de6a2c4 Compare March 3, 2026 15:56
@mbelinky mbelinky force-pushed the stack/ios-sec-03-security-guards branch from 136ec0d to 53cfcb4 Compare March 3, 2026 15:56
Copy link
Copy Markdown

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

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: 53cfcb462b

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


private func presentAgentDeepLinkPrompt(_ prompt: AgentDeepLinkPrompt) {
self.lastAgentDeepLinkPromptAt = Date()
self.pendingAgentDeepLinkPrompt = prompt
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Clear stale queued prompt before showing a new deep-link alert

When a prompt is presented via presentAgentDeepLinkPrompt, any previously queued prompt is left intact, so an older queued deep link can still be delivered later by deliverQueuedAgentDeepLinkPrompt(). This creates an out-of-order confirmation flow (new request first, stale request later) and can cause users to approve outdated content after handling a newer deep link.

Useful? React with 👍 / 👎.

@mbelinky mbelinky force-pushed the stack/ios-sec-02-concurrency-locks branch from de6a2c4 to d5b5846 Compare March 3, 2026 16:10
@mbelinky mbelinky force-pushed the stack/ios-sec-03-security-guards branch from 53cfcb4 to 961dfc0 Compare March 3, 2026 16:10
@mbelinky mbelinky force-pushed the stack/ios-sec-02-concurrency-locks branch from d5b5846 to dd85dc7 Compare March 3, 2026 16:13
@mbelinky mbelinky force-pushed the stack/ios-sec-03-security-guards branch from 961dfc0 to 84864c4 Compare March 3, 2026 16:13
@mbelinky mbelinky changed the base branch from stack/ios-sec-02-concurrency-locks to main March 3, 2026 16:17
@mbelinky mbelinky force-pushed the stack/ios-sec-03-security-guards branch from 84864c4 to 1a70e35 Compare March 3, 2026 16:23
@mbelinky mbelinky force-pushed the stack/ios-sec-03-security-guards branch from 1a70e35 to f6a7145 Compare March 3, 2026 16:25
@mbelinky mbelinky force-pushed the stack/ios-sec-03-security-guards branch from f6a7145 to 9917165 Compare March 3, 2026 16:30
@mbelinky mbelinky merged commit a3112d6 into main Mar 3, 2026
9 checks passed
@mbelinky mbelinky deleted the stack/ios-sec-03-security-guards branch March 3, 2026 16:30
dawi369 pushed a commit to dawi369/davis that referenced this pull request Mar 3, 2026
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 9917165
Co-authored-by: mbelinky <[email protected]>
Co-authored-by: mbelinky <[email protected]>
Reviewed-by: @mbelinky