fix(envd): port scanner ignores net.Connections error and drops active forwarded ports
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 1.6k
- Forks
- 438
- PR merge metrics
- No merged PRs in 30d
Description
Problem
Inside envd (packages/envd/internal/port/scan.go), the background port scanner loop invokes net.Connections("tcp") and silently discards the returned error using _.
When reading /proc/net/tcp or /proc/net/tcp6 fails (e.g. transient kernel resource pressure or procfs read errors), processes evaluates to nil. Passing an empty/nil connection list to subscribers causes Forwarder to assume zero local TCP ports are listening. As a result, Forwarder marks all active forwarded ports as DELETE and forcibly terminates all background socat forwarding processes, dropping user process reachability without logging any diagnostic error.
Additionally, packages/envd/internal/port has no unit tests.
// Transient failure reading /proc/net/tcp inside guest:
net.Connections("tcp") -> returns (nil, err)
// Error ignored with _:
processes, _ := net.Connections("tcp")
// Forwarder receives nil processes -> kills active socat instances!
Root Cause
In packages/envd/internal/port/scan.go:
| Factor | Current State | Expected State |
|---|---|---|
| Error Handling | Discarded via processes, _ := net.Connections("tcp") |
Log error and skip subscriber broadcast on error |
| Port Forwarder | Clears active socat ports on empty scan results |
Retains existing socat instances during transient scan errors |
| Test Coverage | 0 test files in packages/envd/internal/port |
Unit tests for scanner lifecycle, filtering, and error handling |
Reproduction Steps
- Start
envdwith port scanning active. - Simulate a procfs or system error where
net.Connections("tcp")returns(nil, err). - Observe
ScanAndBroadcastbroadcastingnilprocesses to subscribers. - Observe
Forwarderkilling all activesocatport-forwarding processes on guest ports.
// Current implementation in packages/envd/internal/port/scan.go
func (s *Scanner) ScanAndBroadcast() {
ticker := time.NewTicker(s.period)
defer ticker.Stop()
for {
processes, _ := net.Connections("tcp") // Silent error discard!
for _, sub := range s.subs.Items() {
sub.Signal(processes)
}
select {
case <-s.scanExit:
return
case <-ticker.C:
}
}
}
Technical Context
- Files affected:
packages/envd/internal/port/scan.go,packages/envd/main.go,packages/envd/pkg/version.go - Subsystem: Envd (In-VM Agent)
- Impact: Medium
Proposed Changes
| # | Change | File(s) Affected | Complexity |
|---|---|---|---|
| 1 | Pass logger to NewScanner and log net.Connections("tcp") errors without broadcasting invalid empty slices |
packages/envd/internal/port/scan.go, packages/envd/main.go |
Low |
| 2 | Add comprehensive unit tests for Scanner and ScannerSubscriber |
packages/envd/internal/port/scan_test.go |
Low |
| 3 | Bump envd version to 0.6.12 |
packages/envd/pkg/version.go |
Trivial |
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/envd/internal/port/scan.go and trace Scanner construction from packages/envd/main.go. Add coverage in packages/envd/internal/port/scan_test.go for scanner lifecycle, filtering, subscriber behavior, and connection errors; done means errors are logged without broadcasting invalid results and active forwards are retained. Update packages/envd/pkg/version.go to 0.6.12 as specified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100