📝 docs(security): address Copilot findings on SECURITY-MODEL.md + README (#8207)#8223
Conversation
…DME (#8207) Fixes #8207 Addresses all 6 Copilot review comments from PR #8203 (security docs bundle). Verified each claim against source before applying: - Verified InitializeProviders (pkg/agent/registry.go:283) registers only CLI-based tool agents and explicitly excludes API-key HTTP providers (claude/openai/gemini/groq/openrouter/open-webui). - Verified update_checker.go lives in pkg/agent/ (local kc-agent), not in the Go backend server pod. - Verified DEV_MODE is read in cmd/kc-agent/main.go:18 while KC_DEV_MODE=1 is only used in pkg/agent/server_http.go:2202 for the backend-driven agent restart path. Changes: 1. README.md (finding #1): The "security model" paragraph no longer claims users can point an OpenAI-compatible local LLM at kc-agent via GROQ_BASE_URL / OPENROUTER_BASE_URL / OPEN_WEBUI_URL today. Reframed as a planned follow-up; currently supported path is the CLI-based agents. 2. SECURITY-MODEL.md §1 data flow (finding #2): Replaced the single-sentence "Key consequence" block with the two-path distinction (CLI tool agents vs direct HTTP providers). Notes that CLI agents can exfiltrate cluster data indirectly via kubectl/helm tool output; direct HTTP providers are not registered at runtime today. 3. SECURITY-MODEL.md §2 Posture B (finding #3): Rewrote the restricted-egress section to match runtime reality. AI gating is by registered CLI agent availability, not by API-key env vars. Setting *_API_KEY does not by itself enable AI. Settings → API Keys modal documented as non-operative. 4. SECURITY-MODEL.md §1 "leaves the cluster" (finding #5): Corrected the update_checker.go reference. The local kc-agent (not the backend pod) performs any GitHub update polling. In-cluster backend deployments do not poll GitHub from the server pod. 5. SECURITY-MODEL.md §3 Local/Self-hosted LLMs (finding #4): Added a prominent "current registration status" subsection stating that Groq/OpenRouter/Open WebUI provider implementations exist but are NOT registered by InitializeProviders. Relabeled the Ollama / vLLM / LM Studio / internal-gateway recipes as "planned follow-up" (not operative today). Base-URL env vars noted as "parsed, not wired". Retained the mermaid diagrams from PR #8206 and framed them as the intended direction. 6. SECURITY-MODEL.md §4 env var cheat sheet (finding #6): Split the KC_DEV_MODE row into two entries — DEV_MODE (general kc-agent dev/logging toggle, read in cmd/kc-agent/main.go) and KC_DEV_MODE (backend-driven restart/dev path in pkg/agent/server_http.go) — so operators don't set the wrong variable. Docs-only change. web build + lint pass. Signed-off-by: Andy Anderson <[email protected]>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
✅ Deploy Preview for kubestellarconsole ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
👋 Hey @clubanderson — thanks for opening this PR!
This is an automated message. |
There was a problem hiding this comment.
Pull request overview
Docs-only follow-up to #8203/#8206 that corrects security-model wording to match current kc-agent runtime behavior (CLI-agent-only registration, update checks running locally, and DEV_MODE vs KC_DEV_MODE).
Changes:
- Clarifies AI egress paths by separating CLI tool agents vs direct HTTP providers, and documents that HTTP providers aren’t selectable at runtime today.
- Corrects “what leaves the cluster” to reflect that update checks run in the local kc-agent (not the in-cluster backend pod).
- Updates Posture B guidance and the env-var cheat sheet (DEV_MODE vs KC_DEV_MODE).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| docs/security/SECURITY-MODEL.md | Aligns security/egress/provider claims with current provider registry behavior and update-check location; refines env-var guidance. |
| README.md | Rewords the security-model link paragraph to avoid implying local LLM base-URL overrides are supported today. |
| ### Important: current registration status | ||
|
|
||
| The provider implementations for **Groq**, **OpenRouter**, and **Open WebUI** (and the other API-key HTTP providers such as Claude API, OpenAI, and Gemini) exist in `pkg/agent/provider_*.go`, **but they are not registered by `InitializeProviders`** in the current build. They are explicitly excluded as "API-only agents" (see `pkg/agent/registry.go:303-307`) because the active runtime registry only registers CLI-based tool-capable agents (`claude-code`, `bob`, `codex`, `gemini-cli`, `antigravity`, `goose`, `copilot-cli`). As a result, **these HTTP providers cannot currently be selected via the runtime provider registry**, and their `*_BASE_URL` environment variables are parsed by the provider source files but are **not** wired into a selectable provider at runtime. | ||
|
|
||
| The currently supported self-hosted path is therefore the CLI tool-agent path: install one of the supported local CLIs (for example `claude-code`, `codex`, or `gemini-cli`) on the machine that runs kc-agent, and it will be picked up by `InitializeProviders`. | ||
|
|
||
| | Provider | `provider` name | API key env var | Model env var | Base URL overridable? | Base URL env var | Source | | ||
| ### Provider source files and env vars (reference) | ||
|
|
||
| The table below documents the provider implementations that exist in the source tree and the env vars they parse. Rows marked "Registered?" as **no** are not currently selectable at runtime. | ||
|
|
||
| | Provider | `provider` name | API key env var | Model env var | Base URL env var | Registered? | Source | | ||
| |---|---|---|---|---|---|---| | ||
| | Anthropic Claude | `claude` / `anthropic` | `ANTHROPIC_API_KEY` | `CLAUDE_MODEL` | no (fixed to Anthropic) | — | `pkg/agent/provider_claude.go` | | ||
| | OpenAI (ChatGPT) | `openai` | `OPENAI_API_KEY` | `OPENAI_MODEL` | no (fixed to `api.openai.com`) | — | `pkg/agent/provider_openai.go:15` | | ||
| | Google Gemini | `gemini` / `google` | `GOOGLE_API_KEY` | `GEMINI_MODEL` | no | — | `pkg/agent/provider_gemini.go:15` | | ||
| | Groq (OpenAI-compatible) | `groq` | `GROQ_API_KEY` | `GROQ_MODEL` | **yes** | `GROQ_BASE_URL` | `pkg/agent/provider_groq.go:22-51` | | ||
| | OpenRouter (OpenAI-compatible) | `openrouter` | `OPENROUTER_API_KEY` | `OPENROUTER_MODEL` | **yes** | `OPENROUTER_BASE_URL` | `pkg/agent/provider_openrouter.go:23-58` | | ||
| | Open WebUI (OpenAI-compatible) | `open-webui` | `OPEN_WEBUI_API_KEY` | `OPEN_WEBUI_MODEL` | **yes** | `OPEN_WEBUI_URL` | `pkg/agent/provider_openwebui.go:16,39` | | ||
| | Anthropic Claude (HTTP) | `claude` / `anthropic` | `ANTHROPIC_API_KEY` | `CLAUDE_MODEL` | — | no | `pkg/agent/provider_claude.go` | | ||
| | OpenAI (ChatGPT, HTTP) | `openai` | `OPENAI_API_KEY` | `OPENAI_MODEL` | — | no | `pkg/agent/provider_openai.go:15` | | ||
| | Google Gemini (HTTP) | `gemini` / `google` | `GOOGLE_API_KEY` | `GEMINI_MODEL` | — | no | `pkg/agent/provider_gemini.go:15` | | ||
| | Groq (OpenAI-compatible, HTTP) | `groq` | `GROQ_API_KEY` | `GROQ_MODEL` | `GROQ_BASE_URL` (parsed, not wired) | no | `pkg/agent/provider_groq.go:22-51` | | ||
| | OpenRouter (OpenAI-compatible, HTTP) | `openrouter` | `OPENROUTER_API_KEY` | `OPENROUTER_MODEL` | `OPENROUTER_BASE_URL` (parsed, not wired) | no | `pkg/agent/provider_openrouter.go:23-58` | | ||
| | Open WebUI (OpenAI-compatible, HTTP) | `open-webui` | `OPEN_WEBUI_API_KEY` | `OPEN_WEBUI_MODEL` | `OPEN_WEBUI_URL` (parsed, not wired) | no | `pkg/agent/provider_openwebui.go:16,39` | | ||
|
|
||
| Note the asymmetry: the upstream OpenAI provider source file hard-codes its hostname as a package-level variable in `pkg/agent/provider_openai.go:15` (no `OPENAI_BASE_URL` override). Groq, OpenRouter, and Open WebUI do parse base-URL env vars, but because those providers are not registered at runtime today, setting those env vars does not actually route AI traffic through a local endpoint. | ||
|
|
||
| ### Planned follow-up: wire up OpenAI-compatible local LLMs | ||
|
|
||
| Note the asymmetry: **the upstream OpenAI provider does not currently honor an `OPENAI_BASE_URL` override.** The hostname is a package-level variable in `pkg/agent/provider_openai.go:15`, but it is not re-read from the environment. If you want to point an OpenAI-compatible local server at the console today, use one of the three providers whose base URLs *are* overridable: **Groq, OpenRouter, or Open WebUI**. All three speak the OpenAI chat-completions wire format. | ||
| The diagrams and examples below describe the **planned** configuration shape once the base-URL-overridable HTTP providers are registered in `InitializeProviders`. They are **not operative in the current build** — treat them as forward-looking documentation. If/when the providers are wired in, this section will be promoted back to a supported recipe. | ||
|
|
There was a problem hiding this comment.
This “current registration status / planned follow-up” section now documents that the OpenAI-compatible HTTP providers (Groq/OpenRouter/Open WebUI) are not selectable at runtime, but the document’s opening summary still states local/self-hosted LLMs are supported “Yes, via” those providers. Please update the earlier summary/question phrasing to match the new reality (planned/not yet wired) to avoid a contradictory “supported today” impression.
| | `KC_AGENT_TOKEN` | kc-agent | Optional shared secret for browser→agent auth | | ||
| | `KC_ALLOWED_ORIGINS` | kc-agent | Extra allowed origins (comma-separated) | | ||
| | `KC_DEV_MODE` | kc-agent | Development mode toggle (`1` to enable) | | ||
| | `DEV_MODE` | kc-agent | General kc-agent development/logging mode toggle | |
There was a problem hiding this comment.
The cheat sheet lists DEV_MODE as a generic kc-agent dev/logging toggle but doesn’t document the expected value. In cmd/kc-agent/main.go, the toggle is os.Getenv("DEV_MODE") == "true" (not 1). Please note the required value (e.g., DEV_MODE=true) to prevent operators from setting DEV_MODE=1 and expecting it to work.
| | `DEV_MODE` | kc-agent | General kc-agent development/logging mode toggle | | |
| | `DEV_MODE` | kc-agent | General kc-agent development/logging mode toggle; set `DEV_MODE=true` to enable (the code checks for the literal string `true`) | |
| Key consequence: **the kubeconfig, raw secrets, and cluster credentials never cross the process boundary from kc-agent.** The only thing kc-agent sends outward is the HTTP chat payload to the configured AI provider, which contains the conversation the user has been having (system prompt + message history + current prompt — see `pkg/agent/provider_openai.go:207-238` for the exact OpenAI shape). | ||
| Key consequence: **the kubeconfig, raw secrets, and cluster credentials never cross the process boundary from kc-agent as direct credential uploads.** However, the data that can leave the machine depends on which kind of AI agent is configured: | ||
|
|
||
| - **CLI tool agents** (for example `claude-code`, `codex`, `gemini-cli`) run an external CLI locally. These agents can execute tools such as `kubectl` and `helm`, and the external CLI may send tool output or other cluster-derived context to its upstream LLM depending on the agent's behavior and the prompt. In the current build, `InitializeProviders` (`pkg/agent/registry.go:283`) registers **only** CLI-based tool-capable agents — `claude-code`, `bob`, `codex`, `gemini-cli`, `antigravity`, `goose`, and `copilot-cli`. |
There was a problem hiding this comment.
The “CLI tool agents” paragraph describes all registered agents as tool-capable (“can execute tools such as kubectl and helm”) and includes antigravity in the list of “tool-capable agents”. In code, AntigravityProvider.Capabilities() returns CapabilityChat only (no tool execution), so this overstates capabilities and could mislead operators about what data can be pulled via tools. Please either remove antigravity from the tool-capable list or qualify it as chat-only / non-tool-executing, and scope the kubectl/helm statement to agents that actually have CapabilityToolExec.
| - **CLI tool agents** (for example `claude-code`, `codex`, `gemini-cli`) run an external CLI locally. These agents can execute tools such as `kubectl` and `helm`, and the external CLI may send tool output or other cluster-derived context to its upstream LLM depending on the agent's behavior and the prompt. In the current build, `InitializeProviders` (`pkg/agent/registry.go:283`) registers **only** CLI-based tool-capable agents — `claude-code`, `bob`, `codex`, `gemini-cli`, `antigravity`, `goose`, and `copilot-cli`. | |
| - **CLI-based agents** run an external CLI locally. For the registered agents that have tool-execution capability (for example `claude-code`, `bob`, `codex`, `gemini-cli`, `goose`, and `copilot-cli`), the agent can execute tools such as `kubectl` and `helm`, and the external CLI may send tool output or other cluster-derived context to its upstream LLM depending on the agent's behavior and the prompt. In the current build, `InitializeProviders` (`pkg/agent/registry.go:283`) registers those CLI-based tool-capable agents, and also registers `antigravity`, which is CLI-based but chat-only / non-tool-executing. |
| ### Supported providers and env vars | ||
| ### Important: current registration status | ||
|
|
||
| The provider implementations for **Groq**, **OpenRouter**, and **Open WebUI** (and the other API-key HTTP providers such as Claude API, OpenAI, and Gemini) exist in `pkg/agent/provider_*.go`, **but they are not registered by `InitializeProviders`** in the current build. They are explicitly excluded as "API-only agents" (see `pkg/agent/registry.go:303-307`) because the active runtime registry only registers CLI-based tool-capable agents (`claude-code`, `bob`, `codex`, `gemini-cli`, `antigravity`, `goose`, `copilot-cli`). As a result, **these HTTP providers cannot currently be selected via the runtime provider registry**, and their `*_BASE_URL` environment variables are parsed by the provider source files but are **not** wired into a selectable provider at runtime. |
There was a problem hiding this comment.
This section says Groq/OpenRouter/Open WebUI are “explicitly excluded as "API-only agents" (see pkg/agent/registry.go:303-307)”. That comment only names Claude API/OpenAI/Gemini and IDE agents; it doesn’t mention Groq/OpenRouter/Open WebUI. Since they’re simply not registered today (no registry.Register(NewGroqProvider()), etc.), please reword to avoid claiming the registry comment explicitly excludes those providers, or add a more accurate citation/wording (e.g., “not registered by InitializeProviders”).
| The provider implementations for **Groq**, **OpenRouter**, and **Open WebUI** (and the other API-key HTTP providers such as Claude API, OpenAI, and Gemini) exist in `pkg/agent/provider_*.go`, **but they are not registered by `InitializeProviders`** in the current build. They are explicitly excluded as "API-only agents" (see `pkg/agent/registry.go:303-307`) because the active runtime registry only registers CLI-based tool-capable agents (`claude-code`, `bob`, `codex`, `gemini-cli`, `antigravity`, `goose`, `copilot-cli`). As a result, **these HTTP providers cannot currently be selected via the runtime provider registry**, and their `*_BASE_URL` environment variables are parsed by the provider source files but are **not** wired into a selectable provider at runtime. | |
| The provider implementations for **Groq**, **OpenRouter**, and **Open WebUI** (and the other API-key HTTP providers such as Claude API, OpenAI, and Gemini) exist in `pkg/agent/provider_*.go`, **but they are not registered by `InitializeProviders`** in the current build. The active runtime registry currently registers only CLI-based tool-capable agents (`claude-code`, `bob`, `codex`, `gemini-cli`, `antigravity`, `goose`, `copilot-cli`; see `pkg/agent/registry.go:303-307`). As a result, **these HTTP providers cannot currently be selected via the runtime provider registry**, and their `*_BASE_URL` environment variables are parsed by the provider source files but are **not** wired into a selectable provider at runtime. |
|
Thank you for your contribution! Your PR has been merged. Check out what's new:
Stay connected: Slack #kubestellar-dev | Multi-Cluster Survey |
|
Post-merge build verification passed ✅ Both Go and frontend builds compiled successfully against merge commit |
Fixes #8207
Addresses all 6 Copilot review comments from the merged security docs bundle (PR #8203). Each claim was verified against source before applying.
Verifications run
grep -n "InitializeProviders\|RegisterProvider" pkg/agent/*.go→ confirmedInitializeProviders(pkg/agent/registry.go:283) registers only CLI-based tool agents (claude-code,bob,codex,gemini-cli,antigravity,goose,copilot-cli) and explicitly excludes API-only HTTP providers atpkg/agent/registry.go:303-307.find . -name update_checker.go→ lives atpkg/agent/update_checker.go(local kc-agent), not in the Go backend.grep -n "DEV_MODE\|KC_DEV_MODE"→DEV_MODEis read incmd/kc-agent/main.go:18(general kc-agent dev/logging toggle);KC_DEV_MODE=1is read only inpkg/agent/server_http.go:2202for the backend-driven agent restart path.Findings addressed
README.md:174 — OpenAI-compatible local LLM claim. Reframed the "security model" paragraph so it no longer implies
GROQ_BASE_URL/OPENROUTER_BASE_URL/OPEN_WEBUI_URLenable a selectable provider today. Marked as a planned follow-up. Points readers at the currently supported CLI-based agent path.SECURITY-MODEL.md §1 data flow (~line 108) — CLI vs HTTP distinction. Replaced the "Key consequence" block with a two-path description: CLI tool agents (which execute
kubectl/helmlocally and may forward tool output upstream) vs direct HTTP providers (where the request body is built inpkg/agent/provider_*.go). Notes that API-only HTTP providers are not registered at runtime today.SECURITY-MODEL.md §2 Posture B (~line 142) — AI gating condition. Rewrote the restricted-egress section to match runtime reality: AI is gated by registered CLI agent availability, not by API-key env vars.
*_API_KEYvars do not by themselves enable AI. Settings → API Keys modal treated as non-operative for current runtime enablement.SECURITY-MODEL.md §1 "what leaves the cluster" (~line 122) — update_checker.go location. Corrected the reference: the local kc-agent (
pkg/agent/update_checker.go) performs GitHub update polling, not the in-cluster backend pod. Separated the GitHub OAuth call site from the update-check call site in the bullet list.SECURITY-MODEL.md §3 Local / Self-Hosted LLMs (~line 184) — "supported" claim. Added a prominent "Current registration status" subsection stating that Groq/OpenRouter/Open WebUI (and Claude API/OpenAI/Gemini) provider implementations exist in
pkg/agent/provider_*.gobut are not registered byInitializeProviders. Base-URL env vars relabeled as "parsed, not wired". Moved the Ollama / vLLM / LM Studio / internal-gateway recipes under a "Planned follow-up" subsection and annotated every code block with# PLANNED — not yet wired at runtime. Preserved the mermaid diagrams added in PR 📝 docs(security): add mermaid diagrams to SECURITY-MODEL.md #8206.SECURITY-MODEL.md §4 env var cheat sheet (~line 264) — DEV_MODE vs KC_DEV_MODE. Split the single
KC_DEV_MODErow into two:DEV_MODE(general kc-agent dev/logging) andKC_DEV_MODE(backend-driven restart path) so operators don't set the wrong variable.Notes
web/ npm run buildandweb/ npm run lintboth pass locally.🤖 Generated with Claude Code