Skip to content

Commit 0155c26

Browse files
authored
Merge pull request #6371 from Benehiko/support-fallback-negative-certs
Add escape hatch for GODEBUG=x509negativeserial
2 parents b3cd9d4 + 72f7933 commit 0155c26

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
@@ -281,6 +281,17 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...CLIOption)
281281
}
282282
filterResourceAttributesEnvvar()
283283

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

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

488+
// setGoDebug is an escape hatch that sets the GODEBUG environment
489+
// variable value using docker context metadata.
490+
//
491+
// {
492+
// "Name": "my-context",
493+
// "Metadata": { "GODEBUG": "x509negativeserial=1" }
494+
// }
495+
//
496+
// WARNING: Setting x509negativeserial=1 allows Go's x509 library to accept
497+
// X.509 certificates with negative serial numbers.
498+
// This behavior is deprecated and non-compliant with current security
499+
// standards (RFC 5280). Accepting negative serial numbers can introduce
500+
// serious security vulnerabilities, including the risk of certificate
501+
// collision or bypass attacks.
502+
// This option should only be used for legacy compatibility and never in
503+
// production environments.
504+
// Use at your own risk.
505+
func setGoDebug(meta store.Metadata) {
506+
fieldName := "GODEBUG"
507+
godebugEnv := os.Getenv(fieldName)
508+
// early return if GODEBUG is already set. We don't want to override what
509+
// the user already sets.
510+
if godebugEnv != "" {
511+
return
512+
}
513+
514+
var cfg any
515+
var ok bool
516+
switch m := meta.Metadata.(type) {
517+
case DockerContext:
518+
cfg, ok = m.AdditionalFields[fieldName]
519+
if !ok {
520+
return
521+
}
522+
case map[string]any:
523+
cfg, ok = m[fieldName]
524+
if !ok {
525+
return
526+
}
527+
default:
528+
return
529+
}
530+
531+
v, ok := cfg.(string)
532+
if !ok {
533+
return
534+
}
535+
// set the GODEBUG environment variable with whatever was in the context
536+
_ = os.Setenv(fieldName, v)
537+
}
538+
477539
func (cli *DockerCli) initialize() error {
478540
cli.init.Do(func() {
479541
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/moby/moby/api/types"
2324
"github.com/moby/moby/client"
@@ -352,3 +353,23 @@ func TestHooksEnabled(t *testing.T) {
352353
assert.Check(t, !cli.HooksEnabled())
353354
})
354355
}
356+
357+
func TestSetGoDebug(t *testing.T) {
358+
t.Run("GODEBUG already set", func(t *testing.T) {
359+
t.Setenv("GODEBUG", "val1,val2")
360+
meta := store.Metadata{}
361+
setGoDebug(meta)
362+
assert.Equal(t, "val1,val2", os.Getenv("GODEBUG"))
363+
})
364+
t.Run("GODEBUG in context metadata can set env", func(t *testing.T) {
365+
meta := store.Metadata{
366+
Metadata: DockerContext{
367+
AdditionalFields: map[string]any{
368+
"GODEBUG": "val1,val2=1",
369+
},
370+
},
371+
}
372+
setGoDebug(meta)
373+
assert.Equal(t, "val1,val2=1", os.Getenv("GODEBUG"))
374+
})
375+
}

0 commit comments

Comments
 (0)