Skip to content

fix(ai): never send an API key over unencrypted http (#91 item 3) - #155

Merged
Razee4315 merged 1 commit into
mainfrom
fix/https-for-remote-ai-endpoints
Jul 29, 2026
Merged

fix(ai): never send an API key over unencrypted http (#91 item 3)#155
Razee4315 merged 1 commit into
mainfrom
fix/https-for-remote-ai-endpoints

Conversation

@Razee4315

Copy link
Copy Markdown
Owner

Addresses item 3 of #91.

The hole

isValidEndpoint (aiAssist.ts) accepted http: for any host, and the Rust transport only re-checked the scheme. So an endpoint like http://api.example.com/v1/chat/completions sent the Authorization header across the network in cleartext.

The rule

The problem is the credential, not the scheme, so http stays allowed wherever there is nothing to leak:

endpoint API key set result
https:// anything yes allowed
http:// loopback yes allowed, never touches a network
http:// remote no allowed, nothing to expose
http:// remote yes refused

Deliberate deviation from the issue text

#91 asked for "allow http: only for localhost and 127.0.0.1, require https: for everything else". Implemented literally, that would break anyone running Ollama or LM Studio on another machine on their LAN over plain http, which AI-01 went out of its way to enable (routing requests through Rust exists partly so those endpoints work). The 1.0.49 changelog advertises it: "including plain-http servers on your local network."

Since those setups are keyless, there is no credential to protect, so banning them buys no security and costs real users their config. The ban is narrowed to the case the issue was actually about. Happy to tighten it to the literal rule if you would rather, it is a one-line change in endpoint_is_key_safe.

Where it is enforced

  • src-tauri/src/ai.rs is the real gate, since that is where the request leaves the app. Frontend checks are bypassable in principle; this one is not.
  • aiAssist.ts / aiChat.ts throw before calling the transport, so the key never even crosses the IPC boundary.
  • Settings, AI shows an "Insecure endpoint" pill and an inline explanation, so the user sees why rather than debugging a failed "Test connection".

Loopback detection covers localhost, RFC 6761''s *.localhost, all of 127.0.0.0/8 and ::1, so http://127.1.2.3 and http://[::1] are correctly recognised instead of only 127.0.0.1.

Verification

  • bun run build passes
  • bun run test passes, 32 files / 308 tests (6 new: 4 for endpointLeaksKey, 2 for the runAIAction guard including an assertion that the transport is never reached)
  • 3 new Rust unit tests for endpoint_is_key_safe covering https, the loopback forms, and the off-box cases
  • localhost.evil.com is covered as a test case, since a naive prefix check would treat it as local

No version bump and no release in this PR.

isValidEndpoint accepted http: for any host, and the Rust transport only
re-checked the scheme, so an endpoint like http://api.example.com sent the
Authorization header in cleartext over the network.

Refuse that request instead. The rule is about the credential, not the
scheme: http stays allowed when there is nothing to leak.

  https, any host                -> allowed
  http  + loopback host          -> allowed (never touches a network)
  http  + no API key set         -> allowed (keyless LAN model server)
  http  + remote host + API key  -> refused

Keeping keyless plain-http working is deliberate. AI-01 routed requests
through Rust specifically so a local model server on the LAN
(http://192.168.1.50:11434) would work, and blocking it here would regress
that for no security gain. Issue #91 asked for "http only for localhost",
which would have broken those users; this narrows the ban to the case the
issue was actually about, a key crossing a network in the clear.

Loopback covers localhost, RFC 6761's *.localhost, all of 127.0.0.0/8 and
::1, so 127.1.2.3 and [::1] are recognised rather than just 127.0.0.1.

Enforced in src-tauri/src/ai.rs, which is where the request actually leaves
the app; the frontend guards in aiAssist/aiChat and the Settings warning are
UX so the user sees why before hitting send.
@Razee4315
Razee4315 force-pushed the fix/https-for-remote-ai-endpoints branch from 228b54b to f370e72 Compare July 29, 2026 22:19
@Razee4315
Razee4315 merged commit 4edb859 into main Jul 29, 2026
7 checks passed
@Razee4315
Razee4315 deleted the fix/https-for-remote-ai-endpoints branch July 29, 2026 22:26
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.

1 participant