diff --git a/python/vyos/utils/boot.py b/python/vyos/utils/boot.py
index 3aecbec64..708bef14d 100644
--- a/python/vyos/utils/boot.py
+++ b/python/vyos/utils/boot.py
@@ -1,35 +1,39 @@
-# Copyright 2023 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2023-2024 VyOS maintainers and contributors <maintainers@vyos.io>
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
 # License as published by the Free Software Foundation; either
 # version 2.1 of the License, or (at your option) any later version.
 #
 # This library is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 # Lesser General Public License for more details.
 #
 # You should have received a copy of the GNU Lesser General Public
 # License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 
 import os
 
 def boot_configuration_complete() -> bool:
     """ Check if the boot config loader has completed
     """
     from vyos.defaults import config_status
     if os.path.isfile(config_status):
         return True
     return False
 
 def boot_configuration_success() -> bool:
     from vyos.defaults import config_status
     try:
         with open(config_status) as f:
             res = f.read().strip()
     except FileNotFoundError:
         return False
     if int(res) == 0:
         return True
     return False
+
+def is_uefi_system() -> bool:
+    efi_fw_dir = '/sys/firmware/efi'
+    return os.path.exists(efi_fw_dir) and os.path.isdir(efi_fw_dir)
diff --git a/python/vyos/utils/system.py b/python/vyos/utils/system.py
index fca93d118..7b12efb14 100644
--- a/python/vyos/utils/system.py
+++ b/python/vyos/utils/system.py
@@ -1,141 +1,149 @@
 # Copyright 2023-2024 VyOS maintainers and contributors <maintainers@vyos.io>
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
 # License as published by the Free Software Foundation; either
 # version 2.1 of the License, or (at your option) any later version.
 #
 # This library is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 # Lesser General Public License for more details.
 #
 # You should have received a copy of the GNU Lesser General Public
 # License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 
 import os
 from subprocess import run
 
 def sysctl_read(name: str) -> str:
     """Read and return current value of sysctl() option
 
     Args:
         name (str): sysctl key name
 
     Returns:
         str: sysctl key value
     """
     tmp = run(['sysctl', '-nb', name], capture_output=True)
     return tmp.stdout.decode()
 
 def sysctl_write(name: str, value: str | int) -> bool:
     """Change value via sysctl()
 
     Args:
         name (str): sysctl key name
         value (str | int): sysctl key value
 
     Returns:
         bool: True if changed, False otherwise
     """
     # convert other types to string before comparison
     if not isinstance(value, str):
         value = str(value)
     # do not change anything if a value is already configured
     if sysctl_read(name) == value:
         return True
     # return False if sysctl call failed
     if run(['sysctl', '-wq', f'{name}={value}']).returncode != 0:
         return False
     # compare old and new values
     # sysctl may apply value, but its actual value will be
     # different from requested
     if sysctl_read(name) == value:
         return True
     # False in other cases
     return False
 
 def sysctl_apply(sysctl_dict: dict[str, str], revert: bool = True) -> bool:
     """Apply sysctl values.
 
     Args:
         sysctl_dict (dict[str, str]): dictionary with sysctl keys with values
         revert (bool, optional): Revert to original values if new were not
         applied. Defaults to True.
 
     Returns:
         bool: True if all params configured properly, False in other cases
     """
     # get current values
     sysctl_original: dict[str, str] = {}
     for key_name in sysctl_dict.keys():
         sysctl_original[key_name] = sysctl_read(key_name)
     # apply new values and revert in case one of them was not applied
     for key_name, value in sysctl_dict.items():
         if not sysctl_write(key_name, value):
             if revert:
                 sysctl_apply(sysctl_original, revert=False)
             return False
     # everything applied
     return True
 
 def find_device_file(device):
     """ Recurively search /dev for the given device file and return its full path.
         If no device file was found 'None' is returned """
     from fnmatch import fnmatch
 
     for root, dirs, files in os.walk('/dev'):
         for basename in files:
             if fnmatch(basename, device):
                 return os.path.join(root, basename)
 
     return None
 
 def load_as_module(name: str, path: str):
     import importlib.util
 
     spec = importlib.util.spec_from_file_location(name, path)
     mod = importlib.util.module_from_spec(spec)
     spec.loader.exec_module(mod)
     return mod
 
 def load_as_module_source(name: str, path: str):
     """ Necessary modification of load_as_module for files without *.py
     extension """
     import importlib.util
     from importlib.machinery import SourceFileLoader
 
     loader = SourceFileLoader(name, path)
     spec = importlib.util.spec_from_loader(name, loader)
     mod = importlib.util.module_from_spec(spec)
     spec.loader.exec_module(mod)
     return mod
 
 def get_uptime_seconds():
     """ Returns system uptime in seconds """
     from re import search
     from vyos.utils.file import read_file
 
     data = read_file("/proc/uptime")
     seconds = search(r"([0-9\.]+)\s", data).group(1)
     res  = int(float(seconds))
 
     return res
 
 def get_load_averages():
     """ Returns load averages for 1, 5, and 15 minutes as a dict """
     from re import search
     from vyos.utils.file import read_file
     from vyos.utils.cpu import get_core_count
 
     data = read_file("/proc/loadavg")
     matches = search(r"\s*(?P<one>[0-9\.]+)\s+(?P<five>[0-9\.]+)\s+(?P<fifteen>[0-9\.]+)\s*", data)
 
     core_count = get_core_count()
 
     res = {}
     res[1]  = float(matches["one"]) / core_count
     res[5]  = float(matches["five"]) / core_count
     res[15] = float(matches["fifteen"]) / core_count
 
     return res
