Skip to content

Commit 5c3388e

Browse files
authored
Merge branch 'main' into carterbrainerd-vuln-114-cross-host-redirect-causes-oauth-bearer-token-exfiltration
2 parents 7bb91b5 + 23e836a commit 5c3388e

14 files changed

Lines changed: 215 additions & 112 deletions

File tree

‎Dockerfile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55
# Nothing fancy here: we copy in the source code and build on the Alpine Go
66
# image. Refer to .dockerignore to get a sense of what we're not going to copy.
7-
FROM golang:1.26.4-alpine3.22@sha256:727cfc3c40be55cd1bc9a4a059406b28a059857e3be752aa9d09531e12c20c56 AS builder
7+
FROM golang:1.26.5-alpine3.23@sha256:622e56dbc11a8cfe87cafa2331e9a201877271cbff918af53d3be315f3da88cc AS builder
88

99
COPY . /src
1010
WORKDIR /src

‎README.md‎

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -103,54 +103,65 @@ See [Sourcegraph CLI for Windows](WINDOWS.md).
103103
docker run --rm=true sourcegraph/src-cli:latest search 'hello world'
104104
```
105105

106-
## Log into your Sourcegraph instance
106+
<a id="log-into-your-sourcegraph-instance"></a>
107107

108-
Run <code><strong>src login <i>SOURCEGRAPH-URL</i></strong></code> to authenticate `src` to access your Sourcegraph instance with your user credentials.
108+
## Connect to your Sourcegraph instance
109109

110-
<blockquote>
110+
`src` needs the URL of your Sourcegraph instance. Set `SRC_ENDPOINT` in your shell environment, replacing `https://sourcegraph.example.com` with your instance URL:
111111

112-
**Examples**
113-
`src login https://sourcegraph.example.com`
114-
`src login https://sourcegraph.com`
112+
```sh
113+
export SRC_ENDPOINT=https://sourcegraph.example.com
114+
```
115115

116-
</blockquote>
116+
For PowerShell on Windows:
117117

118-
`src` consults the following environment variables:
118+
```powershell
119+
$env:SRC_ENDPOINT = 'https://sourcegraph.example.com'
120+
```
119121

