{"record":{"id":"db0186228f95efd3","repo":"golang/go","slug":"fips-140-3-mode-is-incompatible-with-the-purego-bu","errorCode":null,"errorMessage":"FIPS 140-3 mode is incompatible with the purego build tag","messagePattern":"FIPS 140-3 mode is incompatible with the purego build tag","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/internal/fips140/fips140.go","lineNumber":38,"sourceCode":"\tcase \"on\", \"only\":\n\t\tEnabled = true\n\tcase \"debug\":\n\t\tEnabled = true\n\t\tdebug = true\n\tcase \"off\", \"\":\n\tdefault:\n\t\tpanic(\"fips140: unknown GODEBUG setting fips140=\" + v)\n\t}\n}\n\n// Supported returns an error if FIPS 140-3 mode can't be enabled.\nfunc Supported() error {\n\t// Keep this in sync with fipsSupported in cmd/dist/test.go.\n\n\t// The purego tag changes too much of the implementation to claim the\n\t// validation still applies.\n\tif puregoEnabled {\n\t\treturn errors.New(\"FIPS 140-3 mode is incompatible with the purego build tag\")\n\t}\n\n\t// ASAN disapproves of reading swaths of global memory in fips140/check.\n\t// One option would be to expose runtime.asanunpoison through\n\t// crypto/internal/fips140deps and then call it to unpoison the range\n\t// before reading it, but it is unclear whether that would then cause\n\t// false negatives. For now, FIPS+ASAN doesn't need to work.\n\tif asanEnabled {\n\t\treturn errors.New(\"FIPS 140-3 mode is incompatible with ASAN\")\n\t}\n\n\t// See EnableFIPS in cmd/internal/obj/fips.go for commentary.\n\t// Also, js/wasm and windows/386 don't have good enough timers\n\t// for the CPU jitter entropy source.\n\tswitch {\n\tcase runtime.GOARCH == \"wasm\",\n\t\truntime.GOOS == \"windows\" && runtime.GOARCH == \"386\",\n\t\truntime.GOOS == \"openbsd\", // due to -fexecute-only, see #70880","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/fips140/fips140.go#L20-L56","documentation":"Returned by fips140.Supported() when the purego build tag is active. FIPS 140-3 validation only covers the assembly-backed implementations; purego replaces too much crypto code with Go-level implementations, invalidating the validation boundary.","triggerScenarios":"Building with -tags purego (or GOFLAGS containing it) and then calling fips140.Supported() or attempting to enable FIPS mode via GOFIPS140=1.","commonSituations":"Cross-compiling without assembly support; CI pipelines that add purego globally; tooling that injects purego for portability on unsupported architectures.","solutions":["Drop the purego build tag for the FIPS build target.","Use a supported architecture (amd64, arm64, s390x) where assembly backends exist and purego is not required.","If you need purego for portability, do not also enable FIPS mode — pick one.","Audit GOFLAGS, makefiles, and Dockerfiles for stray -tags=purego."],"exampleFix":"# before\nGOFLAGS=\"-tags=purego\" GOFIPS140=1 go build ./...\n\n# after\nGOFIPS140=1 go build ./...","handlingStrategy":"validation","validationCode":"if err := fips140.Supported(); err != nil {\n    if strings.Contains(err.Error(), \"purego\") {\n        log.Fatal(\"FIPS mode requires assembly backends; drop the purego build tag\")\n    }\n    log.Fatalf(\"FIPS unsupported: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := fips140.Supported(); err != nil {\n    // surface at deploy time before serving traffic\n    return fmt.Errorf(\"refusing to start: FIPS mode unavailable: %w\", err)\n}","preventionTips":["Call fips140.Supported() at process startup and fail fast.","Audit GOFLAGS, Dockerfiles, and CI for stray -tags=purego when FIPS is required.","Build on a supported architecture so purego is unnecessary."],"tags":["fips140","build-tags","purego","config","compatibility"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}