Summary
Comprehensive code review has identified 7 blocking, 5 high, 4 medium, and 8 nit-level issues. Additionally, a feature request for saving session/connection configurations.
🚨 Blocking Issues (Must Fix Before Merge)
B1. Build broken: Tests directory has colliding main packages
- Files:
tests/producer.go, tests/consumer.go
- Issue: Both files declare
package main, causing build failure
- Fix: Separate into
tests/producer/main.go and tests/consumer/main.go
B2. Panic-prone bare type assertions in AI response parsing
- Files:
pkg/ui/ai_assistant.go:629-632, 704-715, 784-787, 1629-1640
- Issue: All AI provider JSON parsing uses bare assertions without comma-ok pattern. Unexpected response structure → panic → TUI crash
- Example:
firstChoice := choices[0].(map[string]interface{}) // panics if type wrong
- Fix: Use comma-ok pattern:
firstChoice, ok := choices[0].(map[string]interface{})
if !ok {
return "", fmt.Errorf("unexpected response structure")
}
B3. Gemini API key leaked in URL query parameter
- File:
pkg/ui/ai_assistant.go:643
- Issue: API key embedded in URL:
https://...?key=<KEY> → appears in proxy logs, error messages, debug output
- Fix: Use HTTP header
x-goog-api-key instead of query parameter
B4. AI assistant executes destructive operations without confirmation
- File:
pkg/ui/ai_assistant.go:1008-1790
- Issue:
parseAndExecuteCommand directly mutates Kafka state (create topics, modify ALL topic configs, delete ACLs) based on AI-generated JSON. No user confirmation gate.
- Fix: Add confirmation dialog before any destructive operation
B5. os.Exit(0) in PreRunE callback
- File:
cmd/kconduit/main.go:53
- Issue: Bypasses deferred cleanup in main. Use Cobra's built-in version support instead
- Fix: Use
rootCmd.Version and rootCmd.SetVersionTemplate()
B6. Data race on topic cache
- File:
pkg/kafka/client.go:188-216 (GetTopicDetails)
- Issue:
c.topics and c.topicsLastFetched read/written without synchronization. Data race if multiple goroutines call this.
- Fix: Guard with
sync.RWMutex
B7. Near-zero test coverage
- File:
pkg/kafka/client_test.go (single 50-line test)
- Issue: No tests for Client methods, UI models, AI parsing/execution, message production/consumption
- Impact: Critical for a tool that executes Kafka mutations
- Fix: Add unit tests for client.go, create_topic, delete_topic, edit_config, ACL operations, AI command execution
🔴 Security Issues (High Priority)
S1. SASL password visible in process list
- File:
cmd/kconduit/main.go:144
- Issue:
--sasl-password flag visible in ps aux output
- Attack: Co-tenant reads
/proc/<pid>/cmdline to harvest credentials
- Fix: Remove CLI flag; accept only via
KCONDUIT_SASL_PASSWORD env var or --sasl-password-file
S2. TLS MinVersion not set (defaults to TLS 1.0)
- File:
pkg/kafka/client.go:106-108
- Issue: Allows downgrade to TLS 1.0 (BEAST, POODLE vulnerabilities)
- Fix:
tlsConf := &tls.Config{
MinVersion: tls.VersionTLS12,
InsecureSkipVerify: tlsConfig.InsecureSkipVerify,
}
S3. InsecureSkipVerify has no runtime warning
- File:
pkg/kafka/client.go:112
- Issue: Flag silently disables certificate validation; user may enable for testing and forget to remove
- Fix: Log prominent warning when enabled
S4. Ollama URL user-controlled with no validation (SSRF)
- File:
pkg/ui/ai_assistant.go:146, 806
- Issue:
OLLAMA_URL env var used directly in HTTP request: can point to internal services, cloud metadata endpoints
- Fix: Validate URL scheme (http/https only), reject loopback/link-local/RFC1918 unless explicitly allowed
S5. Unbounded io.ReadAll on AI responses
- Files:
pkg/ui/ai_assistant.go:610, 684, 765, 825
- Issue: No size limit → OOM if provider returns large response
- Fix: Use
io.LimitReader(resp.Body, 10*1024*1024) for 10MB max
🟠 Important Issues
I1. File sizes exceed maintainability threshold
ai_assistant.go: 1790 lines (4 AI providers + command execution + rendering)
model.go: 1447 lines (all tab views in one file)
client.go: 1401 lines (client + ACLs + types)
- Fix: Split into separate files by responsibility
I2. parseAndExecuteCommand has extreme cyclomatic complexity
- File:
pkg/ui/ai_assistant.go:1008-1790 (~780 lines, ~50+ cyclomatic complexity)
- Fix: Extract into dispatch table with per-command handler methods
I3. updateListView high cyclomatic complexity
- File:
pkg/ui/model.go:292-773 (~480 lines)
- Fix: Extract tab key handling into
handleBrokersTabKey(), handleTopicsTabKey(), etc.
I4. HTTP clients lack context.Context
- Files:
pkg/ui/ai_assistant.go (all AI providers)
- Issue: User presses ESC but in-flight HTTP request blocks until timeout (~30-60s)
- Fix: Use
http.NewRequestWithContext with cancellable context
I5. Global mutable logger singleton with TOCTOU race
- File:
pkg/logger/logger.go
- Issue:
Get() checks Log == nil without lock before Init. File handle leak if error occurs.
- Fix: Always call
Init via sync.Once, close file handles on error
I6. Password capture race in AI command closure
- File:
pkg/ui/ai_assistant.go:549-569
- Issue:
processAIQuery captures pointer receiver m in closure running in separate goroutine while main loop modifies m
- Fix: Capture provider and config by value in closure
I7. Consumer goroutine leak potential
- File:
pkg/ui/consumer.go:150-161
- Issue: Spawns goroutine in
Cmd but immediately returns nil. No WaitGroup to verify exit.
- Fix: Track goroutines with
sync.WaitGroup on model shutdown
I8. confluent-kafka-go unused in main code
- File:
go.mod:11
- Issue: Pulls in librdkafka (C library, CGO requirement) only for test utilities in
tests/
- Fix: Move test utilities to separate module or use build tags
📋 Feature Request: Session Config Saving
Goal: Allow users to save and reuse connection configurations instead of typing flags every time.
Design
Config file: ~/.config/kconduit/sessions.yaml (XDG-compliant)
sessions:
local-dev:
brokers: "localhost:9092"
ai_engine: "ollama"
ai_model: "llama3"
staging-kafka:
brokers: "broker1:9092,broker2:9092"
sasl:
enabled: true
mechanism: "SCRAM-SHA-256"
username: "admin"
protocol: "SASL_SSL"
tls:
enabled: true
ca_cert: "/path/to/ca.pem"
New CLI Flags
--session <name> — load a named session
--save-session <name> — save current flags as a session
--list-sessions — list available sessions
--delete-session <name> — remove a session
Security Constraints
- Passwords never stored in config file; use
password_file: references or env vars
- File permissions checked (warn if > 0600)
- AI API keys stay as env vars only
Implementation
- New
pkg/config/config.go package with session load/save/list/delete
- Integrate with Viper precedence: CLI flags > env vars > session config > defaults
- Optional: TUI session picker at startup if no
--session or --brokers provided
NITs
- N1: Unused
isSearchResult variable in consumer.go:455-464
- N2: Naming
cfgTlsEnabled should be cfgTLSEnabled (acronym convention)
- N3: Redundant
_ = err after if err != nil check
- N4: Magic lipgloss color codes — use named constants
- N5: Import ordering inconsistency
- N6:
topicSet computed but unused for deduplication in GetConsumerGroups
- N7:
parseTimeToMilliseconds fragile on space-before-unit input
- N8:
Client.Close() error formatting should use errors.Join (Go 1.20+)
Recommended Priority
- Blocking issues (B1-B7) — prevents merge
- Security issues (S1-S5) — blocks production use
- Important issues (I1-I8) — affects maintainability/reliability
- Feature — session config saving (nice-to-have)
- NITs — low priority cleanup
Summary
Comprehensive code review has identified 7 blocking, 5 high, 4 medium, and 8 nit-level issues. Additionally, a feature request for saving session/connection configurations.
🚨 Blocking Issues (Must Fix Before Merge)
B1. Build broken: Tests directory has colliding
mainpackagestests/producer.go,tests/consumer.gopackage main, causing build failuretests/producer/main.goandtests/consumer/main.goB2. Panic-prone bare type assertions in AI response parsing
pkg/ui/ai_assistant.go:629-632, 704-715, 784-787, 1629-1640B3. Gemini API key leaked in URL query parameter
pkg/ui/ai_assistant.go:643https://...?key=<KEY>→ appears in proxy logs, error messages, debug outputx-goog-api-keyinstead of query parameterB4. AI assistant executes destructive operations without confirmation
pkg/ui/ai_assistant.go:1008-1790parseAndExecuteCommanddirectly mutates Kafka state (create topics, modify ALL topic configs, delete ACLs) based on AI-generated JSON. No user confirmation gate.B5.
os.Exit(0)inPreRunEcallbackcmd/kconduit/main.go:53rootCmd.VersionandrootCmd.SetVersionTemplate()B6. Data race on topic cache
pkg/kafka/client.go:188-216(GetTopicDetails)c.topicsandc.topicsLastFetchedread/written without synchronization. Data race if multiple goroutines call this.sync.RWMutexB7. Near-zero test coverage
pkg/kafka/client_test.go(single 50-line test)🔴 Security Issues (High Priority)
S1. SASL password visible in process list
cmd/kconduit/main.go:144--sasl-passwordflag visible inps auxoutput/proc/<pid>/cmdlineto harvest credentialsKCONDUIT_SASL_PASSWORDenv var or--sasl-password-fileS2. TLS
MinVersionnot set (defaults to TLS 1.0)pkg/kafka/client.go:106-108S3.
InsecureSkipVerifyhas no runtime warningpkg/kafka/client.go:112S4. Ollama URL user-controlled with no validation (SSRF)
pkg/ui/ai_assistant.go:146, 806OLLAMA_URLenv var used directly in HTTP request: can point to internal services, cloud metadata endpointsS5. Unbounded
io.ReadAllon AI responsespkg/ui/ai_assistant.go:610, 684, 765, 825io.LimitReader(resp.Body, 10*1024*1024)for 10MB max🟠 Important Issues
I1. File sizes exceed maintainability threshold
ai_assistant.go: 1790 lines (4 AI providers + command execution + rendering)model.go: 1447 lines (all tab views in one file)client.go: 1401 lines (client + ACLs + types)I2.
parseAndExecuteCommandhas extreme cyclomatic complexitypkg/ui/ai_assistant.go:1008-1790(~780 lines, ~50+ cyclomatic complexity)I3.
updateListViewhigh cyclomatic complexitypkg/ui/model.go:292-773(~480 lines)handleBrokersTabKey(),handleTopicsTabKey(), etc.I4. HTTP clients lack
context.Contextpkg/ui/ai_assistant.go(all AI providers)http.NewRequestWithContextwith cancellable contextI5. Global mutable logger singleton with TOCTOU race
pkg/logger/logger.goGet()checksLog == nilwithout lock beforeInit. File handle leak if error occurs.Initviasync.Once, close file handles on errorI6. Password capture race in AI command closure
pkg/ui/ai_assistant.go:549-569processAIQuerycaptures pointer receivermin closure running in separate goroutine while main loop modifiesmI7. Consumer goroutine leak potential
pkg/ui/consumer.go:150-161Cmdbut immediately returns nil. NoWaitGroupto verify exit.sync.WaitGroupon model shutdownI8.
confluent-kafka-gounused in main codego.mod:11tests/📋 Feature Request: Session Config Saving
Goal: Allow users to save and reuse connection configurations instead of typing flags every time.
Design
Config file:
~/.config/kconduit/sessions.yaml(XDG-compliant)New CLI Flags
--session <name>— load a named session--save-session <name>— save current flags as a session--list-sessions— list available sessions--delete-session <name>— remove a sessionSecurity Constraints
password_file:references or env varsImplementation
pkg/config/config.gopackage with session load/save/list/delete--sessionor--brokersprovidedNITs
isSearchResultvariable inconsumer.go:455-464cfgTlsEnabledshould becfgTLSEnabled(acronym convention)_ = errafterif err != nilchecktopicSetcomputed but unused for deduplication inGetConsumerGroupsparseTimeToMillisecondsfragile on space-before-unit inputClient.Close()error formatting should useerrors.Join(Go 1.20+)Recommended Priority