+
+def get_secure_boot_state() -> bool:
+    from vyos.utils.process import cmd
+    from vyos.utils.boot import is_uefi_system
+    if not is_uefi_system():
+        return False
+    tmp = cmd('mokutil --sb-state')
+    return bool('enabled' in tmp)
diff --git a/src/etc/sudoers.d/vyos b/src/etc/sudoers.d/vyos
index 63a944f41..67d7babc4 100644
--- a/src/etc/sudoers.d/vyos
+++ b/src/etc/sudoers.d/vyos
@@ -1,60 +1,63 @@
 #
 # VyOS modifications to sudo configuration
 #
 Defaults syslog_goodpri=info
 Defaults env_keep+=VYATTA_*
 
 #
 # Command groups allowed for operator users
 #
 Cmnd_Alias IPTABLES = /sbin/iptables --list -n,\
 		      /sbin/iptables -L -vn,\
                       /sbin/iptables -L * -vn,\
 		      /sbin/iptables -t * -L *, \
                       /sbin/iptables -Z *,\
 		      /sbin/iptables -Z -t nat, \
                       /sbin/iptables -t * -Z *
 Cmnd_Alias IP6TABLES = /sbin/ip6tables -t * -Z *, \
                        /sbin/ip6tables -t * -L *
 Cmnd_Alias CONNTRACK = /usr/sbin/conntrack -L *, \
                        /usr/sbin/conntrack -G *, \
 		       /usr/sbin/conntrack -E *
 Cmnd_Alias IPFLUSH = /sbin/ip route flush cache, \
 		     /sbin/ip route flush cache *,\
 		     /sbin/ip neigh flush to *, \
 		     /sbin/ip neigh flush dev *, \
                      /sbin/ip -f inet6 route flush cache, \
 		     /sbin/ip -f inet6 route flush cache *,\
 		     /sbin/ip -f inet6 neigh flush to *, \
 		     /sbin/ip -f inet6 neigh flush dev *
 Cmnd_Alias ETHTOOL = /sbin/ethtool -p *, \
                      /sbin/ethtool -S *, \
                      /sbin/ethtool -a *, \
                      /sbin/ethtool -c *, \
                      /sbin/ethtool -i *
 Cmnd_Alias DMIDECODE = /usr/sbin/dmidecode
 Cmnd_Alias DISK    = /usr/bin/lsof, /sbin/fdisk -l *, /sbin/sfdisk -d *
 Cmnd_Alias DATE    = /bin/date, /usr/sbin/ntpdate
 Cmnd_Alias PPPOE_CMDS = /sbin/pppd, /sbin/poff, /usr/sbin/pppstats
 Cmnd_Alias PCAPTURE = /usr/bin/tcpdump
 Cmnd_Alias HWINFO   = /usr/bin/lspci
 Cmnd_Alias FORCE_CLUSTER = /usr/share/heartbeat/hb_takeover, \
                            /usr/share/heartbeat/hb_standby
 Cmnd_Alias DIAGNOSTICS = /bin/ip vrf exec * /bin/ping *,       \
                          /bin/ip vrf exec * /bin/traceroute *, \
                          /bin/ip vrf exec * /usr/bin/mtr *, \
                          /usr/libexec/vyos/op_mode/*
 Cmnd_Alias KEA_IP6_ROUTES = /sbin/ip -6 route replace *,\
                            /sbin/ip -6 route del *
 %operator ALL=NOPASSWD: DATE, IPTABLES, ETHTOOL, IPFLUSH, HWINFO, \
 			PPPOE_CMDS, PCAPTURE, /usr/sbin/wanpipemon, \
                         DMIDECODE, DISK, CONNTRACK, IP6TABLES,  \
                         FORCE_CLUSTER, DIAGNOSTICS
 
 # Allow any user to run files in sudo-users
 %users ALL=NOPASSWD: /opt/vyatta/bin/sudo-users/
 
 # Allow members of group sudo to execute any command
 %sudo ALL=NOPASSWD: ALL
 
+# Allow any user to query Machine Owner Key status
+%sudo ALL=NOPASSWD: /usr/bin/mokutil
+
 _kea ALL=NOPASSWD: KEA_IP6_ROUTES
diff --git a/src/op_mode/version.py b/src/op_mode/version.py
index 09d69ad1d..71a40dd50 100755
--- a/src/op_mode/version.py
+++ b/src/op_mode/version.py
@@ -1,88 +1,97 @@
 #!/usr/bin/env python3
 #
 # Copyright (C) 2016-2024 VyOS maintainers and contributors
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License version 2 or later as
 # published by the Free Software Foundation.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 # Purpose:
 #    Displays image version and system information.
 #    Used by the "run show version" command.
 
 import sys
 import typing
 
 import vyos.opmode
 import vyos.version
 import vyos.limericks
 
+from vyos.utils.boot import is_uefi_system
+from vyos.utils.system import get_secure_boot_state
+
 from jinja2 import Template
 
 version_output_tmpl = """
 Version:          VyOS {{version}}
 Release train:    {{release_train}}
 Release flavor:   {{flavor}}
 
 Built by:         {{built_by}}
 Built on:         {{built_on}}
 Build UUID:       {{build_uuid}}
 Build commit ID:  {{build_git}}
 {%- if build_comment %}
 Build comment:    {{build_comment}}
 {% endif %}
 
 Architecture:     {{system_arch}}
 Boot via:         {{boot_via}}
 System type:      {{system_type}}
+Secure Boot:      {{secure_boot}}
 
 Hardware vendor:  {{hardware_vendor}}
 Hardware model:   {{hardware_model}}
 Hardware S/N:     {{hardware_serial}}
 Hardware UUID:    {{hardware_uuid}}
 
 Copyright:        VyOS maintainers and contributors
 {%- if limerick %}
 {{limerick}}
 {% endif -%}
 """
 
 def _get_raw_data(funny=False):
     version_data = vyos.version.get_full_version_data()
+    version_data["secure_boot"] = "n/a (BIOS)"
+    if is_uefi_system():
+        version_data["secure_boot"] = "disabled"
+        if get_secure_boot_state():
+            version_data["secure_boot"] = "enabled"
 
     if funny:
         version_data["limerick"] = vyos.limericks.get_random()
 
     return version_data
 
 def _get_formatted_output(version_data):
     tmpl = Template(version_output_tmpl)
     return tmpl.render(version_data).strip()
 
 def show(raw: bool, funny: typing.Optional[bool]):
     """ Display neighbor table contents """
     version_data = _get_raw_data(funny=funny)
 
     if raw:
         return version_data
     else:
         return _get_formatted_output(version_data)
 
 
 if __name__ == '__main__':
     try:
         res = vyos.opmode.run(sys.modules[__name__])
         if res:
             print(res)
     except (ValueError, vyos.opmode.Error) as e:
         print(e)
         sys.exit(1)