Skip to content

[AAASM-4655] 🔒 (core): Enforce non-loopback TLS guard on register endpoint#259

Merged
Chisanan232 merged 3 commits into
masterfrom
v0.0.1/AAASM-4655/register_tls_guard
Jul 15, 2026
Merged

[AAASM-4655] 🔒 (core): Enforce non-loopback TLS guard on register endpoint#259
Chisanan232 merged 3 commits into
masterfrom
v0.0.1/AAASM-4655/register_tls_guard

Conversation

@Chisanan232

@Chisanan232 Chisanan232 commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Description

resolve_gateway_grpc_endpoint (the agent-registration :50051 endpoint resolver used by the register path in assembly.py) derived a plaintext http://remotehost:50051 register target for a non-loopback gateway with no refusal — unlike the op-control path, which calls require_secure_grpc_target (transport_security.py), and unlike the go-sdk, which enforces non-loopback→TLS for all targets. The Register call carries the agent identity, so it must not travel unencrypted to a remote host by default.

This change applies the existing require_secure_grpc_target helper to the derived endpoint branch, honouring the same allow_insecure opt-out op-control uses:

  • Loopback (localhost/127.0.0.1/::1) plaintext — still allowed (documented dev default).
  • https:// (TLS) non-loopback — still allowed (carries its own TLS).
  • http:// (plaintext) non-loopback — refused with the same ValueError op-control raises, unless allow_insecure=True is passed.
  • The AA_GATEWAY_ENDPOINT explicit operator override is honoured verbatim (the channel_factory escape-hatch analogue), unchanged.

Reuses the existing helper — no TLS logic is reimplemented. Defense-in-depth / TLS parity with the op-control path and the go-sdk.

Type of Change

  • 🔧 Bug fix

Breaking Changes

Does this PR introduce any breaking changes?

  • Yes (please describe below)

Registration against a non-loopback plaintext http:// gateway now raises ValueError instead of silently registering over an unencrypted channel. This is the intended security fix — use an https:// endpoint, or pass allow_insecure=True to opt in (loopback dev / trusted-network only). Loopback and https:// behaviour is unchanged.

Related Issues

  • Related JIRA ticket: AAASM-4655
  • Related GitHub issues: #none

Testing

Describe the testing performed for this PR:

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • No tests required (explain why)

New TestResolveGatewayGrpcEndpointTlsGuard covers: loopback plaintext allowed, non-loopback plaintext allowed with allow_insecure=True, and non-loopback plaintext without opt-in raising the same secure-transport error op-control raises. The existing test_derives_host_and_substitutes_grpc_port was updated to opt in for its non-loopback plaintext case (port-substitution behaviour unchanged). Local: ruff check, ruff format, mypy agent_assembly (only pre-existing native _core/grpc-stub baseline errors), and the new/affected tests all pass.

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • Comments added for complex logic
  • Documentation updated if needed
  • All tests passing

🤖 Generated with Claude Code

https://claude.ai/code/session_01HMnPRm9T3fdrS4uNYXkzg6

Chisanan232 and others added 3 commits July 15, 2026 20:24
resolve_gateway_grpc_endpoint derived a plaintext http:// register
target for a non-loopback gateway with no refusal, unlike the op-control
path (require_secure_grpc_target) and the go-sdk. The Register call
carries the agent identity, so mirror op-control's non-loopback→TLS
contract: refuse a derived plaintext endpoint to a remote host unless
allow_insecure is set. https:// and loopback still pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HMnPRm9T3fdrS4uNYXkzg6
Cover resolve_gateway_grpc_endpoint's non-loopback TLS guard: loopback
plaintext allowed, non-loopback plaintext allowed with allow_insecure,
and non-loopback plaintext without opt-in raises the same secure-transport
error op_control raises via require_secure_grpc_target.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HMnPRm9T3fdrS4uNYXkzg6
The AAASM-4655 register-endpoint TLS guard fail-closes a plaintext http://
register channel to a non-loopback host. Existing tests that used a
non-loopback plaintext gateway as an incidental fixture now hit the guard.
Preserve each test's intent: switch remote-host fixtures to https:// (still a
non-loopback host, so the host→gRPC-port substitution stays exercised), and
assert the plaintext-warning test now fail-closes after its warning fires.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HMnPRm9T3fdrS4uNYXkzg6
@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@sonarqubecloud

Copy link
Copy Markdown

@Chisanan232

Copy link
Copy Markdown
Contributor Author

🤖 Claude Code — PR review (post CI-fix)

Verdict: ✅ Ready to approve & merge (fail-closed security fix).

1. CI: Now green — 19 SUCCESS / 7 SKIPPED / 0 FAILURE (CI Success, unit + integration, Sonar, CodeQL, pip-audit all pass).

2. Side-effect caught & corrected: the fail-closed guard initially broke 21 existing unit tests (init_registration/spawn_context/assembly) whose fixtures used a non-loopback plaintext gateway — they began raising ConfigurationError at init before reaching the behavior under test. All 21 were reconciled intent-preservingly: fixtures where transport was incidental switched to https:// (still non-loopback, so the AAASM-4547 port-substitution path stays exercised); the one test whose intent is the non-loopback-plaintext warning kept http:// and now asserts both pytest.warns and pytest.raises(ConfigurationError). No assertions deleted.

3. Scope vs AAASM-4655: covered — register endpoint resolution now refuses non-loopback plaintext by default (parity with op-control + go-sdk), regression test added. Production code unchanged at the call site — default stays fail-closed; zero-config loopback (http://localhost:7391) unaffected. 726 unit tests pass.

4. Design note (for a human decision, non-blocking): init_assembly() exposes no allow_insecure opt-in, so an operator running a remote gateway over plaintext http on a trusted network has no public-API escape hatch for the register channel (unlike op_control). Deliberately not added here (would weaken the secure default / expand scope). Worth a follow-up if that deployment is supported.

5. Front-end: N/A.

No changes requested.

@Chisanan232 Chisanan232 merged commit c0de54e into master Jul 15, 2026
26 checks passed
@Chisanan232 Chisanan232 deleted the v0.0.1/AAASM-4655/register_tls_guard branch July 15, 2026 13:17
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