Skip to content

Commit aced30d

Browse files
authored
Merge pull request #6399 from vvoland/6371-28.x
[28.x backport] Add escape hatch for GODEBUG=x509negativeserial
2 parents d26f1fd + b9e15ef commit aced30d

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

cli/command/cli.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,17 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...CLIOption)
282282
}
283283
filterResourceAttributesEnvvar()
284284

285+
// early return if GODEBUG is already set or the docker context is
286+
// the default context, i.e. is a virtual context where we won't override
287+
// any GODEBUG values.
288+
if v := os.Getenv("GODEBUG"); cli.currentContext == DefaultContextName || v != "" {
289+
return nil
290+
}
291+
meta, err := cli.contextStore.GetMetadata(cli.currentContext)
292+
if err == nil {
293+
setGoDebug(meta)
294+
}
295+
285296
return nil
286297
}
287298

@@ -475,6 +486,57 @@ func (cli *DockerCli) getDockerEndPoint() (ep docker.Endpoint, err error) {
475486
return resolveDockerEndpoint(cli.contextStore, cn)
476487
}
477488

489+
// setGoDebug is an escape hatch that sets the GODEBUG environment
490+
// variable value using docker context metadata.
491+
//
492+
// {
493+
// "Name": "my-context",
494+
// "Metadata": { "GODEBUG": "x509negativeserial=1" }
495+
// }
496+
//
497+
// WARNING: Setting x509negativeserial=1 allows Go's x509 library to accept
498+
// X.509 certificates with negative serial numbers.
499+
// This behavior is deprecated and non-compliant with current security
500+
// standards (RFC 5280). Accepting negative serial numbers can introduce
501+
// serious security vulnerabilities, including the risk of certificate
502+
// collision or bypass attacks.
503+
// This option should only be used for legacy compatibility and never in
504+
// production environments.
505+
// Use at your own risk.
506+
func setGoDebug(meta store.Metadata) {
507+
fieldName := "GODEBUG"
508+
godebugEnv := os.Getenv(fieldName)
509+
// early return if GODEBUG is already set. We don't want to override what
510+
// the user already sets.
511+
if godebugEnv != "" {
512+
return
513+
}
514+
515+
var cfg any
516+
var ok bool
517+
switch m := meta.Metadata.(type) {
518+
case DockerContext:
519+
cfg, ok = m.AdditionalFields[fieldName]
520+
if !ok {
521+
return
522+
}
523+
case map[string]any:
524+
cfg, ok = m[fieldName]
525+
if !ok {
526+
return
527+
}
528+
default:
529+
return
530+
}
531+
532+
v, ok := cfg.(string)
533+
if !ok {
534+
return
535+
}
536+
// set the GODEBUG environment variable with whatever was in the context
537+
_ = os.Setenv(fieldName, v)
538+
}
539+
478540
func (cli *DockerCli) initialize() error {
479541
cli.init.Do(func() {
480542
cli.dockerEndpoint, cli.initErr = cli.getDockerEndPoint()

cli/command/cli_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818

1919
"github.com/docker/cli/cli/config"
2020
"github.com/docker/cli/cli/config/configfile"
21+
"github.com/docker/cli/cli/context/store"
2122
"github.com/docker/cli/cli/flags"
2223
"github.com/docker/docker/api"
2324
"github.com/docker/docker/api/types"
@@ -353,3 +354,23 @@ func TestHooksEnabled(t *testing.T) {
353354
assert.Check(t, !cli.HooksEnabled())
354355
})
355356
}
357+
358+
func TestSetGoDebug(t *testing.T) {
359+
t.Run("GODEBUG already set", func(t *testing.T) {
360+
t.Setenv("GODEBUG", "val1,val2")
361+
meta := store.Metadata{}
362+
setGoDebug(meta)
363+
assert.Equal(t, "val1,val2", os.Getenv("GODEBUG"))
364+
})
365+
t.Run("GODEBUG in context metadata can set env", func(t *testing.T) {
366+
meta := store.Metadata{
367+
Metadata: DockerContext{
368+
AdditionalFields: map[string]any{
369+
"GODEBUG": "val1,val2=1",
370+
},
371+
},
372+
}
373+
setGoDebug(meta)
374+
assert.Equal(t, "val1,val2=1", os.Getenv("GODEBUG"))
375+
})
376+
}

0 commit comments

Comments
 (0)