{"record":{"id":"f318312507e357c6","repo":"henrygd/beszel","slug":"no-selinux-tools-available-semanage-restorecon-or","errorCode":null,"errorMessage":"no SELinux tools available (semanage/restorecon or chcon)","messagePattern":"no SELinux tools available \\(semanage/restorecon or chcon\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/ghupdate/selinux.go","lineNumber":36,"sourceCode":"\t\treturn nil\n\t}\n\n\tColorPrint(ColorYellow, \"SELinux is enabled; applying context…\")\n\n\t// Try persistent context via semanage+restorecon\n\tif success := trySemanageRestorecon(path); success {\n\t\treturn nil\n\t}\n\n\t// Fallback to temporary context via chcon\n\tif chconPath, err := exec.LookPath(\"chcon\"); err == nil {\n\t\tif err := exec.Command(chconPath, \"-t\", \"bin_t\", path).Run(); err != nil {\n\t\t\treturn fmt.Errorf(\"chcon failed: %w\", err)\n\t\t}\n\t\treturn nil\n\t}\n\n\treturn fmt.Errorf(\"no SELinux tools available (semanage/restorecon or chcon)\")\n}\n\n// trySemanageRestorecon attempts to set persistent SELinux context using semanage and restorecon.\n// Returns true if successful, false otherwise.\nfunc trySemanageRestorecon(path string) bool {\n\tsemanagePath, err := exec.LookPath(\"semanage\")\n\tif err != nil {\n\t\treturn false\n\t}\n\n\trestoreconPath, err := exec.LookPath(\"restorecon\")\n\tif err != nil {\n\t\treturn false\n\t}\n\n\t// Try to add the fcontext rule; if it already exists, try to modify it\n\tif err := exec.Command(semanagePath, \"fcontext\", \"-a\", \"-t\", \"bin_t\", path).Run(); err != nil {\n\t\t// Rule may already exist, try modify instead","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/henrygd/beszel/blob/b38fb7dafa60812cc22e6a84ce313e94f1ce0a32/internal/ghupdate/selinux.go#L18-L54","documentation":"HandleSELinuxContext first tries persistent SELinux relabeling via semanage/restorecon, then falls back to chcon. If none of these tools can be found on PATH (exec.LookPath fails for chcon as the last fallback), it returns this error. It indicates an SELinux system (or one the function treats as such) with no available tooling to apply a bin_t context.","triggerScenarios":"Calling HandleSELinuxContext on a host where neither semanage, restorecon, nor chcon is installed or on PATH. Tests TestHandleSELinuxContext_NoSELinux and TestHandleSELinuxContext_InvalidPath exercise this path.","commonSituations":"Minimal/scratch container images or distroless systems without SELinux userland; running from an environment with a stripped PATH (cron, systemd unit with minimal Environment); SELinux utilities simply never installed on the host.","solutions":["Install SELinux userland tools: `dnf install policycoreutils-python-utils` (semanage/restorecon) or at minimum `yum install policycoreutils` (chcon).","Ensure PATH includes /usr/sbin and /sbin when running from systemd/cron, since SELinux tools often live there.","If the host does not use SELinux, guard the call so HandleSELinuxContext is skipped (e.g. check /sys/fs/selinux exists) — this error is expected on non-SELinux systems.","Relabel manually after update: `sudo chcon -t bin_t /path/to/binary`."],"exampleFix":"// before: minimal container without SELinux tools\n// error: no SELinux tools available (semanage/restorecon or chcon)\n\n// after: install tooling or skip when SELinux is absent\nif _, err := os.Stat(\"/sys/fs/selinux\"); err == nil {\n    if err := HandleSELinuxContext(binPath); err != nil { log.Warn(err) }\n}","handlingStrategy":"fallback","validationCode":"func selinuxManaged() bool {\n    if _, err := os.Stat(\"/sys/fs/selinux\"); err != nil { return false }\n    for _, t := range []string{\"semanage\", \"restorecon\", \"chcon\"} {\n        if _, err := exec.LookPath(t); err == nil { return true }\n    }\n    return false\n}\n// call HandleSELinuxContext only if selinuxManaged()","typeGuard":"func hasAnySELinuxTool() bool {\n    for _, t := range []string{\"semanage\", \"restorecon\", \"chcon\"} {\n        if p, _ := exec.LookPath(t); p != \"\" { return true }\n    }\n    return false\n}","tryCatchPattern":"err := HandleSELinuxContext(binPath)\nif err != nil && strings.Contains(err.Error(), \"no SELinux tools available\") {\n    log.Info(\"SELinux tooling absent; skipping context fix\")\n    return nil\n}","preventionTips":["Skip the call on non-SELinux systems (check /sys/fs/selinux) — this error is expected there.","Bake SELinux userland into container images if relabeling is required at runtime.","Ensure PATH includes /usr/sbin for systemd/cron-launched updaters.","Provide a manual relabel step in deployment docs as fallback."],"tags":["selinux","security","linux","missing-tool"],"backgroundTag":"selinux-context-failed","analyzedSha":"b38fb7dafa60812cc22e6a84ce313e94f1ce0a32","analyzedAt":"2026-08-31T15:10:10.149Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}