Files
rclone/fs/config_test.go
Nick Craig-Wood 53f972830c rc: stop global.* connection string options changing config CVE-2026-49980
A connection string can carry global.* options which change rclone's
process-wide configuration (e.g. global.http_proxy). This is
undesirable for the rc interface which was designed to have multiple
users or connections at once. The rc interface has the `_config`
mechanism for setting request scoped global config.

This blocks global.* options on all rc paths by marking the context as
a remote control request at the rc boundaries. fs.NewFs then skips
applying global.* to the process-wide config for a marked context.

The marker is reapplied in fs.CopyConfig, which is the call rclone
uses to detach context but keep config.

global.* options still apply to the individual backend they are set
on, exactly like override.* options; they just no longer leak into the
rest of the process. Remotes created directly on the command line are
unaffected as are remotes defined in the config file.

See: GHSA-qw24-gh76-8rvv
2026-06-05 15:21:01 +01:00

50 lines
1.4 KiB
Go

package fs
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
)
func TestGetConfig(t *testing.T) {
ctx := context.Background()
// Check nil
//lint:ignore SA1012 false positive when running staticcheck, we want to test passing a nil Context and therefore ignore lint suggestion to use context.TODO
//nolint:staticcheck // Don't include staticcheck when running golangci-lint to avoid SA1012
config := GetConfig(nil)
assert.Equal(t, globalConfig, config)
// Check empty config
config = GetConfig(ctx)
assert.Equal(t, globalConfig, config)
// Check adding a config
ctx2, config2 := AddConfig(ctx)
config2.Transfers++
assert.NotEqual(t, config2, config)
// Check can get config back
config2ctx := GetConfig(ctx2)
assert.Equal(t, config2, config2ctx)
}
// The rc request marker must survive CopyConfig, which is how rclone
// does detach context but keep config.
func TestRCRequestContext(t *testing.T) {
ctx := context.Background()
assert.False(t, IsRCRequest(ctx))
rcCtx := WithRCRequest(ctx)
assert.True(t, IsRCRequest(rcCtx))
// CopyConfig carries the marker even when there is no config to copy
assert.True(t, IsRCRequest(CopyConfig(context.Background(), rcCtx)))
// and when there is
rcCtx, _ = AddConfig(rcCtx)
assert.True(t, IsRCRequest(CopyConfig(context.Background(), rcCtx)))
// An unmarked context stays unmarked
assert.False(t, IsRCRequest(CopyConfig(context.Background(), ctx)))
}