Controlling access to USB storage devices is a foundational practice for maintaining data integrity and preventing unauthorized data exfiltration in enterprise environments. As threats from removable media persist—ranging from insider data leaks to malware-laden USB drives—IT administrators and Managed Service Providers (MSPs) must enforce strict policies on USB usage. One effective and scalable method is scripting control at the kernel module level. This blog post dives deep into a robust shell script designed to enable, disable, or configure USB storage devices on Linux with shell scripting.
Background
On Linux systems, USB storage access is governed by kernel modules—specifically, usb-storage and uas (USB Attached SCSI). These modules can be automatically loaded when devices are connected (implicit loading) or manually invoked (explicit loading). By blocking or permitting these modules at the system level, IT professionals can effectively control USB storage device behavior across fleets of Linux endpoints.
The script in question is built for automation, policy enforcement, and compatibility with RMM platforms like NinjaOne. It creates and manages configuration files in /etc/modprobe.d/, updates the initial RAM filesystem (initramfs), and can optionally trigger a system reboot—making it a complete solution for USB device governance.
The Script:
#!/usr/bin/env bash # Description: Enable or disable USB storage devices on Linux. # By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use. # Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. # Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. # Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. # Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. # Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. # Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. # EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA). # # There are two methods of loading USB storage drivers that allow mounting of USB storage devices: # 1. Implicit loading: The USB storage driver is loaded automatically when a USB storage device is connected. # 2. Explicit loading: The USB storage driver is loaded manually by a user, program, or script. # # Release Notes: Initial Release # # Notes: This will create config files in /etc/modprobe.d/ as needed to block USB storage devices. # # Usage: [-Enable | -Disable] [-Reboot] # # Preset Parameter: --help # Displays the help menu. # # Preset Parameter: -Enable # Enables USB storage devices. # # Preset Parameter: -Disable # Disables USB storage devices. # # Preset Parameter: -Reboot # Reboots the system, if needed, after enabling or disabling USB storage devices. # Functions # Print an error message and exit with a specific status code die() { local _ret="${2:-1}" test "${_PRINT_HELP:-no}" = yes && print_help >&2 echo "$1" >&2 exit "${_ret}" } print_help() { printf '\n\n%s\n\n' 'Usage: [-Enable | -Disable]' printf ' %s\n' '-Enable' printf ' Enables USB storage devices' printf ' %s\n' '-Disable' printf ' Disables USB storage devices' } # Set the default values _arg_reboot="false" # Parse the command-line arguments parse_commandline() { while test $# -gt 0; do _key="$1" case "$_key" in -Enable | --Enable | -enable | --enable | -e | --e) _arg_action="Enable" ;; -Disable | --Disable | -disable | --disable | -d | --d) _arg_action="Disable" ;; --Reboot | --reboot | -Reboot | -reboot | -r | --r) _arg_reboot="true" ;; --help | -help | -h | --h) _PRINT_HELP=yes die "" 0 ;; *) _PRINT_HELP=yes die "[Error] Got an unexpected argument '$1'" 1 ;; esac shift done } parse_commandline "$@" # Exit if not running as root if [[ $EUID -ne 0 ]]; then die "[Error] This script must be run as root or SYSTEM from NinjaRMM" 1 fi # If script form variables are used, replace the command line parameters with their value. if [[ -n "${action}" ]] && [[ "${action}" == "Enable" ]]; then _arg_action="Enable" elif [[ -n "${action}" ]] && [[ "${action}" == "Disable" ]]; then _arg_action="Disable" fi if [[ "${reboot}" == "true" ]]; then _arg_reboot="true" fi # Check if action is empty if [[ -z "${_arg_action}" ]]; then die "Invalid action. Use Enable or Disable" 1 fi # Variables # Modprobe.d folder modprobFolder="/etc/modprobe.d" # Config file configFile="${modprobFolder}/ninja-usb-block.conf" # Check if modprobe.d folder does not exists if ! [ -d "${modprobFolder}" ]; then die "[Error] Modprobe folder does not exist" 1 fi # Check if usb-storage and uas kenel drivers are modules if ! modprobe -n uas >/dev/null 2>&1; then die "[Error] USB Attached SCSI driver(uas) must be compiled as a kernel module" 1 fi if ! modprobe -n usb-storage >/dev/null 2>&1; then die "[Error] USB storage(usb-storage) driver must be compiled as a kernel module" 1 fi if [[ "${_arg_action}" == "Enable" ]]; then # Enable USB storage # Check if our file exists if [ -f "${configFile}" ]; then echo "[Info] Enabling USB storage devices" # Remove our config file rm "${configFile}" echo "[Info] Enabled USB storage devices" else echo "[Info] USB storage devices are already enabled" fi # Remove other blocks USB storage in other files for file in "${modprobFolder}"/*; do # Remove implicit USB Storage block if grep -q "blacklist usb_storage" "${file}"; then echo "[Info] Removing implicit USB Storage block in ${file}" sed -i '/blacklist usb_storage/d' "${file}" echo "[Info] Removed implicit USB Storage block in ${file}" fi # Remove implicit USB Attached SCSI block if grep -q "blacklist uas" "${file}"; then echo "[Info] Removing implicit USB Attached SCSI block in ${file}" sed -i '/blacklist uas/d' "${file}" echo "[Info] Removed implicit USB Attached SCSI block in ${file}" fi # Remove explicit USB Storage driver block if grep -q "install usb-storage /bin/true" "${file}"; then echo "[Info] Removing explicit USB Storage block in ${file}" sed -i '/install usb-storage \/bin\/true/d' "${file}" echo "[Info] Removed explicit USB Storage block in ${file}" fi # Remove explicit USB Attached SCSI driver block if grep -q "install uas /bin/true" "${file}"; then echo "[Info] Removing explicit USB Attached SCSI block in ${file}" sed -i '/install uas \/bin\/true/d' "${file}" echo "[Info] Removed explicit USB Attached SCSI block in ${file}" fi done # Check that update-initramfs command exists if command -v update-initramfs >/dev/null 2>&1; then # Update the initramfs echo "[Info] Updating initramfs" update-initramfs -u >/dev/null 2>&1 echo "[Info] Updated initramfs" fi if [[ "${_arg_reboot}" == "true" ]]; then echo "[Info] Rebooting the system to enable USB storage devices" # Shutdown in 1 minute shutdown -r +1 else echo "[Info] USB storage devices are enabled, please reboot the system" fi elif [[ "${_arg_action}" == "Disable" ]]; then # Disable USB storage # Variables to determine if we should block the drivers blacklist_uas="false" blacklist_usb_storage="false" block_uas="false" block_usb_storage="false" # Check if usb_storage or uas is blocked in other files for file in "${modprobFolder}"/*; do # Check if implicit loading is already blocked if grep -q "blacklist uas" "${file}"; then echo "[Info] USB Attached SCSI drivers are already implicitly blocked in ${file}" else blacklist_uas="true" fi # Check if implicit loading is already blocked if grep -q "blacklist usb_storage" "${file}"; then echo "[Info] USB storage drivers are already implicitly blocked in ${file}" else blacklist_usb_storage="true" fi # Check if explicit loading is already blocked if grep -q "install uas /bin/true" "${file}"; then echo "[Info] USB Attached SCSI drivers are already explicitly blocked in ${file}" else block_uas="true" fi # Check if explicit loading is already blocked if grep -q "install uas /bin/true" "${file}"; then echo "[Info] USB storage drivers are already explicitly blocked in ${file}" else block_usb_storage="true" fi done if [ "${blacklist_uas}" == "true" ]; then echo "[Info] Implicitly Disabling USB Attached SCSI driver" # Check if config file exists if ! [ -f "${configFile}" ]; then echo "[Info] Creating blocklist config file (${configFile})" touch "${configFile}" fi # Write the line to the file echo "blacklist uas" >>"${configFile}" fi if [ "${blacklist_usb_storage}" == "true" ]; then echo "[Info] Implicitly Disabling USB storage driver" # Check if config file exists if ! [ -f "${configFile}" ]; then echo "[Info] Creating blocklist config file (${configFile})" touch "${configFile}" fi # Write the line to the file echo "blacklist usb_storage" >>"${configFile}" fi if [ "${block_uas}" == "true" ]; then echo "[Info] Explicitly Disabling USB Attached SCSI driver" # Check if uas config file exists if ! [ -f "${modprobFolder}" ]; then echo "[Info] Creating UAS config file (${modprobFolder}/uas.conf)" touch "${modprobFolder}/uas.conf" fi # Write the line to the file echo "install uas /bin/true" >>"${modprobFolder}/uas.conf" fi if [ "${block_usb_storage}" == "true" ]; then echo "[Info] Explicitly Disabling USB storage driver" # Check if usb-storage config file exists if ! [ -f "${modprobFolder}" ]; then echo "[Info] Creating USB storage config file (${modprobFolder}/usb-storage.conf)" touch "${modprobFolder}/usb-storage.conf" fi # Write the line to the file echo "install usb-storage /bin/true" >>"${modprobFolder}/usb-storage.conf" fi # Unload the modules echo "[Info] Unloading USB storage modules" modprobe -r uas >/dev/null 2>&1 modprobe -r usb_storage >/dev/null 2>&1 rmmod uas >/dev/null 2>&1 rmmod usb_storage >/dev/null 2>&1 # Check if the modules are still loaded modules_unloaded="true" if lsmod | grep -q uas; then modules_unloaded="false" fi if lsmod | grep -q usb_storage; then modules_unloaded="false" fi # Check that update-initramfs command exists if command -v update-initramfs >/dev/null 2>&1; then # Update the initramfs echo "[Info] Updating initramfs" update-initramfs -u >/dev/null 2>&1 echo "[Info] Updated initramfs" # Set to false so we can reboot or warn that a reboot is needed modules_unloaded="false" if [[ "${_arg_reboot}" == "false" ]]; then echo "[Warn] USB storage devices can still be mounted, please reboot the system" fi fi if [ "${modules_unloaded}" == "true" ]; then echo "[Info] Unloaded USB storage modules" else if [[ "${_arg_reboot}" == "true" ]]; then echo "[Info] USB storage devices are still mounted, rebooting the system" # Shutdown in 1 minute shutdown -r +1 else echo "[Warn] USB storage devices are still mounted, please unmount them and rerun this script OR reboot the system" fi fi else die "[Error] Invalid parameter. Use -Enable or -Disable" 1 fi
Detailed Breakdown
Here’s how the script functions step-by-step:
1. Command-Line Parsing
The script accepts the following flags:
- -Enable: Allows USB storage by removing related kernel module restrictions.
- -Disable: Prevents USB storage by applying kernel module blacklists and explicit loading blocks.
- -Reboot: Optional flag to reboot the machine after the change.
- –help: Displays usage instructions.
2. Privilege Check
The script verifies it’s being run with root privileges—essential for kernel-level changes.
3. Module Detection
It confirms that usb-storage and uas are compiled as kernel modules, a prerequisite for the changes to be effective.
4. Enabling USB Storage
When -Enable is invoked:
- The script removes its own config file (ninja-usb-block.conf).
- It scans other .conf files in /etc/modprobe.d/ and deletes any blacklist or explicit load-block directives.
- It regenerates initramfs to reflect the changes.
- Optionally, it schedules a reboot.
5. Disabling USB Storage
When -Disable is used:
- The script writes blacklist (blacklist usb_storage, blacklist uas) and install block (install usb-storage /bin/true) directives into dedicated .conf files.
- It forcibly unloads the kernel modules using modprobe -r and rmmod.
- It validates module removal via lsmod.
- It updates initramfs and, if needed, reboots the system.
Potential Use Cases
Case Study: Securing Developer Laptops
An MSP managing Linux developer workstations wants to prevent code or proprietary data from being exfiltrated via USB drives. Using NinjaOne, the admin deploys this shell script with the -Disable -Reboot flags. All targeted systems become USB-storage restricted upon next boot. During a code freeze, USB access is temporarily re-enabled via a scheduled task with -Enable.
This method ensures tight control with auditability and rollback capability.
Comparisons
Method | Pros | Cons |
udev rules | Granular device control | Requires device IDs, complex |
Group Policy (on Windows) | Native enforcement | Not applicable to Linux |
Shell Script (This) | Fast, scriptable, integrates well | Requires kernel module support |
SELinux/AppArmor | Very secure | Complex to configure properly |
Compared to alternatives, this shell script offers a balanced mix of simplicity, portability, and system-wide enforcement without needing to handle device IDs or third-party software.
FAQs
Q1: What happens if my system doesn’t use initramfs?
The script silently skips initramfs updates. However, changes may not apply until the next reboot.
Q2: Can this script be deployed through NinjaOne?
Yes. It’s fully compatible with NinjaOne’s Linux scripting automation, including support for passing parameters like action=Disable and reboot=true.
Q3: What if a user manually loads the module after disabling?
The install /bin/true directive prevents even manual module loading unless explicitly removed.
Q4: Is this reversible?
Absolutely. Running the script with -Enable undoes all configuration and restores USB functionality.
Implications
Using this script enhances endpoint security and enforces policy compliance across Linux machines. It mitigates risks from:
- Insider threats transferring sensitive data
- Malware infection from rogue USBs
- Bypass of DLP systems via removable drives
For regulated industries like finance, healthcare, or government, this script offers an effective compliance control.
Recommendations
- Test before mass deployment—especially on systems with custom kernel modules.
- Automate rollback procedures—store a backup of modified .conf files.
- Integrate with RMM alerts—track systems where USB storage is re-enabled.
- Schedule reboots carefully to avoid disrupting users.
Final Thoughts
Whether you’re looking to disable USB storage devices on Linux with shell scripting, enable USB storage devices on Linux with shell scripting, or configure USB storage access policies on Linux, this script offers a reliable and maintainable approach. Through NinjaOne’s scripting and automation framework, MSPs and IT professionals can operationalize USB governance at scale—enforcing security policies while maintaining administrative control.
For managing Linux endpoints efficiently and securely, NinjaOne’s centralized scripting, automation, and reporting tools complement this script’s power, helping teams scale enforcement without increasing workload.