hyperledger / hyperledger/fabric-x
gRPC clients fall back to plaintext when TLS is disabled - no certificate validation
- Dominant language
- Go
- Stars
- 64
- Forks
- 80
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 15
Description
## Summary
When `tls.enabled` is set to `false` (or left unset), the gRPC client in `fxconfig` silently downgrades to a completely **plaintext connection** with zero certificate validation. Because the default value of `enabled` is `false`, every fresh deployment that doesn't explicitly opt into TLS is running without any transport security out of the box.
## Where
**File:** `tools/fxconfig/internal/client/client.go`, lines 42-44
**Function:** `createSecOpts`
```go
if !tlsConfig.IsEnabled() {
return &secOpts, nil // returns empty SecureOptions → UseTLS = false → plaintext
}
```
This returns a bare comm.SecureOptions{} struct - UseTLS stays false, no root CAs are loaded, and the resulting grpc.ClientConn is dialed without any transport credentials.
The IsEnabled() check lives in tools/fxconfig/internal/config/config.go:107-111 and defaults to false when the pointer is nil.
## Why this matters
1.No encryption in transit. Channel payloads (transaction proposals, block events, notification streams) are sent as cleartext over the network.
2.No server identity verification. Without root CA certificates, there is nothing stopping a man-in-the-middle from impersonating the orderer, query, or notification service.
3.Unsafe default. The enabled field defaults to false, which means operators who forget to (or don't know to) flip the flag are silently running insecure. This is especially risky in cloud or multi-tenant environments where network trust boundaries are not guaranteed.
## Steps to reproduce
1.Create or use a config file where `tls.enabled` is either explicitly `false` or simply omitted.
2.Start `fxconfig` — all three clients will connect over plaintext gRPC.
3.Inspect the wire traffic (e.g., with `tcpdump` or Wireshark) to confirm payloads are unencrypted.
## Suggested fix
A few options to consider (not mutually exclusive):
Default `enabled` to `true`. Flip the struct tag default from `"false"` to `"true"` so TLS is on unless an operator deliberately disables it. This is the "secure by default" approach.
Log a warning when TLS is off. If keeping false as the default is intentional for local dev, emit a clear warning at startup (e.g., `"TLS is disabled for — connections are not encrypted"`) so operators are aware.
Require an explicit opt-out. Instead of silently accepting a missing `enabled` field, require the operator to set `enabled: false` explicitly if they truly want plaintext, and error on `nil`.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.