Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: "1.26"
go-version: "1.27"
- name: go fix
run: |
if [ -n "$(go fix -diff ./...)" ]; then
Expand All @@ -25,15 +25,15 @@ jobs:
fi
- uses: golangci/golangci-lint-action@v9
with:
version: v2.10
version: v2.13

govulncheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: "1.26"
go-version: "1.27"
- run: make govulncheck

test-linux:
Expand All @@ -42,7 +42,7 @@ jobs:
# AppArmor restrictions on unprivileged user namespaces that break the
# namespace-based sandbox tests; Debian does not.
container:
image: golang:1.26
image: golang:1.27
env:
CGO_ENABLED: "0"
steps:
Expand All @@ -63,5 +63,5 @@ jobs:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: "1.26"
go-version: "1.27"
- run: make test
5 changes: 2 additions & 3 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type Config struct {
Quiet bool
DryRun bool
Auto bool
ConfigFilePaths []string
ConfigFilePaths []string
Command []string
}

Expand Down Expand Up @@ -137,7 +137,7 @@ func FromFlags(cmd *cobra.Command) (*Config, error) {
Quiet: quiet,
DryRun: dryRun,
Auto: auto,
Command: cmd.Flags().Args(),
Command: cmd.Flags().Args(),
}

// Wildcard handling: '*' in list flags sets the corresponding escape hatch.
Expand Down Expand Up @@ -273,4 +273,3 @@ func EnvBool(key string) bool {
val := os.Getenv(key)
return val == "1" || strings.EqualFold(val, "true")
}

