Skip to content

feat: make CORS origin configurable for cloud deployments#2344

Open
hobostay wants to merge 1 commit into
tinyhumansai:mainfrom
hobostay:fix/configurable-cors-origins
Open

feat: make CORS origin configurable for cloud deployments#2344
hobostay wants to merge 1 commit 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

Release Notes

  • New Features
    • Added configurable CORS origin support, enabling operators to selectively restrict cross-origin requests to specific trusted origins instead of accepting all requests. Configuration is managed via an optional environment variable with a permissive default to maintain backward compatibility. This enhances security for production deployments.

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

📝 Walkthrough

Walkthrough

This PR makes the JSON-RPC server's CORS origin configurable via the OPENHUMAN_CORS_ORIGIN environment variable. Documentation is added to .env.example with deployment guidance, and the with_cors_headers function is updated to read the env var and validate it as a valid HTTP header value, defaulting to *.

Changes

Configurable CORS Origin

Layer / File(s) Summary
CORS origin from environment variable
.env.example, src/core/jsonrpc.rs
Environment variable OPENHUMAN_CORS_ORIGIN is documented with default and deployment guidance, and is read and validated in with_cors_headers to set Access-Control-Allow-Origin, falling back to * if unset or invalid.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related issues

  • #2262: Both changes modify src/core/jsonrpc.rs's with_cors_headers behavior for Access-Control-Allow-Origin (this PR adds env-based configuration, while #2262 proposes an allowlist approach).

Suggested reviewers

  • senamakel

Poem

🐰 A rabbit hops through CORS with glee,
Origins now configurable, wild or set free!
From env vars it reads with validation so neat,
Cross-origin requests now meet the beat. ✨

🚥 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 clearly and concisely summarizes the main change: making CORS origin configurable for cloud deployments, which aligns with the primary objective of the PR.
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
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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants