Skip to content

feat: make CORS origin configurable for cloud deployments#2344

Merged
senamakel merged 6 commits into
tinyhumansai:mainfrom
hobostay:fix/configurable-cors-origins
May 23, 2026
Merged

feat: make CORS origin configurable for cloud deployments#2344
senamakel merged 6 commits into
tinyhumansai:mainfrom
hobostay:fix/configurable-cors-origins

Conversation

@hobostay
Copy link
Copy Markdown
Contributor

@hobostay hobostay commented May 20, 2026

Summary

  • Adds OPENHUMAN_CORS_ORIGIN environment variable to configure the JSON-RPC server's Access-Control-Allow-Origin header
  • Default (unset) preserves current behavior: wildcard * for local/Tauri desktop
  • When set to a specific origin (e.g. https://app.example.com), CORS is restricted to that origin only
  • Falls back to wildcard on invalid input so the server never crashes over a typo

Context

The JSON-RPC server in src/core/jsonrpc.rs hardcodes Access-Control-Allow-Origin: *. This is correct for the desktop case where the sidecar binds to 127.0.0.1, but becomes a security concern for Docker/cloud deployments where OPENHUMAN_CORE_HOST=0.0.0.0 — any website could make cross-origin requests to the API.

The .env.example already documents cloud deployment mode (OPENHUMAN_CORE_HOST=0.0.0.0) and gitbooks/features/cloud-deploy.md covers the setup. This change gives cloud deployers the ability to lock down CORS without modifying source code.

Test plan

  • Verify local desktop still works with OPENHUMAN_CORS_ORIGIN unset (wildcard)
  • Set OPENHUMAN_CORS_ORIGIN=https://example.com and verify CORS header reflects the value
  • Set OPENHUMAN_CORS_ORIGIN to an invalid string and verify fallback to wildcard

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Added guidance and a commented example for an optional environment variable to list allowed CORS origins (comma-separated) and notes on setting canonical frontend origins for Docker/cloud deployments bound to 0.0.0.0.
  • Chore
    • Clarified CORS guidance in server comments; no runtime behavior or header injection logic was changed.

Review Change Stack

The JSON-RPC server in jsonrpc.rs hardcodes Access-Control-Allow-Origin
to wildcard (*). This is correct for the local/Tauri desktop case (the
sidecar only binds to 127.0.0.1) but becomes a security concern when
deploying to Docker or cloud where OPENHUMAN_CORE_HOST=0.0.0.0 — any
website could make cross-origin requests to the API.

Add OPENHUMAN_CORS_ORIGIN env var support:
- Default (unset): wildcard *, preserving current desktop behavior
- Set to a specific origin: restricts CORS to that origin
- Invalid value: falls back to wildcard with no server crash

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@hobostay hobostay requested a review from a team May 20, 2026 12:26
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 10c03f9a-ba1a-48be-8471-0fb319c1ce14

📥 Commits

Reviewing files that changed from the base of the PR and between c441d2e and c6530c9.

📒 Files selected for processing (2)
  • .env.example
  • src/core/jsonrpc.rs
💤 Files with no reviewable changes (1)
  • src/core/jsonrpc.rs
✅ Files skipped from review due to trivial changes (1)
  • .env.example

📝 Walkthrough

Walkthrough

Adds a commented OPENHUMAN_CORE_ALLOWED_ORIGINS entry to .env.example and a doc comment above with_cors_headers in src/core/jsonrpc.rs advising using that env var (comma-separated) for non-loopback Docker/cloud deployments instead of wildcarding CORS.

Changes

CORS docs and comments

Layer / File(s) Summary
Env example and doc comment
.env.example, src/core/jsonrpc.rs
Adds a commented OPENHUMAN_CORE_ALLOWED_ORIGINS example to .env.example and a doc comment above with_cors_headers advising the env var be used (comma-separated origins) when the server binds to 0.0.0.0; no runtime logic changes.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Possibly related PRs

Suggested labels

rust-core, working

Suggested reviewers

  • M3gA-Mind
  • sanil-23

Poem

🐰 I nibbled docs beneath the moonlit code,
A hint for origins, in a safe, small node.
Commented lines to guide the cloud-bound host,
No logic changed, just a helpful post.
Hooray — deployment's safer, says this rabbit most.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change—making CORS origins configurable—which directly corresponds to the PR objectives and file modifications.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/jsonrpc.rs`:
- Around line 626-635: Add structured logging around the CORS origin parsing:
when reading OPENHUMAN_CORS_ORIGIN and before calling
HeaderValue::from_str(&origin) emit an info/debug log that a custom origin was
configured (include the origin value), and when HeaderValue::from_str(&origin)
returns Err (the current unwrap_or_else branch that creates
HeaderValue::from_static("*")) emit a warning/error log that the provided
OPENHUMAN_CORS_ORIGIN was invalid and the code is falling back to wildcard "*"
(include the invalid origin and the fact that wildcard is used); place these
logs adjacent to the origin/origin_value logic and keep using the same logging
facility used elsewhere in jsonrpc.rs for consistent structured, grep-friendly
messages.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 72f12ddd-fdf4-4125-9181-7d0429df60c6

📥 Commits

Reviewing files that changed from the base of the PR and between 41e7631 and c441d2e.

📒 Files selected for processing (2)
  • .env.example
  • src/core/jsonrpc.rs

Comment thread src/core/jsonrpc.rs Outdated
Comment on lines +626 to +635
let origin = std::env::var("OPENHUMAN_CORS_ORIGIN")
.ok()
.filter(|v| !v.is_empty())
.unwrap_or_else(|| "*".to_string());
// HeaderValue::from_str is fallible for non-visible ASCII; fall back to
// wildcard on invalid input so the server never refuses to start over a
// typo in the env var.
let origin_value = HeaderValue::from_str(&origin)
.unwrap_or_else(|_| HeaderValue::from_static("*"));
headers.insert(header::ACCESS_CONTROL_ALLOW_ORIGIN, origin_value);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify HeaderValue::from_str usage is correct for the axum version

# Check Cargo.toml for axum version
echo "=== Checking axum version in Cargo.toml ==="
rg -n "axum\s*=" Cargo.toml

# Check for existing HeaderValue::from_str usage patterns in the codebase
echo -e "\n=== Existing HeaderValue::from_str usage ==="
rg -n "HeaderValue::from_str" --type rust -C2

Repository: tinyhumansai/openhuman

Length of output: 5383


🏁 Script executed:

# Check the actual current code at lines 626-635
sed -n '620,640p' src/core/jsonrpc.rs | cat -n

Repository: tinyhumansai/openhuman

Length of output: 1221


🏁 Script executed:

# Check if log/tracing is already imported in jsonrpc.rs
head -50 src/core/jsonrpc.rs | grep -E "^use.*log|^use.*tracing"

Repository: tinyhumansai/openhuman

Length of output: 48


🏁 Script executed:

# Check the full context around the CORS function
sed -n '620,645p' src/core/jsonrpc.rs | cat -n

Repository: tinyhumansai/openhuman

Length of output: 1434


🏁 Script executed:

# Check if log crate is in Cargo.toml
rg -n "^log\s*=" Cargo.toml

Repository: tinyhumansai/openhuman

Length of output: 81


🏁 Script executed:

# Search for any logging already in jsonrpc.rs
rg -n "log::|tracing::|eprintln|println" src/core/jsonrpc.rs

Repository: tinyhumansai/openhuman

Length of output: 5548


🏁 Script executed:

# Check what's imported at the top of jsonrpc.rs
head -100 src/core/jsonrpc.rs

Repository: tinyhumansai/openhuman

Length of output: 4566


Add logging for CORS origin validation to improve observability.

The CORS header configuration should log when an invalid OPENHUMAN_CORS_ORIGIN environment variable falls back to wildcard *, as this is a security-relevant error path for cloud deployments. Also log when a valid custom origin is configured.

Add structured, grep-friendly logging consistent with the rest of jsonrpc.rs:

Suggested logging implementation
     let origin_value = HeaderValue::from_str(&origin)
-        .unwrap_or_else(|_| HeaderValue::from_static("*"));
+        .unwrap_or_else(|e| {
+            log::warn!(
+                "[cors] Invalid OPENHUMAN_CORS_ORIGIN value {:?} — falling back to wildcard '*': {}",
+                origin,
+                e
+            );
+            HeaderValue::from_static("*")
+        });
+    if origin != "*" && origin_value.to_str().unwrap_or("*") != "*" {
+        log::debug!("[cors] Using custom origin: {}", origin);
+    }

Per coding guidelines, error paths should be logged at appropriate levels. The fallback to wildcard when invalid input is provided is a security-relevant error path that operators need to observe.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let origin = std::env::var("OPENHUMAN_CORS_ORIGIN")
.ok()
.filter(|v| !v.is_empty())
.unwrap_or_else(|| "*".to_string());
// HeaderValue::from_str is fallible for non-visible ASCII; fall back to
// wildcard on invalid input so the server never refuses to start over a
// typo in the env var.
let origin_value = HeaderValue::from_str(&origin)
.unwrap_or_else(|_| HeaderValue::from_static("*"));
headers.insert(header::ACCESS_CONTROL_ALLOW_ORIGIN, origin_value);
let origin = std::env::var("OPENHUMAN_CORS_ORIGIN")
.ok()
.filter(|v| !v.is_empty())
.unwrap_or_else(|| "*".to_string());
// HeaderValue::from_str is fallible for non-visible ASCII; fall back to
// wildcard on invalid input so the server never refuses to start over a
// typo in the env var.
let origin_value = HeaderValue::from_str(&origin)
.unwrap_or_else(|e| {
log::warn!(
"[cors] Invalid OPENHUMAN_CORS_ORIGIN value {:?} — falling back to wildcard '*': {}",
origin,
e
);
HeaderValue::from_static("*")
});
if origin != "*" && origin_value.to_str().unwrap_or("*") != "*" {
log::debug!("[cors] Using custom origin: {}", origin);
}
headers.insert(header::ACCESS_CONTROL_ALLOW_ORIGIN, origin_value);
🧰 Tools
🪛 GitHub Actions: Type Check / 0_Type Check TypeScript.txt

[error] 630-630: Prettier formatting check failed. Diff indicates a formatting change in jsonrpc.rs around let origin_value = HeaderValue::from_str(&origin) ... (reflowed to multiple lines).

🪛 GitHub Actions: Type Check / 1_Rust Quality (fmt + clippy).txt

[error] 630-631: cargo fmt --all -- --check failed due to formatting diff in src/core/jsonrpc.rs around line 630 (mismatched line breaks/indentation). Run cargo fmt to apply the correct formatting.

🪛 GitHub Actions: Type Check / Rust Quality (fmt + clippy)

[error] 630-632: cargo fmt --check failed due to Rust formatting differences. Diff indicates formatting change needed for let origin_value assignment (line break/indentation).

🪛 GitHub Actions: Type Check / Type Check TypeScript

[error] 630-634: Prettier format check failed. Diff shows formatting change in let origin_value assignment (line wrapping/indentation).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/jsonrpc.rs` around lines 626 - 635, Add structured logging around
the CORS origin parsing: when reading OPENHUMAN_CORS_ORIGIN and before calling
HeaderValue::from_str(&origin) emit an info/debug log that a custom origin was
configured (include the origin value), and when HeaderValue::from_str(&origin)
returns Err (the current unwrap_or_else branch that creates
HeaderValue::from_static("*")) emit a warning/error log that the provided
OPENHUMAN_CORS_ORIGIN was invalid and the code is falling back to wildcard "*"
(include the invalid origin and the fact that wildcard is used); place these
logs adjacent to the origin/origin_value logic and keep using the same logging
facility used elsewhere in jsonrpc.rs for consistent structured, grep-friendly
messages.

@M3gA-Mind
Copy link
Copy Markdown
Contributor

@hobostay CI is failing on changes in this PR — please fix before review.

2 similar comments
@M3gA-Mind
Copy link
Copy Markdown
Contributor

@hobostay CI is failing on changes in this PR — please fix before review.

@M3gA-Mind
Copy link
Copy Markdown
Contributor

@hobostay CI is failing on changes in this PR — please fix before review.

@senamakel
Copy link
Copy Markdown
Member

Per pr-manager-lite finishing pass:

Merge with main: Resolved the src/core/jsonrpc.rs CORS conflict. Main now ships a proper Origin-echoing allowlist (is_origin_allowed keyed off OPENHUMAN_CORE_ALLOWED_ORIGINS), so the original OPENHUMAN_CORS_ORIGIN wildcard mechanism this PR introduced is superseded. Took main's with_cors_headers implementation, kept this PR's contribution by:

  • documenting OPENHUMAN_CORE_ALLOWED_ORIGINS in .env.example for the Docker / cloud deployment use case
  • adding a rustdoc note above with_cors_headers pointing operators at the env var instead of wildcard

CodeRabbit comment (jsonrpc.rs:635 — log invalid OPENHUMAN_CORS_ORIGIN fallback): stale. The env var no longer exists; the invalid-value-falls-back-to-wildcard path it asked to log is gone. The spirit of the request (observability on the security-relevant path) is already satisfied by tracing::warn!("[cors] rejected disallowed origin: ...") introduced on main.

CI failures (Type Check / Rust Quality fmt+clippy / PR Submission Checklist): those failures were against the pre-merge code. cargo fmt --check and cargo check are clean on the merged tree; the CORS unit tests (8/8) pass.

Commits pushed to hobostay:fix/configurable-cors-origins:

  • abd87a5 Merge branch 'main' into pr/2344
  • c6530c9 chore(pr-fix): drop stray blank line in with_cors_headers

@coderabbitai coderabbitai Bot added rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. working A PR that is being worked on by the team. labels May 22, 2026
@senamakel senamakel merged commit 9ac9613 into tinyhumansai:main May 23, 2026
29 of 34 checks passed
senamakel added a commit to aqilaziz/openhuman that referenced this pull request May 23, 2026
…ai#2344)

Co-authored-by: Test User <test@example.com>
Co-authored-by: Steven Enamakel <31011319+senamakel@users.noreply.github.com>
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. working A PR that is being worked on by the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants