Skip to content

server: add --cors-* options - #25655

Merged
ServeurpersoCom merged 5 commits into
masterfrom
xsn/server_cors_args
Jul 14, 2026
Merged

server: add --cors-* options#25655
ServeurpersoCom merged 5 commits into
masterfrom
xsn/server_cors_args

Conversation

@ngxson

@ngxson ngxson commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Overview

Traditionally, llama-server always enable CORS * with no way to disable it. This was fine because llama-server endpoints were stateless, read-only and default config doesn't expose any sensitive data. The only risk was DoS which is not considered a vulnerability per llama.cpp's policy.

However, with the addition of --agent mode (built-in tools), server can now expose API that allow read/write arbitrary files. If combine with the relaxed CORS, it may allow malicious pages to access local file from server API.

This PR introduce 4 flags, inspired by vllm:

  • --cors-origins
  • --cors-methods
  • --cors-headers
  • --(no-)cors-credentials

By default:

  • the relaxed profile is used: credentials are allowed and Origin header is reflected back (no breaking changes), but a warning will show when server starts
  • if server tools are enable, CORS origin will be limited to localhost (can override via --cors-origins)

Recommendations

Depending on use case

  • Public deployment:
    • highly recommended setting an API key
    • explicit --cors-origins is optional
    • using llama-server behind a reverse proxy to mitigate DoS-related issues
  • Local (trusted) network deployment:
    • recommend explicitly set --cors-origins to origin server address
  • Local deployment (same machine):
    • recommend setting --cors-origins localhost (auto set via --agent)

Requirements

@ngxson
ngxson marked this pull request as ready for review July 14, 2026 11:07
@ngxson
ngxson requested review from a team as code owners July 14, 2026 11:07
@ServeurpersoCom

Copy link
Copy Markdown
Contributor

Memo to myself: I'm going to test/merge this one

@pwilkin

pwilkin commented Jul 14, 2026

Copy link
Copy Markdown
Member

@ngxson Definitely should have a separate documentation section in the server notes, at least with what you just wrote in the PR description.

@ServeurpersoCom ServeurpersoCom self-assigned this Jul 14, 2026
@ServeurpersoCom

ServeurpersoCom commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

@ngxson Definitely should have a separate documentation section in the server notes, at least with what you just wrote in the PR description.

I think I can commit to the branch if you approve this proposal, @pwilkin?

doc proposal :

diff --git a/tools/server/README.md b/tools/server/README.md
index 9c8b32dcc..84132b5d7 100644
--- a/tools/server/README.md
+++ b/tools/server/README.md
@@ -329,6 +329,22 @@ The server includes a set of built-in tools that enable the LLM to access the lo

 To use this feature, start the server with `--tools all`. You can also enable only specific tools by passing a comma-separated list: `--tools name1,name2,...`. Run `--help` for the full list of available tool names.

+### CORS
+
+By default the server reflects any `Origin` header back with credentials allowed. This matches the old, always-on `*` behavior and is fine as long as the server only exposes stateless, read-only endpoints.
+
+Enabling `--tools` or `--agent` exposes file read/write over the API, so in that case `--cors-origins` defaults to `localhost` instead: only pages served from localhost can reach the server. Pass `--cors-origins` explicitly to override either default.
+
+Recommended `--cors-origins` setting, depending on where the server runs:
+
+| Deployment | Recommendation |
+| ---------- | --------------- |
+| Public | set an API key, put the server behind a reverse proxy, `--cors-origins` optional |
+| Local network | set `--cors-origins` to your frontend's origin |
+| Same machine | `--cors-origins localhost` (default once `--agent` is set) |
+
+Related flags: `--cors-origins`, `--cors-methods`, `--cors-headers`, `--cors-credentials` / `--no-cors-credentials`. Background and rationale: [#25655](https://github.com/ggml-org/llama.cpp/pull/25655).
+
 ## Build

 `llama-server` is built alongside everything else from the root of the project

CORS

By default the server reflects any Origin header back with credentials allowed. This matches the old, always-on * behavior and is fine as long as the server only exposes stateless, read-only endpoints.

Enabling --tools or --agent exposes file read/write over the API, so in that case --cors-origins defaults to localhost instead: only pages served from localhost can reach the server. Pass --cors-origins explicitly to override either default.

Recommended --cors-origins setting, depending on where the server runs:

Deployment Recommendation
Public set an API key, put the server behind a reverse proxy, --cors-origins optional
Local network set --cors-origins to your frontend's origin
Same machine --cors-origins localhost (default once --agent is set)

Related flags: --cors-origins, --cors-methods, --cors-headers, --cors-credentials / --no-cors-credentials. Background and rationale: #25655.

@ServeurpersoCom ServeurpersoCom left a comment

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.

LGTM

What's I tested :

  • default (*, credentials) behavior unchanged, startup warning fires

  • --agent / --tools switches default to localhost, explicit override works

  • reflects localhost / 127.0.0.1 / [::1], rejects everything else

  • /cors-proxy forwards only explicit proxy headers

  • test_security.py: 17/17 passed

  • adversarial: null origin, subdomain suffix, decimal/mapped IP, case, trailing dot all rejected

  • minor: "http://evil.com@localhost" accepted, host correctly parses as localhost per URL syntax, not exploitable: browsers never put userinfo in the Origin header (RFC 6454), no real request can carry this value

@ServeurpersoCom
ServeurpersoCom merged commit 6e52db5 into master Jul 14, 2026
30 of 31 checks passed
fewtarius added a commit to fewtarius/CachyLLama that referenced this pull request Jul 19, 2026
…, OpenCL Q6_K/Adreno, CORS, checkpoint min-step, prompt cache refactor, MoE expert API stays)