120-
- `SRC_ENDPOINT`: the URL to your Sourcegraph instance (such as `https://sourcegraph.example.com`)
121-
- `SRC_ACCESS_TOKEN`: your Sourcegraph access token (on your Sourcegraph instance, click your user menu in the top right, then select **Settings > Access tokens** to create one)
122+
For convenience, add this environment variable to your terminal profile or system environment variables. On Mac OS and Linux, the terminal profile is typically `~/.bash_profile` for Bash or `~/.zprofile` for Zsh. On Windows, you can add it through the *System Properties* window. See [these instructions](https://www.computerhope.com/issues/ch000549.htm) for details.
122123

123-
For convenience, you can add these environment variables persistently.
124+
If `SRC_ENDPOINT` is not set, `src` defaults to `https://sourcegraph.com`.
124125

125-
### Configuration: Mac OS / Linux
126+
### OAuth login
126127

127-
Add the following to your terminal profile file, typically accessible at `~/.bash_profile` (if using Bash) or `~/.zprofile` (if using Zsh):
128+
Run `src login` to authenticate interactively with OAuth:
128129

129-
```
130-
export SRC_ACCESS_TOKEN=my-token
131-
export SRC_ENDPOINT=https://sourcegraph.example.com
130+
```sh
131+
src login
132132
```
133133

134-
Replace `my-token` and `https://sourcegraph.example.com` with the appropriate values for your account and instance.
134+
OAuth does not require you to create or export `SRC_ACCESS_TOKEN`. The OAuth credential is stored in your operating system's native keyring. Keep `SRC_ENDPOINT` set when running subsequent commands because `src` uses the endpoint to load the matching OAuth credential.
135135

136-
You can also inline them in a single command with:
136+
You can also pass the instance URL directly to `src login`, but this only selects the endpoint for that login command. You must still set `SRC_ENDPOINT` when running subsequent commands:
137137

138138
```sh
139-
SRC_ENDPOINT=https://sourcegraph.example.com SRC_ACCESS_TOKEN=my-token src search 'foo'
139+
src login https://sourcegraph.example.com
140140
```
141141

142-
### Configuration: Windows
142+
To use the active credential in another command, `src auth token` prints the raw token and `src auth token --header` prints a complete `Authorization` header for the active authentication mode.
143143

144-
Type the following on your PowerShell terminal:
144+
### Personal access token login
145145

146+
For non-interactive authentication, such as in CI or scripts, create an access token on your Sourcegraph instance under **Settings > Access tokens**, then set both `SRC_ENDPOINT` and `SRC_ACCESS_TOKEN`:
147+
148+
```sh
149+
export SRC_ENDPOINT=https://sourcegraph.example.com
150+
export SRC_ACCESS_TOKEN=my-token
146151
```
152+
153+
For PowerShell on Windows:
154+
155+
```powershell
147156
$env:SRC_ENDPOINT = 'https://sourcegraph.example.com'
148157
$env:SRC_ACCESS_TOKEN = 'my-token'
149158
```
150159

151-
Replace `my-token` and `https://sourcegraph.example.com` with the appropriate values for your account and instance.
160+
When `SRC_ACCESS_TOKEN` is set, `src` uses it instead of an OAuth credential and running `src login` is not necessary. You can also set both variables for a single command:
152161

153-
You can also manually add them via the *System Properties* windows. Check [this post](https://www.computerhope.com/issues/ch000549.htm) for details.
162+
```sh
163+
SRC_ENDPOINT=https://sourcegraph.example.com SRC_ACCESS_TOKEN=my-token src search 'foo'
164+
```
154165

155166
Is your Sourcegraph instance behind a custom auth proxy? See [auth proxy configuration](./AUTH_PROXY.md) docs.
156167

@@ -159,6 +170,7 @@ Is your Sourcegraph instance behind a custom auth proxy? See [auth proxy configu
159170
`src` provides different subcommands to interact with different parts of Sourcegraph:
160171

161172
- `src login` - authenticate to a Sourcegraph instance with your user credentials
173+
- `src auth` - print the active authentication token or authorization header
162174
- `src search` - perform searches and get results in your terminal or as JSON
163175
- `src api` - run Sourcegraph GraphQL API requests
164176
- `src batch` - execute and manage [batch changes](https://docs.sourcegraph.com/batch_changes)

‎cmd/src/main.go‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,16 @@ func readConfig() (*config, error) {
337337
}
338338
}
339339

340-
cfg.additionalHeaders = parseAdditionalHeaders()
340+
// Merge config-file headers under the env headers (which take precedence),
341+
// lowercasing config keys to match the env-header convention.
342+
envHeaders := parseAdditionalHeaders()
343+
for k, v := range cfg.additionalHeaders {
344+
lk := strings.ToLower(k)
345+
if _, ok := envHeaders[lk]; !ok {
346+
envHeaders[lk] = v
347+
}
348+
}
349+
cfg.additionalHeaders = envHeaders
341350
// Ensure that we're not clashing additonal headers
342351
_, hasAuthorizationAdditonalHeader := cfg.additionalHeaders["authorization"]
343352
if cfg.accessToken != "" && hasAuthorizationAdditonalHeader {

‎cmd/src/main_test.go‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,63 @@ func TestReadConfig(t *testing.T) {
358358
inCI: true,
359359
},
360360
},
361+
{
362+
name: "config file additional headers preserved when endpoint/token from environment",
363+
fileContents: &configFromFile{
364+
Endpoint: "https://example.com/",
365+
AccessToken: "deadbeef",
366+
AdditionalHeaders: map[string]string{"x-proxy-token": "secret"},
367+
},
368+
envToken: "abc",
369+
envEndpoint: "https://override.com",
370+
want: &config{
371+
endpointURL: &url.URL{Scheme: "https", Host: "override.com"},
372+
accessToken: "abc",
373+
additionalHeaders: map[string]string{"x-proxy-token": "secret"},
374+
},
375+
},
376+
{
377+
name: "config file additional headers merged with environment headers",
378+
fileContents: &configFromFile{
379+
Endpoint: "https://example.com/",
380+
AccessToken: "deadbeef",
381+
AdditionalHeaders: map[string]string{"x-proxy-token": "secret"},
382+
},
383+
envFooHeader: "bar",
384+
want: &config{
385+
endpointURL: &url.URL{Scheme: "https", Host: "example.com"},
386+
accessToken: "deadbeef",
387+
additionalHeaders: map[string]string{"x-proxy-token": "secret", "foo": "bar"},
388+
},
389+
},
390+
{
391+
name: "environment headers override config file headers",
392+
fileContents: &configFromFile{
393+
Endpoint: "https://example.com/",
394+
AccessToken: "deadbeef",
395+
AdditionalHeaders: map[string]string{"foo": "from-config"},
396+
},
397+
envFooHeader: "from-env",
398+
want: &config{
399+
endpointURL: &url.URL{Scheme: "https", Host: "example.com"},
400+
accessToken: "deadbeef",
401+
additionalHeaders: map[string]string{"foo": "from-env"},
402+
},
403+
},
404+
{
405+
name: "environment headers override differently-cased config file headers",
406+
fileContents: &configFromFile{
407+
Endpoint: "https://example.com/",
408+
AccessToken: "deadbeef",
409+
AdditionalHeaders: map[string]string{"Foo": "from-config"},
410+
},
411+
envFooHeader: "from-env",
412+
want: &config{
413+
endpointURL: &url.URL{Scheme: "https", Host: "example.com"},
414+
accessToken: "deadbeef",
415+
additionalHeaders: map[string]string{"foo": "from-env"},
416+
},
417+
},
361418
}
362419

363420
for _, test := range tests {

‎dev/vendor-lib.sh‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ echo "Creating go.mod file..."
136136
cat > "$DEST_LIB/go.mod" <<EOF
137137
module github.com/sourcegraph/sourcegraph/lib
138138
139-
go 1.26.4
139+
go 1.26.5
140140
EOF
141141

142142
# Create README.md

‎go.mod‎

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/sourcegraph/src-cli
22

3-
go 1.26.4
3+
go 1.26.5
44

55
require (
66
cloud.google.com/go/storage v1.50.0
@@ -32,9 +32,9 @@ require (
3232
github.com/tliron/glsp v0.2.2
3333
github.com/urfave/cli/v3 v3.8.0
3434
github.com/zalando/go-keyring v0.2.6
35-
golang.org/x/sync v0.19.0
35+
golang.org/x/sync v0.22.0
3636
google.golang.org/api v0.256.0
37-
google.golang.org/protobuf v1.36.10
37+
google.golang.org/protobuf v1.36.11
3838
gopkg.in/yaml.v3 v3.0.1
3939
jaytaylor.com/html2text v0.0.0-20200412013138-3577fbdbcff7
4040
k8s.io/api v0.33.2
@@ -48,7 +48,7 @@ require (
4848
cloud.google.com/go/auth v0.17.0 // indirect
4949
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
5050
cloud.google.com/go/monitoring v1.24.2 // indirect
51-
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 // indirect
51+
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0 // indirect
5252
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.50.0 // indirect
5353
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.50.0 // indirect
5454
github.com/alecthomas/chroma/v2 v2.14.0 // indirect
@@ -60,9 +60,9 @@ require (
6060
github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf // indirect
6161
github.com/charmbracelet/x/term v0.2.1 // indirect
6262
github.com/clipperhouse/uax29/v2 v2.2.0 // indirect
63-
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect
63+
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // indirect
6464
github.com/danieljoos/wincred v1.2.2 // indirect
65-
github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect
65+
github.com/envoyproxy/go-control-plane/envoy v1.37.0 // indirect
6666
github.com/felixge/httpsnoop v1.0.4 // indirect
6767
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
6868
github.com/go-jose/go-jose/v4 v4.1.4 // indirect
@@ -88,17 +88,17 @@ require (
8888
github.com/xlab/treeprint v1.2.0 // indirect
8989
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
9090
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
91-
go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect
91+
go.opentelemetry.io/contrib/detectors/gcp v1.43.0 // indirect
9292
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
9393
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect
9494
go.opentelemetry.io/otel v1.43.0 // indirect
9595
go.opentelemetry.io/otel/metric v1.43.0 // indirect
9696
go.opentelemetry.io/otel/sdk v1.43.0 // indirect
9797
go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect
9898
go.opentelemetry.io/otel/trace v1.43.0 // indirect
99-
golang.org/x/net v0.48.0 // indirect
100-
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect
101-
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
99+
golang.org/x/net v0.57.0 // indirect
100+
google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 // indirect
101+
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect
102102
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
103103
sigs.k8s.io/randfill v1.0.0 // indirect
104104
)
@@ -129,7 +129,7 @@ require (
129129
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
130130
github.com/dlclark/regexp2 v1.11.0 // indirect
131131
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
132-
github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect
132+
github.com/envoyproxy/protoc-gen-validate v1.3.3 // indirect
133133
github.com/fatih/color v1.18.0 // indirect
134134
github.com/getsentry/sentry-go v0.27.0 // indirect
135135
github.com/ghodss/yaml v1.0.0 // indirect
@@ -174,21 +174,21 @@ require (
174174
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
175175
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
176176
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
177-
github.com/yuin/goldmark v1.7.8 // indirect
177+
github.com/yuin/goldmark v1.7.17 // indirect
178178
github.com/yuin/goldmark-emoji v1.0.5 // indirect
179179
go.uber.org/atomic v1.11.0 // indirect
180180
go.uber.org/multierr v1.11.0 // indirect
181181
go.uber.org/zap v1.24.0 // indirect
182-
golang.org/x/crypto v0.46.0 // indirect
183-
golang.org/x/mod v0.30.0 // indirect
184-
golang.org/x/oauth2 v0.34.0 // indirect
185-
golang.org/x/sys v0.42.0 // indirect
186-
golang.org/x/term v0.38.0 // indirect
187-
golang.org/x/text v0.32.0 // indirect
182+
golang.org/x/crypto v0.54.0 // indirect
183+
golang.org/x/mod v0.37.0 // indirect
184+
golang.org/x/oauth2 v0.36.0 // indirect
185+
golang.org/x/sys v0.47.0 // indirect
186+
golang.org/x/term v0.45.0 // indirect
187+
golang.org/x/text v0.40.0 // indirect
188188
golang.org/x/time v0.14.0 // indirect
189-
golang.org/x/tools v0.39.0 // indirect
189+
golang.org/x/tools v0.47.0 // indirect
190190
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
191-
google.golang.org/grpc v1.79.3 // indirect
191+
google.golang.org/grpc v1.82.1 // indirect
192192
gopkg.in/inf.v0 v0.9.1 // indirect; direct
193193
gopkg.in/yaml.v2 v2.4.0 // indirect
194194
k8s.io/klog/v2 v2.130.1 // indirect

0 commit comments

Comments
 (0)