{"record":{"id":"afcfdc293f7deee1","repo":"gastownhall/beads","slug":"externaldoltconfig-tlsskipverify-set-without-tlsr","errorCode":null,"errorMessage":"ExternalDoltConfig: TLSSkipVerify set without TLSRequired","messagePattern":"ExternalDoltConfig: TLSSkipVerify set without TLSRequired","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configfile/external_dolt_config.go","lineNumber":89,"sourceCode":"\t\treturn fmt.Errorf(\"ExternalDoltConfig: TLSCert %q is not absolute\", c.TLSCert)\n\t}\n\tif c.TLSKey != \"\" && !filepath.IsAbs(c.TLSKey) {\n\t\treturn fmt.Errorf(\"ExternalDoltConfig: TLSKey %q is not absolute\", c.TLSKey)\n\t}\n\tif c.TLSCACert != \"\" && !filepath.IsAbs(c.TLSCACert) {\n\t\treturn fmt.Errorf(\"ExternalDoltConfig: TLSCACert %q is not absolute\", c.TLSCACert)\n\t}\n\n\tif !c.TLSRequired {\n\t\tswitch {\n\t\tcase c.TLSCACert != \"\":\n\t\t\treturn errors.New(\"ExternalDoltConfig: TLSCACert set without TLSRequired\")\n\t\tcase c.TLSCert != \"\" || c.TLSKey != \"\":\n\t\t\treturn errors.New(\"ExternalDoltConfig: TLSCert/TLSKey set without TLSRequired\")\n\t\tcase c.TLSServerName != \"\":\n\t\t\treturn errors.New(\"ExternalDoltConfig: TLSServerName set without TLSRequired\")\n\t\tcase c.TLSSkipVerify:\n\t\t\treturn errors.New(\"ExternalDoltConfig: TLSSkipVerify set without TLSRequired\")\n\t\t}\n\t}\n\n\tif c.TLSRequired && hasSocket && c.TLSServerName == \"\" && !c.TLSSkipVerify {\n\t\treturn errors.New(\"ExternalDoltConfig: TLSRequired over Socket needs TLSServerName or TLSSkipVerify\")\n\t}\n\n\tif c.KeepAlivePeriod < 0 {\n\t\treturn fmt.Errorf(\"ExternalDoltConfig: KeepAlivePeriod %s is negative\", c.KeepAlivePeriod)\n\t}\n\n\treturn nil\n}\n\nfunc (c ExternalDoltConfig) TLSClientConfig() (*tls.Config, error) {\n\tif !c.TLSRequired {\n\t\treturn nil, nil\n\t}","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/configfile/external_dolt_config.go#L71-L107","documentation":"Validate() rejects TLSSkipVerify=true when TLSRequired is false. TLSSkipVerify is an explicit opt-in to insecure TLS (InsecureSkipVerify in TLSClientConfig), which only exists when TLSRequired is on; setting it on a plaintext config is contradictory and would be silently ignored. Failing loudly prevents operators from believing they disabled certificate verification when TLS was never active.","triggerScenarios":"Constructing ExternalDoltConfig with TLSSkipVerify=true (tls_skip_verify: true in YAML, or the testing flag left on) while TLSRequired is false, then calling Validate() directly or via buildProxiedServerClientInfo / NewExternalDoltServer / NewExternalDoltServerUOWProvider.","commonSituations":"Pointing the client at a self-signed-cert server and setting skip-verify first but forgetting tls_required; a test/dev flag (BEADS test configs set TLSSkipVerify) leaking into a production config where tls_required got dropped; copy-pasting a debug config snippet.","solutions":["Set TLSRequired: true in the config — skip-verify only applies to a TLS connection.","Remove TLSSkipVerify if the endpoint is plaintext.","Prefer a proper fix over skip-verify: keep TLSRequired true and supply TLSCACert (and TLSServerName) for the self-signed server."],"exampleFix":"// before (YAML)\nexternal:\n  host: dolt.internal\n  port: 3307\n  tls_skip_verify: true\n// after\nexternal:\n  host: dolt.internal\n  port: 3307\n  tls_required: true\n  tls_skip_verify: true  # dev only; prefer tls_ca_cert in production","handlingStrategy":"validation","validationCode":"func validateSkipVerify(cfg configfile.ExternalDoltConfig, allowInsecure bool) error {\n\tif cfg.TLSSkipVerify && !cfg.TLSRequired {\n\t\treturn fmt.Errorf(\"tls_skip_verify requires tls_required: true\")\n\t}\n\tif cfg.TLSSkipVerify && !allowInsecure {\n\t\treturn fmt.Errorf(\"tls_skip_verify not allowed in this environment\")\n\t}\n\treturn cfg.Validate()\n}","typeGuard":null,"tryCatchPattern":"if err := cfg.Validate(); err != nil {\n\tif strings.Contains(err.Error(), \"TLSSkipVerify set without TLSRequired\") {\n\t\t// set tls_required: true or drop tls_skip_verify, then retry\n\t}\n\treturn err\n}","preventionTips":["Keep TLSSkipVerify confined to test configs; gate it behind an explicit dev/test env flag.","Always pair tls_required with the skip-verify flag in generated configs.","Validate the struct at load time rather than at server start."],"tags":["tls","insecure-skip-verify","config-validation","external-dolt"],"backgroundTag":"tls-config-mismatch","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}