12 changes: 6 additions & 6 deletions config/configfile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,12 +363,12 @@ func TestMergeConfigFile_ExpandEnvDollarEscape(t *testing.T) {

cf := &ConfigFile{
Read: []string{
"/foo$$bar", // literal $: "/foo$bar"
"/foo$$$$bar", // literal $$: "/foo$$bar"
"$$/$CURB_TEST_DIR", // literal $ then expansion: "$/tmp/curb-expand-test"
"$CURB_TEST_DIR$$tail", // expansion then literal $: "/tmp/curb-expand-test$tail"
"$${CURB_TEST_DIR}", // escape disarms braces: "${CURB_TEST_DIR}"
`\!$$bang`, // bang-escape + literal $: "\!$bang"
"/foo$$bar", // literal $: "/foo$bar"
"/foo$$$$bar", // literal $$: "/foo$$bar"
"$$/$CURB_TEST_DIR", // literal $ then expansion: "$/tmp/curb-expand-test"
"$CURB_TEST_DIR$$tail", // expansion then literal $: "/tmp/curb-expand-test$tail"
"$${CURB_TEST_DIR}", // escape disarms braces: "${CURB_TEST_DIR}"
`\!$$bang`, // bang-escape + literal $: "\!$bang"
},
}
MergeConfigFile(cfg, cf, cmd.Flags())
Expand Down
1 change: 0 additions & 1 deletion config/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,3 @@ func ExpandHomeRefs(paths []string, home string) []string {
func PathReferencesHome(p string) bool {
return p == "~" || strings.HasPrefix(p, "~/") || strings.Contains(p, homeRefMarker)
}

32 changes: 15 additions & 17 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
module github.com/upsun/curb

go 1.26.1
go 1.27.1

require (
github.com/landlock-lsm/go-landlock v0.7.0
github.com/landlock-lsm/go-landlock v0.10.0
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.9
github.com/stretchr/testify v1.11.1
golang.org/x/crypto v0.49.0
golang.org/x/net v0.51.0
golang.org/x/sys v0.42.0
golang.org/x/term v0.41.0
github.com/spf13/pflag v1.0.10
github.com/stretchr/testify v1.12.1
golang.org/x/crypto v0.56.0
golang.org/x/net v0.58.0
golang.org/x/sys v0.47.0
golang.org/x/term v0.45.0
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/mod v0.31.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/telemetry v0.0.0-20251203150158-8fff8a5912fc // indirect
golang.org/x/tools v0.40.0 // indirect
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect
golang.org/x/vuln v1.1.4 // indirect
kernel.org/pub/linux/libs/security/libcap/psx v1.2.77 // indirect
go.yaml.in/yaml/v3 v3.0.5 // indirect
golang.org/x/mod v0.40.0 // indirect
golang.org/x/sync v0.22.0 // indirect
golang.org/x/telemetry v0.0.0-20260811182544-a038080d80e5 // indirect
golang.org/x/tools v0.49.0 // indirect
golang.org/x/vuln v1.7.0 // indirect
kernel.org/pub/linux/libs/security/libcap/psx v1.2.78 // indirect
)

tool golang.org/x/vuln/cmd/govulncheck
61 changes: 30 additions & 31 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU=
github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786/go.mod h1:apVn/GCasLZUVpAJ6oWAuyP7Ne7CEsQbTnc0plM3m+o=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
Expand All @@ -9,43 +7,44 @@ github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/landlock-lsm/go-landlock v0.7.0 h1:gXz0+Phg3vddZjpPzXL4pQy/MgsTMHZBs+9zgUIyu/0=
github.com/landlock-lsm/go-landlock v0.7.0/go.mod h1:mn5GSi81Jf7yMs5WSi+SUi4sUeNLUGVdbT4Id6wXNQw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/landlock-lsm/go-landlock v0.10.0 h1:1o2TDSEK/LRazMq9RNd6ln7WSoVx3ceOsATYkIuoeFE=
github.com/landlock-lsm/go-landlock v0.10.0/go.mod h1:mn5GSi81Jf7yMs5WSi+SUi4sUeNLUGVdbT4Id6wXNQw=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/telemetry v0.0.0-20251203150158-8fff8a5912fc h1:bH6xUXay0AIFMElXG2rQ4uiE+7ncwtiOdPfYK1NK2XA=
golang.org/x/telemetry v0.0.0-20251203150158-8fff8a5912fc/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ=
golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
golang.org/x/tools/go/expect v0.1.0-deprecated h1:jY2C5HGYR5lqex3gEniOQL0r7Dq5+VGVgY1nudX5lXY=
golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y=
golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I=
golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs=
golang.org/x/mod v0.40.0/go.mod h1:0/weTWkPWGBikyTWAX3dkjVztMmBA5hM0DH6BElSupE=
golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=
golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/telemetry v0.0.0-20260811182544-a038080d80e5 h1:ZUSxONxc981v7AW7QUg+I9WwZzSTTJ019ENBYr5pV/Q=
golang.org/x/telemetry v0.0.0-20260811182544-a038080d80e5/go.mod h1:LVehoXe41cL5SCVQilsV7Gg6BNG+Js6P9PhSbYTIUkQ=
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI=
golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo=
golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=
golang.org/x/vuln v1.1.4 h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I=
golang.org/x/vuln v1.1.4/go.mod h1:F+45wmU18ym/ca5PLTPLsSzr2KppzswxPP603ldA67s=
golang.org/x/vuln v1.7.0 h1:4MQBuhmXbz2uepNJrf3v+aaZLGDqw1JluwYboegA1qg=
golang.org/x/vuln v1.7.0/go.mod h1:Xw7zvU3e1bsCYYBXu+w4wcn2Kgn27f34WBCTw8LL5Us=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.77 h1:Z06sMOzc0GNCwp6efaVrIrz4ywGJ1v+DP0pjVkOfDuA=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.77/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.78 h1:PC3yNs51cX5LZ7U57a7xielBcoXB3xnV+rXD8V0H0DQ=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.78/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24=
1 change: 0 additions & 1 deletion proxy/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"sync"
)


// Handler is an HTTP proxy handler that filters CONNECT (HTTPS) and plain
// HTTP requests by domain and IP allowlists. HTTPS uses passthrough
// tunneling: the proxy checks the CONNECT hostname, then relays the
Expand Down
20 changes: 6 additions & 14 deletions proxy/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@ func connectThroughProxy(t *testing.T, proxyAddr, target string) (net.Conn, *buf
func setupProxy(t *testing.T) *httptest.Server {
t.Helper()
h := &Handler{
FilterBase: FilterBase{
DomainCheck: func(d string) bool { return d == "allowed.example.com" },
IPCheck: func(a netip.Addr) bool { return a == netip.MustParseAddr("93.184.215.14") },
},
DomainCheck: func(d string) bool { return d == "allowed.example.com" },
IPCheck: func(a netip.Addr) bool { return a == netip.MustParseAddr("93.184.215.14") },
}
proxyServer := httptest.NewServer(h)
t.Cleanup(proxyServer.Close)
Expand All @@ -57,9 +55,7 @@ func TestHandler_CONNECT_Allowed(t *testing.T) {
upstreamAddr := upstreamURL.Host // 127.0.0.1:<port>

h := &Handler{
FilterBase: FilterBase{
IPCheck: func(a netip.Addr) bool { return a.IsLoopback() },
},
IPCheck: func(a netip.Addr) bool { return a.IsLoopback() },
}
proxyServer := httptest.NewServer(h)
defer proxyServer.Close()
Expand Down Expand Up @@ -105,9 +101,7 @@ func TestHandler_CONNECT_IPAllowed(t *testing.T) {
upstreamAddr := upstreamURL.Host // 127.0.0.1:<port>

h := &Handler{
FilterBase: FilterBase{
IPCheck: func(a netip.Addr) bool { return a.IsLoopback() },
},
IPCheck: func(a netip.Addr) bool { return a.IsLoopback() },
}
proxyServer := httptest.NewServer(h)
defer proxyServer.Close()
Expand Down Expand Up @@ -152,10 +146,8 @@ func TestHandler_HTTP_Allowed(t *testing.T) {
upstreamHost := upstreamURL.Host

h := &Handler{
FilterBase: FilterBase{
DomainCheck: func(d string) bool { return true },
IPCheck: func(a netip.Addr) bool { return true },
},
DomainCheck: func(d string) bool { return true },
IPCheck: func(a netip.Addr) bool { return true },
}
proxyServer := httptest.NewServer(h)
defer proxyServer.Close()
Expand Down
20 changes: 10 additions & 10 deletions proxy/socks5_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ func TestSOCKS5Server_ConnectDomain(t *testing.T) {

_, echoPort, _ := net.SplitHostPort(echoLn.Addr().String())

srv := &SOCKS5Server{FilterBase: FilterBase{
srv := &SOCKS5Server{
DomainCheck: func(domain string) bool {
return domain == "localhost"
},
Dialer: &net.Dialer{Timeout: 2 * time.Second},
}}
}

ln, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
Expand Down Expand Up @@ -82,11 +82,11 @@ func TestSOCKS5Server_ConnectDomain(t *testing.T) {
}

func TestSOCKS5Server_BlockedDomain(t *testing.T) {
srv := &SOCKS5Server{FilterBase: FilterBase{
srv := &SOCKS5Server{
DomainCheck: func(domain string) bool {
return false // Block everything.
},
}}
}

ln, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
Expand Down Expand Up @@ -138,12 +138,12 @@ func TestSOCKS5Server_ConnectIPv4(t *testing.T) {
}()
_, echoPort, _ := net.SplitHostPort(echoLn.Addr().String())

srv := &SOCKS5Server{FilterBase: FilterBase{
srv := &SOCKS5Server{
IPCheck: func(addr netip.Addr) bool {
return addr.IsLoopback()
},
Dialer: &net.Dialer{Timeout: 2 * time.Second},
}}
}

ln, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
Expand Down Expand Up @@ -182,9 +182,9 @@ func TestSOCKS5Server_ConnectIPv4(t *testing.T) {
}

func TestSOCKS5Server_UnsupportedCommand(t *testing.T) {
srv := &SOCKS5Server{FilterBase: FilterBase{
srv := &SOCKS5Server{
DomainCheck: func(string) bool { return true },
}}
}

ln, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
Expand Down Expand Up @@ -233,10 +233,10 @@ func TestSOCKS5Server_ConcurrentConnections(t *testing.T) {
}()
_, echoPort, _ := net.SplitHostPort(echoLn.Addr().String())

srv := &SOCKS5Server{FilterBase: FilterBase{
srv := &SOCKS5Server{
DomainCheck: func(string) bool { return true },
Dialer: &net.Dialer{Timeout: 2 * time.Second},
}}
}

ln, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
Expand Down
2 changes: 0 additions & 2 deletions sandbox/capabilities.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package sandbox


// Capabilities holds the results of probing system capabilities.
type Capabilities struct {
UserNS error // nil = ok, non-nil = fatal.
Expand All @@ -27,4 +26,3 @@ func userNSErrMessage() string {
func netNSErrMessage() string {
return `Network namespaces are required for --domains but are not available.`
}

5 changes: 3 additions & 2 deletions sandbox/parent_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"os"
"os/exec"
"os/signal"
"slices"
"syscall"

"github.com/upsun/curb/proxy"
Expand All @@ -21,8 +22,8 @@ type resources struct{ closers []func() }
func (r *resources) push(fn func()) { r.closers = append(r.closers, fn) }

func (r *resources) closeAll() {
for i := len(r.closers) - 1; i >= 0; i-- {
r.closers[i]()
for _, v := range slices.Backward(r.closers) {
v()
}
r.closers = nil
}
Expand Down
2 changes: 1 addition & 1 deletion sandbox/plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -996,7 +996,7 @@ func TestFormatSkill_NoFSSection(t *testing.T) {
func TestFormatSkill_ExcludesSelfEnvVar(t *testing.T) {
plan := &SandboxPlan{
EnvSet: map[string]string{
"TMPDIR": "/tmp/curb-abc",
"TMPDIR": "/tmp/curb-abc",
SkillDirEnvKey: "/tmp/curb-abc/.agents/skills/curb",
},
}
Expand Down