Upstream highlights since 6be7459:
- model: DFlash speculative with KV rotation (ggml-org#25823)
- model: Hy3 (hy_v3) with MTP speculative decoding (ggml-org#25395)
- model: DeepseekV4 with fused hyper-connection ops (ggml-org#25585)
- ggml: 0.17.0, LIGHTNING_INDEXER, out_prod, f16 set_rows
- vulkan: Q2_0 support, native e2m1/e4m3 conversions, transfer-queue race fix
- CUDA: MMQ kernel config refactor (ggml-org#24127), tighter MMQ src1 buffer for fp4 (ggml-org#25613), CUDA graphs on Volta/Turing, MoE gate/up dedup, CUDA Virtual Devices
- ROCm: hexagon L2 cache rework, native fp4, FP16/INT8 coopmat on AMD
- SYCL: Battlemage flash attention via oneDNN XMX, XIELU op, fp16 conv2d_dw
- OpenCL: Q6_K GEMM/GEMV fix, ragged-tile MoE prefill FP16, Adreno vectorized LD/ST, A7x optimizations, ABS op
- kleidiai: SME2 f32 kernel, SME vs SME2 dispatch
- server: refactor prompt cache state ownership (ggml-org#25649) - new server_prompt_cache_state separates prompt metadata from KV data
- server: evict checkpoints within min-step (ggml-org#25472)
- server: text-only slot save/restore with mtmd (ggml-org#25076)
- server: --cors-* options (ggml-org#25655)
- server: refactored server_stream (ggml-org#25541)
- server: respect min-step when splitting prompt batches (ggml-org#25420)
- server: move chat-template thinking probe inside init try/catch (ggml-org#24093)
- common: auto-download dflash/eagle3 HF sidecars (ggml-org#25811), drop --stdin mutual-exclusion, align tokenize usage
- conversion: BitNetForCausalLM, dflash tokenizer fix, split MTP export for HY V3
- llama-quant: exclude i32 ffn_gate_tid2eid routing table, allow manual tensor types with --pure
- llama-batch: fix allowed decreasing pos in a seq (ggml-org#25449), n_keep_tail in split_equal for recurrent
- llama: refactor fused ops (ggml-org#24646), TP fix for Phi3/Bert/Plamo2/3/ChatGLM
- ui: agentic content UX, reasoning effort on mobile add sheet, MCP panel fixes, thinking menu fix
- vendor: BoringSSL 0.20250713.0
- tests: actually exercise test-recurrent-state-rollback, ds_v4_hc sentinel init, export-graph-ops graceful exit

CachyLLama preservation work (conflict resolution):

1. tools/server/server-task.h: Accept upstream's server_prompt refactor (no data member, clear() method).
   Move our t_last_used field from server_prompt to server_prompt_cache_state (where it now lives
   after the refactor). server_prompt_cache_state already has the size() method, so our old
   size() on server_prompt is no longer needed.

2. tools/server/server-context.cpp (create_checkpoint): Take upstream's min-step eviction
   pre-filter as the FIRST pass, then keep our existing highest-pos_min eviction as the
   capacity overflow fallback. These are complementary: min-step removes redundant checkpoints
   from the same task; highest-pos_min keeps the rec-window-friendly checkpoints when at cap.

3. tools/server/server-context.cpp (handle_completions_impl): Keep our std::vector<server_task>
   tasks batching for multi-prompt requests and per-user concurrency check, AND take upstream's
   res->set_req(&req) for spipe ownership transfer.

4. tools/server/server-task.cpp: Fix references to entry.tokens -> entry.prompt.tokens,
   entry.checkpoints -> entry.prompt.checkpoints, entry.n_tokens() -> entry.prompt.n_tokens().
   Update find_eviction_candidate return type from list<server_prompt>::iterator to
   list<server_prompt_cache_state>::iterator.

5. ggml/src/ggml-cuda/mmq.cuh + new mmq-config-rdna3_5.cuh: Upstream's massive MMQ refactor
   moved per-architecture config into separate files but did NOT add RDNA3.5 (gfx1150/1/2/3,
   Strix Halo). Create mmq-config-rdna3_5.cuh (231 CASE entries) derived from rdna2 with
   nthreads=128 (4 warps) and I=48 (smaller X tile) matching our original Strix Halo tuning.
   Wire into both host and device dispatch paths before the RDNA4 / RDNA2 fallback.

6. README.md and AGENTS.md: Keep CachyLLama-specific links and project context where upstream
   added parallel content.

Verified:
- cmake --build builds clean (Release, CPU-only)
- llama-server starts, --help shows all CachyLLama flags preserved:
  --cache-ssd-hot-ram, --cache-ssd-warm-ram, --cache-ssd-system-prompts,
  --cache-ssd-system-max-days, --cache-ssd-no-fsync, --cache-ssd-max-conversations,
  --max-concurrent-per-user
- /expert-stats and /expert-tracking endpoints preserved
- 55/58 tests pass; 3 failures unrelated to merge:
  - test-tokenizers-ggml-vocabs: missing model downloads
  - test-jinja-py: missing jinja2 Python module
  - test-quant-type-selection: snapshot mismatch on upstream's new MXFP4_MOE heuristic

Custom CachyLLama files untouched (no upstream conflicts):
- common/kv-ssd-cache.{cpp,h}, common/kv-ssd-posix.h, common/kv-ssd-system-cache.{cpp,h}
- common/kv_page_manager.{cpp,h}
- tools/server/server-context-page-manager.{cpp,h}
- tools/server/server-context-ssd-cache.{cpp,h}
- test_kv_page_manager.cpp, tests/test-ssd-cache-caps.cpp
- STRIX_HALO_NOTES.md, docs/development/user-isolation-design.md
- .github/workflows/build-cpu.yml, build-cuda-windows.yml, build-vulkan.yml
CowboyTim pushed a commit to aardbeiplantje/llama.cpp that referenced this pull request Jul 21, 2026
* server: add --cors-* options

* add special "localhost" value

* add tests

* fix test

* add link to PR
@imnecho imnecho mentioned this pull request Aug 2, 2026
smalinin pushed a commit to smalinin/llama.cpp that referenced this pull request Aug 4, 2026
* server: add --cors-* options

* add special "localhost" value

* add tests

* fix test

* add link to PR
satindergrewal pushed a commit to satindergrewal/llama.cpp that referenced this pull request Aug 12, 2026
* server: add --cors-* options

* add special "localhost" value

* add tests

* fix test

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants