{"id":353782,"date":"2024-09-04T13:23:54","date_gmt":"2024-09-04T13:23:54","guid":{"rendered":"https:\/\/www.ninjaone.com\/script-hub\/listar-extensiones-del-navegador-2\/"},"modified":"2024-10-13T19:07:03","modified_gmt":"2024-10-13T19:07:03","slug":"listar-extensiones-del-navegador-2","status":"publish","type":"script_hub","link":"https:\/\/www.ninjaone.com\/es\/script-hub\/listar-extensiones-del-navegador-2\/","title":{"rendered":"Gu\u00eda completa para listar las extensiones del navegador en macOS"},"content":{"rendered":"<p>Las extensiones del navegador son potentes herramientas que mejoran la funcionalidad de los navegadores web, pero tambi\u00e9n pueden plantear riesgos de seguridad si no se gestionan adecuadamente. Para los profesionales de TI y los <a href=\"https:\/\/www.ninjaone.com\/es\/que-es-un-msp\" target=\"_blank\" rel=\"noopener\">proveedores de servicios gestionados (MSP)<\/a> responsables de mantener un entorno inform\u00e1tico seguro y eficiente, es crucial disponer de un m\u00e9todo para inventariar las extensiones del navegador en varios navegadores de <a href=\"https:\/\/www.ninjaone.com\/es\/supervision-gestion-de-endpoints\/mac-management\" target=\"_blank\" rel=\"noopener\">sistemas macOS<\/a>.<\/p>\n<p>Este post profundiza en <strong>un completo script que enumera todas las extensiones del navegador<\/strong> instaladas en Safari, Chrome, Firefox y Edge para macOS. Comprender y gestionar estas extensiones puede reforzar significativamente la seguridad de una organizaci\u00f3n.<\/p>\n<h2>Contexto<\/h2>\n<p>En el panorama inform\u00e1tico moderno, garantizar que todo el software, incluidas las extensiones del navegador, est\u00e9 actualizado y sea seguro es una tarea fundamental. Las extensiones pueden aportar grandes beneficios, pero tambi\u00e9n presentan vulnerabilidades potenciales que <a href=\"https:\/\/www.ninjaone.com\/it-hub\/endpoint-security\/what-is-a-threat-actor\/\" target=\"_blank\" rel=\"noopener\">los actores maliciosos<\/a> pueden explotar.<\/p>\n<p>Este script est\u00e1 dise\u00f1ado para ayudar a los profesionales de TI a recopilar informaci\u00f3n de forma r\u00e1pida y eficaz sobre las extensiones de navegador instaladas en varios navegadores de sistemas macOS. Esta capacidad es esencial para mantener el cumplimiento de las normas de seguridad y garantizar que s\u00f3lo se utilizan las extensiones autorizadas.<\/p>\n<h2>El script para listar todas las extensiones del navegador<\/h2>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">#!\/usr\/bin\/env bash\r\n\r\n#\r\n# Description: Get the browser extensions for Safari, Chrome, Firefox, and Edge that are installed on a macOS system.\r\n#\r\n# Usage: [multilineCustomFieldName] [wysiwygCustomFieldName]\r\n#\r\n# Release Notes: Fixed 10% width bug.\r\n# 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.\r\n# 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. \r\n# 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. \r\n# 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. \r\n# Warranty Disclaimer: The script is provided \u201cas is\u201d and \u201cas available\u201d, 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. \r\n# 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. \r\n# 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. \r\n# EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).\r\n#\r\n# Example Output:\r\n#\r\n# Safari Extensions:\r\n# User: john, Name: com.betafish.adblock-mac.SafariMenu, Id: 3KKZV48AQD\r\n# User: ken, Name: com.rockysandstudio.MKPlayer.MKPlayer-Extension, Id: 2N35YUC83U\r\n#\r\n# Chrome Extensions:\r\n# User: john, Name: Chrome Web Store Payments, Id: nmmhkkegccagdldgiimedpiccmgmieda, Version: 1.0.0.6, Profile Name: test1\r\n# User: john, Name: Turn Off the Lights, Id: bfbmjmiodbnnpllbbbfblcplfjjepjdn, Version: 4.2.6.0, Profile Name: test2\r\n# User: ken, Name: Google Docs Offline, Id: ghbmnnjooekpmoecnnnilnnbdlolhkhi, Version: 1.76.1, Profile Name: Person 1\r\n#\r\n# Firefox Addons:\r\n# User: john, Name: Return YouTube Dislike, Id: {762f9885-5a13-4abd-9c77-433dcd38b8fd}, Description: Returns ability to see dislike statistics on youtube, Profile Name: default-release\r\n# User: john, Name: Stylebot, Id: {52bda3fd-dc48-4b3d-a7b9-58af57879f1e}, Description: Change the appearance of the web instantly, Profile Name: default-release\r\n# User: ken, Name: Search by Image, Id: {2e5ff8c8-32fe-46d0-9fc8-6b8986621f3c}, Description: A powerful reverse image search tool, with support for various search engines, such as Google, Bing, Yandex, Baidu and TinEye., Profile Name: default-release\r\n#\r\n# Edge Extensions:\r\n# User: john, Name: Google Docs Offline, Id: ghbmnnjooekpmoecnnnilnnbdlolhkhi, Version: 1.76.2, Profile Name: test 3\r\n# User: john, Name: Edge relevant text changes, Id: jmjflgjpcpepeafmmgdpfkogkghcpiha, Version: 1.2.1, Profile Name: test 3\r\n# User: ken, Name: Google Docs Offline, Id: ghbmnnjooekpmoecnnnilnnbdlolhkhi, Version: 1.76.2, Profile Name: Profile 1\r\n\r\n_arg_multilineField=$1\r\n_arg_wysiwygField=$2\r\n\r\n# Determines whether or not help text is necessary and routes the output to stderr\r\ndie() {\r\n    local _ret=\"${2:-1}\"\r\n    echo \"$1\" &gt;&amp;2\r\n    test \"${_PRINT_HELP:-no}\" = yes &amp;&amp; print_help &gt;&amp;2\r\n    exit \"${_ret}\"\r\n}\r\n\r\n# Prints the help text\r\nprint_help() {\r\n    echo \"Get the browser extensions for Safari, Chrome, Firefox, and Edge that are installed on a macOS system.\"\r\n    echo \"Usage: [multilineCustomFieldName] [wysiwygCustomFieldName]\"\r\n}\r\n\r\n# Check if --help or -h is passed as an argument\r\nfor _arg in \"$@\"; do\r\n    case \"$_arg\" in\r\n    --help | -h)\r\n        print_help\r\n        exit 0\r\n        ;;\r\n    esac\r\ndone\r\n\r\n# Set the custom field value using ninjarmm-cli\r\nGetCustomField() {\r\n    customfieldName=$1\r\n    dataPath=$(printenv | grep -i NINJA_DATA_PATH | awk -F = '{print $2}')\r\n    value=\"\"\r\n    if [ -e \"${dataPath}\/ninjarmm-cli\" ]; then\r\n        value=$(\"${dataPath}\"\/ninjarmm-cli get \"$customfieldName\")\r\n    else\r\n        value=$(\/Applications\/NinjaRMMAgent\/programdata\/ninjarmm-cli get \"$customfieldName\")\r\n    fi\r\n    if [[ \"${value}\" == *\"Unable to find the specified field\"* ]]; then\r\n        echo \"\"\r\n        return 1\r\n    else\r\n        echo \"$value\"\r\n    fi\r\n}\r\n\r\n# Check if the multilineCustomFieldName is set as environment variables\r\nmultiline=$(printenv | grep -i multilineCustomFieldName | awk -F = '{print $2}')\r\nif [[ -n \"$multiline\" ]] &amp;&amp; [[ \"${multiline}\" != \"null\" ]]; then\r\n    _arg_multilineField=$(printenv | grep -i multilineCustomFieldName | awk -F = '{print $2}')\r\nfi\r\n\r\n# Check if the wysiwygCustomFieldName is set as environment variables\r\nwysiwygField=$(printenv | grep -i wysiwygCustomFieldName | awk -F = '{print $2}')\r\nif [[ -n \"$wysiwygField\" ]] &amp;&amp; [[ \"${wysiwygField}\" != \"null\" ]]; then\r\n    _arg_wysiwygField=$(printenv | grep -i wysiwygCustomFieldName | awk -F = '{print $2}')\r\nfi\r\n\r\n# Check if both _arg_multilineField and _arg_wysiwygField are set and not empty\r\nif [[ -n \"$_arg_multilineField\" &amp;&amp; -n \"$_arg_wysiwygField\" ]]; then\r\n    # Convert both field names to uppercase to check for equality\r\n    multiline=$(echo \"$_arg_multilineField\" | tr '[:lower:]' '[:upper:]')\r\n    wysiwyg=$(echo \"$_arg_wysiwygField\" | tr '[:lower:]' '[:upper:]')\r\n\r\n    # If the converted names are the same, it means both fields cannot be identical\r\n    # If they are, terminate the script with an error\r\n    if [[ \"$multiline\" == \"$wysiwyg\" ]]; then\r\n        _PRINT_HELP=yes die '[Error] Multline Field and WYSIWYG Field cannot be the same name. https:\/\/ninjarmm.zendesk.com\/hc\/en-us\/articles\/360060920631-Custom-Fields-Configuration-Device-Role-Fields'\r\n    fi\r\nfi\r\n\r\n# Warn that if not running as root, the script may not be able to access all user directories\r\nif [[ $EUID -ne 0 ]]; then\r\n    echo \"[Warn] This script may not be able to access all user directories unless run as root.\"\r\nfi\r\n\r\n# Converts a string input into an HTML table format\r\nconvertToHTMLTable() {\r\n    local _arg_delimiter=\" \"\r\n    local _arg_inputObject\r\n\r\n    # Process command-line arguments for the function\r\n    while test $# -gt 0; do\r\n        _key=\"$1\"\r\n        case \"$_key\" in\r\n        --delimiter | -d)\r\n            test $# -lt 2 &amp;&amp; echo \"[Error] Missing value for the optional argument\" &gt;&amp;2 &amp;&amp; return 1\r\n            _arg_delimiter=$2\r\n            shift\r\n            ;;\r\n        --*)\r\n            echo \"[Error] Got an unexpected argument\" &gt;&amp;2\r\n            return 1\r\n            ;;\r\n        *)\r\n            _arg_inputObject=$1\r\n            ;;\r\n        esac\r\n        shift\r\n    done\r\n\r\n    # Handles missing input by checking stdin or returning an error\r\n    if [[ -z $_arg_inputObject ]]; then\r\n        if [ -p \/dev\/stdin ]; then\r\n            _arg_inputObject=$(cat)\r\n        else\r\n            echo \"[Error] Missing input object to convert to table\" &gt;&amp;2\r\n            return 1\r\n        fi\r\n    fi\r\n\r\n    local htmlTable=\"&lt;table&gt;\\n\"\r\n    htmlTable+=$(printf '%b' \"$_arg_inputObject\" | head -n1 | awk -F \"$_arg_delimiter\" '{\r\n    printf \"&lt;tr&gt;\"\r\n    for (i=1; i&lt;=NF; i+=1)\r\n      { printf \"&lt;th&gt;\"$i\"&lt;\/th&gt;\" }\r\n    printf \"&lt;\/tr&gt;\"\r\n    }')\r\n    htmlTable+=\"\\n\"\r\n    htmlTable+=$(printf '%b' \"$_arg_inputObject\" | tail -n +2 | awk -F \"$_arg_delimiter\" '{\r\n    printf \"&lt;tr&gt;\"\r\n    for (i=1; i&lt;=NF; i+=1)\r\n      { printf \"&lt;td&gt;\"$i\"&lt;\/td&gt;\" }\r\n    print \"&lt;\/tr&gt;\"\r\n    }')\r\n    htmlTable+=\"\\n&lt;\/table&gt;\"\r\n\r\n    printf '%b' \"$htmlTable\" '\\n'\r\n}\r\n\r\ncreateExtList() {\r\n    userHome=$1\r\n    browser=$2 # chrome or edge\r\n    user_name=$(echo \"$userHome\" | cut -d \"\/\" -f 3)\r\n    if [[ \"${browser}\" == \"chrome\" ]]; then\r\n        manifests=$(find \"${userHome}\/Library\/Application Support\/Google\/Chrome\" -type f -name 'manifest.json' 2&gt;\/dev\/null | grep \"Extensions\")\r\n        profileLocalState=\"${userHome}\/Library\/Application Support\/Google\/Chrome\/Local State\"\r\n    elif [[ \"${browser}\" == \"edge\" ]]; then\r\n        manifests=$(find \"${userHome}\/Library\/Application Support\/Microsoft Edge\" -type f -name 'manifest.json' 2&gt;\/dev\/null | grep \"Extensions\")\r\n        profileLocalState=\"${userHome}\/Library\/Application Support\/Microsoft Edge\/Local State\"\r\n    fi\r\n\r\n    en_messages=\"_locales\/en\/messages.json\"\r\n    enUS_messages=\"_locales\/en_US\/messages.json\"\r\n\r\n    while IFS= read -r manifest; do\r\n        # Check if we can read the manifest file\r\n        if [ ! -f \"$manifest\" ]; then\r\n            continue\r\n        fi\r\n\r\n        profileName=$(\r\n            # Get profile name from profileLocalState that contains json data\r\n            # \"profile.info_cache.Default\" is the default profile\r\n            osascript -l JavaScript -e \"\r\n                    var profileLocalState = JSON.parse(ObjC.unwrap($.NSString.alloc.initWithDataEncoding($.NSData.dataWithContentsOfFile('$profileLocalState'), $.NSUTF8StringEncoding)));\r\n                    \/\/ Get each profile name based on the profile path\r\n                    if ('$browser' === 'chrome') {\r\n                        var profilePathName = '$manifest'.split('\/')[7];\r\n                    } else if ('$browser' === 'edge') {\r\n                        var profilePathName = '$manifest'.split('\/')[6];\r\n                    }\r\n                    for (var key in profileLocalState.profile.info_cache) {\r\n                        if (key.toLowerCase() === profilePathName.toLowerCase()) {\r\n                            var profileName = profileLocalState.profile.info_cache[key].name;\r\n                            break;\r\n                        }\r\n                    }\r\n                    profileName;\r\n                \"\r\n        )\r\n\r\n        # Get the id of the extension from the manifest path by splitting the path on '\/' and getting the 9th element\r\n        if [[ \"${browser}\" == \"chrome\" ]]; then\r\n            extID=$(awk -F '\/' '{print $10}' &lt;&lt;&lt;\"$manifest\")\r\n        elif [[ \"${browser}\" == \"edge\" ]]; then\r\n            extID=$(awk -F '\/' '{print $9}' &lt;&lt;&lt;\"$manifest\")\r\n        fi\r\n        # Get name from manifest\r\n        name=$(\r\n            osascript -l JavaScript -e \"\r\n                var data = JSON.parse(ObjC.unwrap($.NSString.alloc.initWithDataEncoding($.NSData.dataWithContentsOfFile('$manifest'), $.NSUTF8StringEncoding)));\r\n                var name = data.name;\r\n                name;\r\n            \"\r\n        )\r\n        # Get version from manifest\r\n        version=$(\r\n            osascript -l JavaScript -e \"\r\n                var data = JSON.parse(ObjC.unwrap($.NSString.alloc.initWithDataEncoding($.NSData.dataWithContentsOfFile('$manifest'), $.NSUTF8StringEncoding)));\r\n                var version = data.version;\r\n                version;\r\n            \"\r\n        )\r\n\r\n        # Get the name of the extension from the messages.json file if the name contains \"__MSG_\"\r\n        if [[ \"${name}\" =~ \"__MSG_\" ]]; then\r\n            name=$(echo \"$name\" | sed 's\/__MSG_\/\/g' | sed 's\/__$\/\/g')\r\n            if [ -f \"$(dirname \"$manifest\")\/$en_messages\" ]; then\r\n                # Check if message.json exists in en folder\r\n                name=$(\r\n                    osascript -l JavaScript -e \"\r\n                        var data = JSON.parse(ObjC.unwrap($.NSString.alloc.initWithDataEncoding($.NSData.dataWithContentsOfFile('$(dirname \"$manifest\")\/$en_messages'), $.NSUTF8StringEncoding)));\r\n                        var searchKey = '$name';\r\n                        var asLowercase = searchKey.toLowerCase();\r\n                        var name = data[Object.keys(data).find(key =&gt; key.toLowerCase() === asLowercase)].message;\r\n                        name;\r\n                    \" 2&gt;\/dev\/null\r\n                )\r\n            elif [ -f \"$(dirname \"$manifest\")\/$enUS_messages\" ]; then\r\n                # Check if message.json exists in enUS folder\r\n                name=$(\r\n                    osascript -l JavaScript -e \"\r\n                        var data = JSON.parse(ObjC.unwrap($.NSString.alloc.initWithDataEncoding($.NSData.dataWithContentsOfFile('$(dirname \"$manifest\")\/$enUS_messages'), $.NSUTF8StringEncoding)));\r\n                        var searchKey = '$name';\r\n                        var asLowercase = searchKey.toLowerCase();\r\n                        var name = data[Object.keys(data).find(key =&gt; key.toLowerCase() === asLowercase)].message;\r\n                        name;\r\n                    \" 2&gt;\/dev\/null\r\n                )\r\n            fi\r\n        fi\r\n        if [[ -n \"$name\" ]]; then\r\n            printf \"%s|%s|%s|%s|%s\\n\" \"$user_name\" \"$profileName\" \"$name\" \"$extID\" \"$version\"\r\n        else\r\n            printf \"%s|%s|%s|%s|%s\\n\" \"$user_name\" \"$profileName\" \"Name Not Found\" \"$extID\" \"$version\"\r\n        fi\r\n    done &lt;&lt;&lt;\"$manifests\"\r\n}\r\n\r\n# Get a list of all users in the \/Users directory except Shared\r\nusers=()\r\nfor user in \/Users\/*; do\r\n    if [[ -d \"$user\" &amp;&amp; ! \"$user\" =~ \/Users\/Shared ]]; then\r\n        users+=(\"${user##*\/}\")\r\n    fi\r\ndone\r\n\r\n# Error when no users are found\r\nif [[ ${#users[@]} -eq 0 ]]; then\r\n    _PRINT_HELP=no die \"[Error] No user directories found in \/Users\"\r\nfi\r\n\r\nsafari_title=\"Safari Extensions\"\r\nsafari_extensions=\"\"\r\nchrome_title=\"Chrome Extensions\"\r\nchrome_extensions=\"\"\r\nfirefox_title=\"Firefox Addons\"\r\nfirefox_addons=\"\"\r\nedge_title=\"Edge Extensions\"\r\nedge_extensions=\"\"\r\n\r\n# Safari\r\nfor user in \"${users[@]}\"; do\r\n    ext_plist=\"\/Users\/$user\/Library\/Containers\/com.apple.Safari\/Data\/Library\/Safari\/AppExtensions\/Extensions.plist\"\r\n    pattern='(com\\..*)\\s\\((.*)\\)'\r\n    if [[ -f \"$ext_plist\" ]]; then\r\n        safari_extensions+=$'\\n'\"$(\r\n            grep -Eo \"$pattern\" \"$ext_plist\" | while read -r line; do\r\n                ext_name=$(echo \"$line\" | awk -F ' ' '{print $1}')\r\n                ext_id=$(echo \"$line\" | awk -F ' ' '{print $2}' | tr -d '()')\r\n                printf \"%s|%s|%s\\n\" \"$user\" \"$ext_name\" \"$ext_id\"\r\n            done\r\n        )\"\r\n    fi\r\ndone\r\n\r\n# Chrome\r\nfor user in \"${users[@]}\"; do\r\n    # Add a newline to the beginning of the string to separate the results from the previous user\r\n    chrome_extensions+=$'\\n'\"$(createExtList \"\/Users\/$user\" \"chrome\")\"\r\ndone\r\n\r\n# Firefox Get installed Addons (not extensions)\r\nfirefox_addons=$(\r\n    # Loop through each user profile\r\n    for user in \"${users[@]}\"; do\r\n        firefox_path=\"\/Users\/$user\/Library\/Application Support\/Firefox\"\r\n        profile_dir=\"$firefox_path\/Profiles\"\r\n        # Check if Profiles directory exists\r\n        if [[ -d \"$profile_dir\" ]]; then\r\n            profiles_ini_path=\"$firefox_path\/profiles.ini\"\r\n            # Check if profiles.ini file exists\r\n            if [[ -f \"$profiles_ini_path\" ]]; then\r\n                profiles_ini=$(cat \"$profiles_ini_path\")\r\n                # Parse the profiles.ini file and get the profile names and paths\r\n                # Get each section\r\n                awk -F '=' '\/\\[\/{print $1}' &lt;&lt;&lt;\"$profiles_ini\" | while read -r section; do\r\n                    # Get the profile name\r\n                    profile_name=$(\r\n                        awk -F'=' -v section=\"$section\" -v k=\"Name\" '\r\n                        $0==section{ f=1; next }\r\n                        \/\\[\/{ f=0; next }\r\n                        f &amp;&amp; $1==k{ print $0 }\r\n                        ' &lt;&lt;&lt;\"$profiles_ini\" | sed 's\/^Name=\/\/'\r\n                    )\r\n                    # Get the profile path\r\n                    profile_path=$(\r\n                        awk -F'=' -v section=\"$section\" -v k=\"Path\" '\r\n                        $0==section{ f=1; next }\r\n                        \/\\[\/{ f=0; next }\r\n                        f &amp;&amp; $1==k{ print $0 }\r\n                        ' &lt;&lt;&lt;\"$profiles_ini\" | sed 's\/^Path=\/\/'\r\n                    )\r\n                    # Get the addons json file path\r\n                    ext_dir=\"$firefox_path\/$profile_path\/addons.json\"\r\n                    if [[ -f \"$ext_dir\" ]]; then\r\n                        # Get name, id, and description from the addons.json file\r\n                        ff_results=$(\r\n                            osascript -l JavaScript -e \"\r\n                                var data = JSON.parse(ObjC.unwrap($.NSString.alloc.initWithDataEncoding($.NSData.dataWithContentsOfFile('$ext_dir'), $.NSUTF8StringEncoding)));\r\n                                var addons = data.addons;\r\n                                var result = '';\r\n                                for (var i = 0; i &lt; addons.length; i++) {\r\n                                    var addon = addons[i];\r\n                                    result += addon.name + ',' + addon.id + ',' + addon.description + '\\n';\r\n                                }\r\n                                result;\r\n                            \"\r\n                        )\r\n                        Old_IFS=$IFS\r\n                        echo \"$ff_results\" | while IFS=, read -r name id description; do\r\n                            printf \"%s|%s|%s|%s|%s\\n\" \"$user\" \"$profile_name\" \"$name\" \"$id\" \"$description\"\r\n                        done\r\n                        IFS=$Old_IFS\r\n                    fi\r\n                done\r\n            fi\r\n        fi\r\n    done\r\n)\r\n\r\n# Edge\r\nfor user in \"${users[@]}\"; do\r\n    # Add a newline to the beginning of the string to separate the results from the previous user\r\n    edge_extensions+=$'\\n'\"$(createExtList \"\/Users\/$user\" \"edge\")\"\r\ndone\r\n\r\nif [[ -n $_arg_multilineField ]] || [[ -n $_arg_wysiwygField ]]; then\r\n    # Add headers if a custom field is set\r\n    if [[ -n \"${safari_extensions}\" ]]; then\r\n        safari_extensions=$(echo -e \"User|Name|Id\\n$safari_extensions\")\r\n    fi\r\n    if [[ -n \"${chrome_extensions}\" ]]; then\r\n        chrome_extensions=$(echo -e \"User|Profile Name|Name|Id|Version\\n$chrome_extensions\")\r\n    fi\r\n    if [[ -n \"${firefox_addons}\" ]]; then\r\n        firefox_addons=$(echo -e \"User|Profile Name|Name|Id|Description\\n$firefox_addons\")\r\n    fi\r\n    if [[ -n \"${edge_extensions}\" ]]; then\r\n        edge_extensions=$(echo -e \"User|Profile Name|Name|Id|Version\\n$edge_extensions\")\r\n    fi\r\nfi\r\n\r\n# Checks if there is a multiline custom field set\r\nif [[ -n $_arg_multilineField ]]; then\r\n    echo \"\"\r\n    echo \"Attempting to set Custom Field '$_arg_multilineField'...\"\r\n\r\n    # Formats the extension data for the multiline custom field\r\n    multilineValue=\"\"\r\n    # Check if any browser extensions were found\r\n    if [[ -n \"$safari_title\" ]] &amp;&amp; [[ -n \"${safari_extensions}\" ]]; then\r\n        multilineValue+=$'\\n'\r\n        multilineValue+=\"$safari_title:\"\r\n        multilineValue+=$'\\n'\r\n        multilineValue+=$(\r\n            # Convert the safari_extensions string to a table format. Skip the first line as it is the header\r\n            echo \"$safari_extensions\" | tail -n +2 | while IFS='|' read -r user name id; do\r\n                printf \"User: %s, Name: %s, Id: %s\\n\" \"$user\" \"$name\" \"$id\"\r\n            done\r\n        )\r\n    fi\r\n    if [[ -n \"$chrome_title\" ]] &amp;&amp; [[ -n \"${chrome_extensions}\" ]]; then\r\n        multilineValue+=$'\\n'\r\n        multilineValue+=\"$chrome_title:\"\r\n        multilineValue+=$'\\n'\r\n        multilineValue+=$(\r\n            # Convert the chrome_extensions string to a table format. Skip the first line as it is the header\r\n            echo \"$chrome_extensions\" | tail -n +2 | while IFS='|' read -r user_name profileName name id version; do\r\n                if [[ -n \"$name\" ]]; then\r\n                    printf \"User: %s, Profile Name: %s, Name: %s, Id: %s, Version: %s\\n\" \"$user_name\" \"$profileName\" \"$name\" \"$id\" \"$version\"\r\n                fi\r\n            done\r\n        )\r\n    fi\r\n    if [[ -n \"$firefox_title\" ]] &amp;&amp; [[ -n \"${firefox_addons}\" ]]; then\r\n        multilineValue+=$'\\n'\r\n        multilineValue+=\"$firefox_title:\"\r\n        multilineValue+=$'\\n'\r\n        multilineValue+=$(\r\n            # Convert the firefox_addons string to a table format. Skip the first line as it is the header\r\n            echo \"$firefox_addons\" | tail -n +2 | while IFS='|' read -r user profileName name id description; do\r\n                if [[ -n \"$name\" ]]; then\r\n                    printf \"User: %s, Profile Name: %s, Name: %s, Id: %s, Description: %s\\n\" \"$user\" \"$profileName\" \"$name\" \"$id\" \"$description\"\r\n                fi\r\n            done\r\n        )\r\n    fi\r\n    if [[ -n \"$edge_title\" ]] &amp;&amp; [[ -n \"${edge_extensions}\" ]]; then\r\n        multilineValue+=$'\\n'\r\n        multilineValue+=\"$edge_title:\"\r\n        multilineValue+=$'\\n'\r\n        multilineValue+=$(\r\n            # Convert the edge_extensions string to a table format. Skip the first line as it is the header\r\n            echo \"$edge_extensions\" | tail -n +2 | while IFS='|' read -r user_name profileName name id version; do\r\n                if [[ -n \"$name\" ]]; then\r\n                    printf \"User: %s, Profile Name: %s, Name: %s, Id: %s, Version: %s\\n\" \"$user_name\" \"$profileName\" \"$name\" \"$id\" \"$version\"\r\n                fi\r\n            done\r\n        )\r\n    fi\r\n    # if all multilineValue is empty, set it to \"No browser extensions found\"\r\n    if [[ -z \"$multilineValue\" ]]; then\r\n        multilineValue=\"No browser extensions found\"\r\n    fi\r\n\r\n    # Tries to set the multiline custom field using ninjarmm-cli and captures the output\r\n    if ! output=$(printf '%b' \"$multilineValue\" | \/Applications\/NinjaRMMAgent\/programdata\/ninjarmm-cli set --stdin \"$_arg_multilineField\" 2&gt;&amp;1); then\r\n        echo \"[Error] $output\" &gt;&amp;2\r\n        EXITCODE=1\r\n    else\r\n        echo \"[Info] Successfully set Custom Field '$_arg_multilineField'!\"\r\n    fi\r\nfi\r\n\r\n# Checks if there is a WYSIWYG custom field set\r\nif [[ -n $_arg_wysiwygField ]]; then\r\n    echo \"\"\r\n    echo \"Attempting to set Custom Field '$_arg_wysiwygField'...\"\r\n\r\n    # Initializes an HTML formatted string with headers and extension details\r\n    # Check if any browser extensions were found\r\n    if [[ -n \"$safari_title\" ]] &amp;&amp; [[ -n \"${safari_extensions}\" ]]; then\r\n        htmlObject+=\"&lt;h2&gt;$safari_title&lt;\/h2&gt;\"\r\n        htmlObject+=$(echo \"$safari_extensions\" | convertToHTMLTable --delimiter '|')\r\n    fi\r\n    if [[ -n \"$chrome_title\" ]] &amp;&amp; [[ -n \"${chrome_extensions}\" ]]; then\r\n        htmlObject+=\"&lt;h2&gt;$chrome_title&lt;\/h2&gt;\"\r\n        htmlObject+=$(echo \"$chrome_extensions\" | convertToHTMLTable --delimiter '|')\r\n    fi\r\n    if [[ -n \"$firefox_title\" ]] &amp;&amp; [[ -n \"${firefox_addons}\" ]]; then\r\n        htmlObject+=\"&lt;h2&gt;$firefox_title&lt;\/h2&gt;\"\r\n        htmlObject+=$(echo \"$firefox_addons\" | convertToHTMLTable --delimiter '|')\r\n    fi\r\n    if [[ -n \"$edge_title\" ]] &amp;&amp; [[ -n \"${edge_extensions}\" ]]; then\r\n        htmlObject+=\"&lt;h2&gt;$edge_title&lt;\/h2&gt;\"\r\n        htmlObject+=$(echo \"$edge_extensions\" | convertToHTMLTable --delimiter '|')\r\n    fi\r\n    # if all htmlObject is empty, set it to \"No browser extensions found\"\r\n    if [[ -z \"$htmlObject\" ]]; then\r\n        htmlObject=\"&lt;p&gt;No browser extensions found&lt;\/p&gt;\"\r\n    fi\r\n    # Replace &lt;table&gt; with &lt;table style='white-space:nowrap;'&gt;\r\n    htmlObject=${htmlObject\/\/&lt;table&gt;\/&lt;table style=\\'white-space:nowrap;\\'&gt;}\r\n    # Tries to set the WYSIWYG custom field using ninjarmm-cli and captures the output\r\n    if ! output=$(printf '%b' \"$htmlObject\" | \/Applications\/NinjaRMMAgent\/programdata\/ninjarmm-cli set --stdin \"$_arg_wysiwygField\" 2&gt;&amp;1); then\r\n        echo \"[Error] $output\" &gt;&amp;2\r\n        EXITCODE=1\r\n    else\r\n        echo \"[Info] Successfully set Custom Field '$_arg_wysiwygField'!\"\r\n    fi\r\nfi\r\n\r\n# If both _arg_multilineField and _arg_wysiwygField are not set, or if there is an error saving to the custom fields, print the results\r\nif [[ -z $_arg_multilineField &amp;&amp; -z $_arg_wysiwygField ]] || [[ $EXITCODE -ne 0 ]]; then\r\n    echo \"\"\r\n    echo \"$safari_title:\"\r\n    echo \"$safari_extensions\" | while IFS='|' read -r user name id; do\r\n        if [[ -n \"$name\" ]]; then\r\n            printf \"User: %s, Name: %s, Id: %s\\n\" \"$user\" \"$name\" \"$id\"\r\n        fi\r\n    done\r\n    echo \"\"\r\n    echo \"$chrome_title:\"\r\n    echo \"$chrome_extensions\" | while IFS='|' read -r user profileName name id version; do\r\n        if [[ -n \"$name\" ]]; then\r\n            printf \"User: %s, Profile Name: %s, Name: %s, Id: %s, Version: %s\\n\" \"$user\" \"$profileName\" \"$name\" \"$id\" \"$version\"\r\n        fi\r\n    done\r\n    echo \"\"\r\n    echo \"$firefox_title:\"\r\n    echo \"$firefox_addons\" | while IFS='|' read -r user profileName name id description; do\r\n        if [[ -n \"$name\" ]]; then\r\n            printf \"User: %s, Profile Name: %s, Name: %s, Id: %s, Description: %s\\n\" \"$user\" \"$profileName\" \"$name\" \"$id\" \"$description\"\r\n        fi\r\n    done\r\n    echo \"\"\r\n    echo \"$edge_title:\"\r\n    echo \"$edge_extensions\" | while IFS='|' read -r user profileName name id version; do\r\n        if [[ -n \"$name\" ]]; then\r\n            printf \"User: %s, Profile Name: %s, Name: %s, Id: %s, Version: %s\\n\" \"$user\" \"$profileName\" \"$name\" \"$id\" \"$version\"\r\n        fi\r\n    done\r\n    # If no extensions are found, print a message\r\n    if [[ -z \"$safari_extensions\" ]] &amp;&amp; [[ -z \"$chrome_extensions\" ]] &amp;&amp; [[ -z \"$firefox_addons\" ]] &amp;&amp; [[ -z \"$edge_extensions\" ]]; then\r\n        echo \"[Info] No Browser Extensions Found\"\r\n    fi\r\nfi\r\n\r\n# Checks if an error code is set and exits the script with that code\r\nif [[ -n $EXITCODE ]]; then\r\n    echo \"[Error] Failed to save browser extensions to custom field '$_arg_multilineField' or '$_arg_wysiwygField'.\"\r\n    exit \"$EXITCODE\"\r\nfi<\/pre>\n<p>&nbsp;<\/p>\n\n<div class=\"blog-cta-new blog-cta-style-1\"><div class=\"cta-left\"><h2><\/h2><p><\/p><\/div><div class=\"cta-right\"><a class=\"button\" href=\"\"><\/a><\/div><\/div>\n<h2>An\u00e1lisis detallado<\/h2>\n<p>El script para listar todas las extensiones del navegador comienza definiendo su prop\u00f3sito y uso, proporcionando una descripci\u00f3n clara y un ejemplo de salida. A continuaci\u00f3n, comprueba los argumentos de ayuda y establece los valores de los campos personalizados utilizando el ninjarmm-cli, una herramienta para la gesti\u00f3n de campos personalizados en NinjaOne RMM.<\/p>\n<h3>1. Inicializaci\u00f3n y gesti\u00f3n de argumentos<\/h3>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:1440,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"1\" data-aria-level=\"2\">El script para listar todas las extensiones del navegador se inicializa comprobando si se proporcionan argumentos de ayuda (&#8211;help o -h). Si es as\u00ed, imprime las instrucciones de uso y sale.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:1440,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"2\" data-aria-level=\"2\">Define una funci\u00f3n GetCustomField para recuperar valores de campos personalizados utilizando ninjarmm-cli.<\/li>\n<\/ul>\n<h3>2. Comprobaci\u00f3n de variables de entorno<\/h3>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:1440,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"3\" data-aria-level=\"2\">El script comprueba si multilineCustomFieldName y wysiwygCustomFieldName est\u00e1n establecidos como variables de entorno, actualizando los argumentos del script en consecuencia.<\/li>\n<\/ul>\n<h3>3. Identificaci\u00f3n del directorio de usuarios<\/h3>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:1440,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"4\" data-aria-level=\"2\">Identifica los directorios de usuario en \/Usuarios, excluyendo el directorio Compartido, y re\u00fane todas las cuentas de usuario del sistema.<\/li>\n<\/ul>\n<h3>4. Extensiones de Safari<\/h3>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:1440,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"5\" data-aria-level=\"2\">Para cada usuario, el script para listar todas las extensiones del navegador busca los archivos plist de extensiones de Safari y extrae los detalles de las extensiones mediante expresiones regulares.<\/li>\n<\/ul>\n<h3>5. Extensiones para Chrome y Edge<\/h3>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:1440,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"6\" data-aria-level=\"2\">El script emplea una funci\u00f3n createExtList para encontrar y listar extensiones de Chrome y Edge. Analiza los archivos manifest.json de los directorios de extensiones del navegador y extrae los nombres, ID y versiones de las extensiones.<\/li>\n<\/ul>\n<h3>6. Complementos de Firefox<\/h3>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:1440,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"7\" data-aria-level=\"2\">En el caso de Firefox, el script analiza los archivos profiles.ini y addons.json para obtener una lista de los complementos instalados, incluidos nombres, ID y descripciones.<\/li>\n<\/ul>\n<h3>7. Configuraci\u00f3n y salida de campos personalizados<\/h3>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:1440,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"8\" data-aria-level=\"2\">Si se establecen campos personalizados, el script formatea los datos recopilados en tablas HTML o texto sin formato, y luego intenta establecer estos campos utilizando ninjarmm-cli. Si la configuraci\u00f3n de los campos falla, imprime los datos recogidos en la consola.<\/li>\n<\/ul>\n<p>Este enfoque estructurado garantiza una cobertura completa de los principales navegadores y proporciona un inventario claro y detallado de las extensiones instaladas.<\/p>\n<h2>Posibles casos de uso<\/h2>\n<p>Pensemos en un MSP encargado de garantizar la seguridad de todos los equipos cliente. Con este script, el MSP puede generar r\u00e1pidamente una lista de todas las extensiones de navegador instaladas en los sistemas macOS cliente. Por ejemplo, si se descubre una vulnerabilidad de seguridad en una extensi\u00f3n espec\u00edfica, el MSP puede utilizar el script para identificar qu\u00e9 clientes tienen instalada la extensi\u00f3n y tomar las medidas oportunas para mitigar el riesgo.<\/p>\n<h2>Comparaciones<\/h2>\n<p>Otros m\u00e9todos para listar las extensiones del navegador suelen implicar comprobaciones manuales o el uso de herramientas espec\u00edficas del navegador, lo que puede llevar mucho tiempo y ser propenso a errores. Este script para listar todas las extensiones del navegador proporciona una soluci\u00f3n unificada y automatizada que funciona en varios navegadores, ahorrando tiempo y reduciendo la probabilidad de descuidos. Adem\u00e1s, la integraci\u00f3n con NinjaOne RMM permite centralizar la gesti\u00f3n y los informes, lo que no es posible con m\u00e9todos manuales.<\/p>\n<h2>FAQ<\/h2>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"2\" data-aria-level=\"1\"><strong>\u00bfC\u00f3mo gestiona el script los distintos perfiles de usuario?<\/strong><br \/>\nEl script para listar todas las extensiones del navegador itera sobre cada directorio de usuario en \/Users y procesa cada perfil encontrado dentro de los respectivos directorios del navegador.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"3\" data-aria-level=\"1\"><strong>\u00bfQu\u00e9 ocurre si el script no puede acceder a un directorio de usuario?<\/strong><br \/>\nEl script para listar todas las extensiones del navegador advierte que puede necesitar acceso root para leer todos los directorios de usuario. Ejecutar el script como root garantiza un acceso completo.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"4\" data-aria-level=\"1\"><strong>\u00bfSe puede utilizar el script en sistemas que no sean MacOS?<\/strong><br \/>\nNo, este script est\u00e1 dise\u00f1ado espec\u00edficamente para macOS debido a las rutas y herramientas que utiliza.<\/li>\n<\/ul>\n<h2>Implicaciones<\/h2>\n<p>Los resultados de este script para listar todas las extensiones del navegador proporcionan informaci\u00f3n cr\u00edtica sobre las extensiones instaladas en varios navegadores y ponen de manifiesto <a href=\"https:\/\/www.ninjaone.com\/blog\/defeat-cyber-security-threats\/\" target=\"_blank\" rel=\"noopener\">posibles riesgos para la seguridad<\/a>. Al disponer de un inventario claro, los profesionales de TI pueden garantizar el cumplimiento de las pol\u00edticas de seguridad, detectar ampliaciones no autorizadas y solucionar r\u00e1pidamente cualquier vulnerabilidad.<\/p>\n<h2>Recomendaciones<\/h2>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"5\" data-aria-level=\"1\"><strong>Ejecuta el script como root<\/strong> para garantizar el acceso a todos los directorios de usuario.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"6\" data-aria-level=\"1\"><strong>Revisaregularmente las listas de extensiones<\/strong> para identificar y eliminar cualquier extensi\u00f3n innecesaria o potencialmente da\u00f1ina.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"7\" data-aria-level=\"1\"><strong>Integra el script con una herramienta de supervisi\u00f3n<\/strong> como NinjaOne RMM para una gesti\u00f3n e informes continuos.<\/li>\n<\/ul>\n<h2>Reflexiones finales<\/h2>\n<p>La gesti\u00f3n de las extensiones del navegador es un aspecto crucial para mantener un entorno inform\u00e1tico seguro. Este script para listar todas las extensiones del navegador proporciona una soluci\u00f3n potente y automatizada para los principales navegadores en macOS, lo que lo convierte en una herramienta inestimable para los profesionales de TI y los MSP. Gracias a la integraci\u00f3n con <a href=\"https:\/\/www.ninjaone.com\/es\/\" target=\"_blank\" rel=\"noopener\">NinjaOne<\/a>, puedes mejorar tu capacidad para supervisar y gestionar las extensiones del navegador, garantizando un entorno inform\u00e1tico <a href=\"https:\/\/www.ninjaone.com\/blog\/defeat-cyber-security-threats\/\" target=\"_blank\" rel=\"noopener\">seguro<\/a> y conforme a las normas.<\/p>\n","protected":false},"author":35,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"_relevanssi_hide_post":"","_relevanssi_hide_content":"","_relevanssi_pin_for_all":"","_relevanssi_pin_keywords":"","_relevanssi_unpin_keywords":"","_relevanssi_related_keywords":"","_relevanssi_related_include_ids":"","_relevanssi_related_exclude_ids":"","_relevanssi_related_no_append":"","_relevanssi_related_not_related":"","_relevanssi_related_posts":"","_relevanssi_noindex_reason":"","_lmt_disableupdate":"","_lmt_disable":""},"operating_system":[4210],"use_cases":[4259],"class_list":["post-353782","script_hub","type-script_hub","status-publish","hentry","script_hub_category-macos","use_cases-configuracion-general"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/script_hub\/353782","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/script_hub"}],"about":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/types\/script_hub"}],"author":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/users\/35"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/comments?post=353782"}],"wp:attachment":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/media?parent=353782"}],"wp:term":[{"taxonomy":"script_hub_category","embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/operating_system?post=353782"},{"taxonomy":"use_cases","embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/use_cases?post=353782"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}