Skip to content

fix(integrations): warn when bearer auth crosses plaintext HTTP to non-loopback#315

Merged
rohitg00 merged 2 commits into
rohitg00:mainfrom
mvanhorn:fix/275-plugin-plaintext-http
May 13, 2026
Merged

fix(integrations): warn when bearer auth crosses plaintext HTTP to non-loopback#315
rohitg00 merged 2 commits into
rohitg00:mainfrom
mvanhorn:fix/275-plugin-plaintext-http

Conversation

@mvanhorn
Copy link
Copy Markdown
Contributor

@mvanhorn mvanhorn commented May 12, 2026

Summary

Each of the three plugin clients now warns once when a bearer token would be sent over plaintext HTTP to a non-loopback host. Loopback HTTP stays silent (it's not actually wire-exposed). HTTPS stays silent. An opt-in AGENTMEMORY_REQUIRE_HTTPS=1 env var turns the warning into a startup error for users who want a guarantee.

What changed

  • integrations/openclaw/plugin.mjs: HTTP + non-loopback + secret -> one-time console.warn. Hard-fail when AGENTMEMORY_REQUIRE_HTTPS=1.
  • integrations/pi/index.ts + new integrations/pi/security.ts: same guard, factored into a small module so the test can target it directly.
  • integrations/hermes/__init__.py: same guard using warnings.warn + RuntimeError for the hard-fail path.
  • test/integration-plaintext-http.test.ts: covers loopback silence, remote HTTP warning fires once, HTTPS silence, hard-fail when env is set.

Default behavior is unchanged. The warning fires only when the configuration is actually dangerous (HTTP + non-loopback + secret).

Why not raise by default

http://localhost:3111 is the documented default and is loopback-only — the kernel routes those packets without touching any NIC. Hard-failing every plaintext-localhost user would break the install flow for no security gain.

Testing

  • node --check on the modified .mjs file
  • python3 -m py_compile on the modified Python plugin
  • Targeted smoke checks on each plugin's auth path
  • npm test couldn't run locally because vitest isn't in the sandbox; the new test follows the existing test/*.test.ts shape, CI/CodeRabbit will exercise it

Fixes #275

Signed-off-by: Matt Van Horn mvanhorn@gmail.com

Summary by CodeRabbit

  • New Features

    • Plaintext HTTP Bearer-token safety checks added across integrations: loopback hosts bypass, remote HTTP emits a one-time warning to stderr or raises when AGENTMEMORY_REQUIRE_HTTPS=1; enforcement runs at initialization and before requests.
  • Tests

    • Added integration tests covering loopback, remote, HTTPS, warn-once, and fail-on-require semantics across integrations.
  • Documentation

    • READMEs updated to document AGENTMEMORY_REQUIRE_HTTPS behavior.
  • Chore

    • .gitignore updated to ignore Python bytecode cache.

Review Change Stack

@vercel
Copy link
Copy Markdown

vercel Bot commented May 12, 2026

@mvanhorn is attempting to deploy a commit to the rohitg00's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 26dba448-eecd-45ae-ab57-a758ac083bd2

📥 Commits

Reviewing files that changed from the base of the PR and between 80f5580 and 9875c3d.

📒 Files selected for processing (8)
  • .gitignore
  • integrations/hermes/README.md
  • integrations/hermes/__init__.py
  • integrations/openclaw/plugin.mjs
  • integrations/pi/README.md
  • integrations/pi/index.ts
  • integrations/pi/security.ts
  • test/integration-plaintext-http.test.ts
✅ Files skipped from review due to trivial changes (3)
  • integrations/pi/README.md
  • .gitignore
  • integrations/hermes/README.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • integrations/openclaw/plugin.mjs
  • integrations/pi/index.ts
  • integrations/pi/security.ts
  • integrations/hermes/init.py

📝 Walkthrough

Walkthrough

This PR adds plaintext-HTTP Bearer token safety detection and enforcement across Pi (TypeScript), OpenClaw (JavaScript), and Hermes (Python). When AGENTMEMORY_SECRET would be sent over plaintext HTTP to non-loopback hosts, the code warns once or raises an error if AGENTMEMORY_REQUIRE_HTTPS=1. Tests and docs are updated accordingly.

Changes

Plaintext Bearer Auth Safety Guards

Layer / File(s) Summary
Pi security module: detection and guard factory
integrations/pi/security.ts
Exports usesPlaintextBearerAuth, plaintextBearerAuthMessage, and createPlaintextBearerAuthGuard that warns once or throws when HTTPS is required.
Pi integration: apply guard in callAgentMemory and init
integrations/pi/index.ts
Imports guard factory, creates module-scoped guard, invokes it during callAgentMemory and at initialization when AGENTMEMORY_REQUIRE_HTTPS === "1".
OpenClaw integration: plaintext bearer guard in plugin
integrations/openclaw/plugin.mjs
Adds loopback allowlist, hostname normalization, exports createPlaintextBearerAuthGuard(warn, env), and wires it into createClient and each postJson call.
Hermes integration: plaintext bearer guard in Python module
integrations/hermes/__init__.py
Adds sys import, LOOPBACK_HOSTS and _plaintext_bearer_warned, detection/guard helpers, test reset, and guard calls in _api and AgentMemoryProvider.initialize.
Comprehensive test suite for all three integrations
test/integration-plaintext-http.test.ts
Adds tests covering loopback/HTTPS silence, remote HTTP warn-once, IPv6 and RFC1918 cases, empty-secret behavior, and early throw when AGENTMEMORY_REQUIRE_HTTPS is set.
Docs and gitignore
.gitignore, integrations/hermes/README.md, integrations/pi/README.md
Adds integrations/hermes/__pycache__/ to .gitignore and documents AGENTMEMORY_REQUIRE_HTTPS in integration READMEs.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • rohitg00/agentmemory#107: Adds the Hermes AgentMemory provider module that this PR extends with plaintext-bearer HTTP safety guards.

Poem

🐰 I hop through code to guard the key,
Loopback safe, but remote I see,
Warn once gently or force a lock,
HTTPS now keeps secrets on the dock,
Three plugins checked — a snug little spree.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 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: adding warnings when bearer auth is sent over plaintext HTTP to non-loopback hosts across multiple integrations.
Linked Issues check ✅ Passed The PR implements comprehensive guards against plaintext HTTP bearer auth in all three integrations [#275], with warn-once behavior and optional enforcement via AGENTMEMORY_REQUIRE_HTTPS.
Out of Scope Changes check ✅ Passed All changes directly address issue #275: security guards for plaintext HTTP, updated documentation, test coverage, and .gitignore update are all within scope.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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 `@test/integration-plaintext-http.test.ts`:
- Line 7: Update the test import to match the ES module extension convention:
replace the import of createPlaintextBearerAuthGuard from
"../integrations/pi/security.ts" with "../integrations/pi/security.js" so the
test uses the same `.js` import convention as the source (ensure the imported
symbol createPlaintextBearerAuthGuard remains unchanged).
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1e0da6aa-1900-41d9-aebe-17a4567293fb

📥 Commits

Reviewing files that changed from the base of the PR and between 48b11e8 and 80f5580.

📒 Files selected for processing (5)
  • integrations/hermes/__init__.py
  • integrations/openclaw/plugin.mjs
  • integrations/pi/index.ts
  • integrations/pi/security.ts
  • test/integration-plaintext-http.test.ts

Comment thread test/integration-plaintext-http.test.ts
mvanhorn and others added 2 commits May 13, 2026 15:44
…n-loopback (rohitg00#275)

Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
…alike hostnames + docs

@mvanhorn's PR rohitg00#315 lands the right plaintext-bearer-auth warn-once
pattern across three runtimes (hermes/python, openclaw/mjs,
pi/typescript). Reviewed cleanly. Adding test cases + docs before
merge so the contract is locked:

Test additions (test/integration-plaintext-http.test.ts pi suite,
+4 cases, 13 total in suite):

- IPv6 loopback (http://[::1]:3111) — URL parser strips brackets,
  hostname comes back as `::1`, the LOOPBACK_HOSTS set already covers
  this. Test pins the parsing semantic so a future refactor can't
  silently break it.

- Private LAN IPs (RFC1918 ranges 192.168.x.y, 10.x.x.x) — NOT
  loopback, guard MUST warn. RFC1918 was a deliberate design choice
  (loopback set stays minimal: localhost / 127.0.0.1 / ::1). LAN
  deployment behind a tunnel still leaks the bearer over the wire.

- No-secret short-circuit (guard with secret="" or undefined) — guard
  never fires when a bearer wouldn't actually be sent. Mirrors the
  usesPlaintextBearerAuth() early-return.

- Lookalike hostname (http://localhost.evil.com:3111) — `parsed.hostname`
  returns the full `localhost.evil.com` string, which is NOT in
  LOOPBACK_HOSTS. Guard warns. This pins the exact-match (vs prefix)
  loopback semantic.

Docs additions:

- integrations/pi/README.md and integrations/hermes/README.md now
  document AGENTMEMORY_REQUIRE_HTTPS in the env-vars table — same row
  shape as AGENTMEMORY_SECRET, names the env value (=1), describes the
  warn-vs-throw semantic, and lists the loopback hostnames the guard
  recognises.

No code changes to the guard itself — it's already correct. Pre-merge
hardening only.

899 / 899 tests pass on rebased branch. Build clean.
@rohitg00 rohitg00 force-pushed the fix/275-plugin-plaintext-http branch from 80f5580 to 9875c3d Compare May 13, 2026 14:51
@rohitg00 rohitg00 merged commit 1a706ca into rohitg00:main May 13, 2026
3 checks passed
@rohitg00
Copy link
Copy Markdown
Owner

Shipped in v0.9.12 (release notes). Thanks @mvanhorn — symmetric three-runtime guard (Python / mjs / TypeScript), warn-once semantic, and the AGENTMEMORY_REQUIRE_HTTPS=1 escalation knob is exactly the right shape for hardened deployments. Hardening commits we layered before merge (IPv6 / LAN-IP / lookalike-hostname edge-case tests + env-var docs in pi/hermes README) preserved every line of your design — the guard logic itself didn't need a change.

@mvanhorn
Copy link
Copy Markdown
Contributor Author

Thanks @rohitg00 - really appreciate the merge and the extra hardening pass. The IPv6 / LAN-IP / lookalike-hostname coverage tightens the policy in exactly the gaps a single-loopback-string check would miss; good additions. Glad the env-var escape hatch landed cleanly for the hardened-deployment path.

@rohitg00
Copy link
Copy Markdown
Owner

Thanks for your contribution and whatever you do for community, I use /last30days daily.

@mvanhorn
Copy link
Copy Markdown
Contributor Author

Thanks @rohitg00, really glad /last30days is in your rotation. The bearer-over-HTTP warn was a fun one to track down; reach out anytime if there's something else useful to add on the integrations side.

@mvanhorn
Copy link
Copy Markdown
Contributor Author

@rohitg00 thanks for the merge. Warning when a bearer token would hit non-loopback plaintext HTTP is exactly the kind of polite hardening that prevents accidental exposure without breaking the dev-loop on localhost.

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.

CRITICAL: Plugin sends auth token over plaintext HTTP

2 participants