Lucene search
+L

ColdFusion Installed on Microsoft Windows (credentialed check)

🗓️ 05 Jul 2011 00:00:00Reported by TenableType 
nessus
 nessus
🔗 www.tenable.com👁 30 Views

ColdFusion Installed on Windows (credentialed check) - Checks for ColdFusion installation on the remote Windows host

Refs
Code
#
# (C) Tenable Network Security, Inc.
#

include("compat.inc");

if (description)
{
  script_id(55514);
  script_version("1.19");
  script_set_attribute(attribute:"plugin_modification_date", value:"2026/06/11");

  script_xref(name:"IAVT", value:"0001-T-0576");

  script_name(english:"ColdFusion Installed on Microsoft Windows (credentialed check)");
  script_summary(english:"Checks to see if ColdFusion is installed");

  script_set_attribute(attribute:"synopsis", value:"A web application platform is installed on the remote Windows host.");
  script_set_attribute(attribute:"description", value:
"Adobe ColdFusion (formerly Macromedia ColdFusion), a rapid application
development platform, is installed on the remote Windows host.");
  script_set_attribute(attribute:"see_also", value:"https://www.adobe.com/products/coldfusion-family.html");
  script_set_attribute(attribute:"solution", value:"n/a");
  script_set_attribute(attribute:"risk_factor", value:"None");

  script_set_attribute(attribute:"plugin_publication_date", value:"2011/07/05");

  script_set_attribute(attribute:"plugin_type", value:"local");
  script_set_attribute(attribute:"cpe", value:"cpe:/a:macromedia:coldfusion");
  script_set_attribute(attribute:"cpe", value:"cpe:/a:adobe:coldfusion");
  script_set_attribute(attribute:"asset_inventory", value:"True");
  script_set_attribute(attribute:"agent", value:"windows");
  script_end_attributes();

  script_category(ACT_GATHER_INFO);
  script_family(english:"Windows");

  script_copyright(english:"This script is Copyright (C) 2011-2026 and is owned by Tenable, Inc. or an Affiliate thereof.");

  script_dependencies("smb_hotfixes.nasl");
  script_require_keys("SMB/Registry/Enumerated");
  script_require_ports(139, 445);

  exit(0);
}

include("smb_hotfixes.inc");
include("smb_func.inc");
include("byte_func.inc");
include("debug.inc");

global_var instances, name, port, domain, files_to_find, login, pass;
instances = make_array();
name   = kb_smb_name();
port   = kb_smb_transport();
login  = kb_smb_login();
pass   = kb_smb_password();
domain = kb_smb_domain();

# files that we're interested in extracting from cfusion.jar,
# which gives us version and build information
files_to_find = make_array(
  'META-INF/MANIFEST.MF', TRUE,
  'coldfusion/Version.class', TRUE
);

##
# attempts to extract all 'files_to_find' from the given jar
#
# for more on the file format refer to http://www.pkware.com/documents/casestudies/APPNOTE.TXT
#
# @anonparam fh file handle of jar to search through
# @return a hash where the key is the filename, and value is the file contents iff all 'files_to_find' were discovered,
#         NULL otherwise
##
function find_files_in_jar()
{
  var fh, jar_len, field, i, magic, version, bitflag, compression, mtime, mdate, crc, compressed_len, uncompressed_len;
  var filename_len, extra_field_len, filename, compressed_data, uncompressed_data, file_data, files, files_found;
  fh = _FCT_ANON_ARGS[0];

  set_byte_order(BYTE_ORDER_LITTLE_ENDIAN);
  jar_len = GetFileSize(handle:fh);
  i = 0;
  files_found = 0;
  files = NULL;  # key = filename, value = data

  while (i < jar_len)
  {
    field = ReadFile(handle:fh, offset:i, length:4); i += 4;
    magic = getdword(blob:field, pos:0);
    if (magic != 0x04034b50)
    {
      dbg::detailed_log(lvl:3, src:FUNCTION_NAME, msg:"Bad magic: " + hexstr(magic));
      return NULL;
    }

    field = ReadFile(handle:fh, offset:i, length:2); i += 2;
    version = getword(blob:field, pos:0);

    field = ReadFile(handle:fh, offset:i, length:2); i += 2;
    bitflag = getword(blob:field, pos:0);

    field = ReadFile(handle:fh, offset:i, length:2); i += 2;
    compression = getword(blob:field, pos:0);

    field = ReadFile(handle:fh, offset:i, length:2); i += 2;
    mtime = getword(blob:field, pos:0);

    field = ReadFile(handle:fh, offset:i, length:2); i += 2;
    mdate = getword(blob:field, pos:0);

    field = ReadFile(handle:fh, offset:i, length:4); i += 4;
    crc = getdword(blob:field, pos:0);

    field = ReadFile(handle:fh, offset:i, length:4); i += 4;
    compressed_len = getdword(blob:field, pos:0);

    field = ReadFile(handle:fh, offset:i, length:4); i += 4;
    uncompressed_len = getdword(blob:field, pos:0);

    field = ReadFile(handle:fh, offset:i, length:2); i += 2;
    filename_len = getword(blob:field, pos:0);

    field = ReadFile(handle:fh, offset:i, length:2); i += 2;
    extra_field_len = getword(blob:field, pos:0);

    filename = ReadFile(handle:fh, offset:i, length:filename_len); i += filename_len;

    i += extra_field_len;

    file_data = ReadFile(handle:fh, offset:i, length:compressed_len); i += compressed_len;

    # the manifest gives us the build number, the class file gives us the version (x,y,z)
    if (files_to_find[filename])
    {
      if (compression == 0)  # no compression
      {
        files[filename] = file_data;
        if (++files_found == 2) break;
      }
      else if (compression == 8)  # deflate
      {
        uncompressed_data = zlib_decompress(data:file_data, length:uncompressed_len);
        files[filename] = uncompressed_data;
        if (++files_found == 2) break;
      }
      else
      {
        # research indicates the files we're interested in are always compressed using deflate
        # for now we'll ignore anything else
        dbg::detailed_log(lvl:3, src:FUNCTION_NAME, msg:"Unknown compression method: " + compression);
        break;
      }
    }

    # skip over the data descriptor block if it's present
    if (bitflag & 0x4)
    {
      field = ReadFile(handle:fh, offset:i, length:12);
      i += 12;
    }
  }

  if (files_found < 2)
  {
    if (files_found == 0)
      dbg::detailed_log(lvl:3, src:FUNCTION_NAME, msg:"The desired files weren't found in the jar file.");
    else
      dbg::detailed_log(lvl:3, src:FUNCTION_NAME, msg:"Only " + join(files, sep:'') + " was found in the jar file.");

    return NULL;
  }

  return files;
}

##
# Checks to see if the given ColdFusion instance is valid by trying to get
# its version number, build number, and any hotfixes it may have.  If this
# information is obtained, it's stored in the global hash 'instances'
#
# @anonparam name instance name to check
##
function check_instance()
{
  var name, cfroot, share, rc, ver;
  name = _FCT_ANON_ARGS[0];
  cfroot = instances[name]['cfroot'];

  share = ereg_replace(pattern:'^([A-Za-z]):.*', replace:'\\1$', string:cfroot);
  rc = NetUseAdd(login:login, password:pass, domain:domain, share:share);
  if (rc != 1)
    dbg::detailed_log(lvl:3, src:FUNCTION_NAME, msg:'get_instances: Can\'t connect to '+share+' share.');
  else
  {
    get_version(name);
    ver = instances[name]['version'];
    if (!isnull(ver)) get_hotfixes(name, ver);
  }
  NetUseDel(close:FALSE);
}

##
# Tries to get the version number (x.y.z) and build number of the given ColdFusion instance.
# if this function succeeds, the information is stored in the 'instances' global variable
#
# This function assumes the plugin has already been connected to the share
# where the instance is located
#
# @anonparam name name of the instance to get the version for
##
function get_version()
{
  var name, path, jar, fh, files, match, build, version, file_data;
  name = _FCT_ANON_ARGS[0];

  if (instances[name]['type'] == 'Server')
    path = instances[name]['cfroot'] + "\lib\cfusion.jar";
  else if (instances[name]['type'] == 'Multiserver')
    path = instances[name]['cfroot'] + "\WEB-INF\cfusion\lib\cfusion.jar";

  jar = ereg_replace(pattern:'^[A-Za-z]:(.*)', replace:'\\1', string:path);

  fh = CreateFile(
    file:jar,
    desired_access:GENERIC_READ,
    file_attributes:FILE_ATTRIBUTE_NORMAL,
    share_mode:FILE_SHARE_READ,
    create_disposition:OPEN_EXISTING
  );

  if (fh)
  {
    # tries to extract the files containing the version & build from the jar
    files = find_files_in_jar(fh);
    CloseFile(handle:fh);

    if (!isnull(files))
    {
      match = pregmatch(string:files['META-INF/MANIFEST.MF'], pattern:'Implementation-Version: ([0-9]+)');
      if (!isnull(match))
      {
        build = match[1];
        instances[name]['build'] = match[1];
      }

      # need to get rid of the nulls in order for the regex function to work
      file_data = str_replace(string:files['coldfusion/Version.class'], find:'\x00', replace:'');
      match = pregmatch(string:file_data, pattern:'([0-9]+,[0-9]+,[0-9]+),');
      if (!isnull(match))
      {
         version = str_replace(string:match[1], find:',', replace:'.');
         instances[name]['version'] = version;
      }
    }
  }
  else dbg::detailed_log(lvl:3, src:FUNCTION_NAME, msg:'Unable to open: ' + path);
}

##
# gets a list of hotfixes for the given instance. if this function succeeds, the results
# are put in the 'instances' global variable
#
# @anonparam name name of the instance to get hotfixes for
# @anonparam ver  version of the 'name' instance
##
function get_hotfixes()
{
  var name, ver, update_path, dir, pattern, fh, match, type, id, basename;
  name = _FCT_ANON_ARGS[0];
  ver = str_replace(string:_FCT_ANON_ARGS[1], find:'.', replace:'');

  if (instances[name]['type'] == 'Server')
    update_path = instances[name]['cfroot'] + "\lib\updates";
  else if (instances[name]['type'] == 'Multiserver')
    update_path = instances[name]['cfroot'] + "\WEB-INF\cfusion\lib\updates";

  dir = ereg_replace(pattern:'^[A-Za-z]:(.*)', replace:'\\1', string:update_path);
  pattern = dir +  "\*hf" +  ver +  "*.jar";

  fh = FindFirstFile(pattern:pattern);
  while (!isnull(fh[1]))
  {
    # Skip directories.
    if (fh[2] & FILE_ATTRIBUTE_DIRECTORY == 0)
    {
      # Hotfix jars are in the format:
      # hfxyz-nnnn.jar  xyz = CF version, nnnn hotfix number
      # e.g.
      # hf800-1875.jar    hf = regular hotfix, 800 = CF 8.0.0, 1875 = seemingly random number
      # hf800-00001.jar   hf = regular hotfix, 800 = CF 8.0.0, 00001 = zero padded numbers can supersede the random number hotfixes
      # chf800-0001.jar   chf = cumulative hotfix, 800 = CF 8.0.0, 00001 = CHF number. these can supersede the previous two types
      #
      # this is all undocumented and, at best, an educated guess
      match = pregmatch(string:fh[1], pattern:"^(c?hf)" + ver + "-?([0-9]+).jar$");
      if (!isnull(match))
      {
        type = match[1];
        id = match[2];
        basename = ereg_replace(pattern:'\\.jar$', replace:'', string:fh[1]);

        if (isnull(instances[name][type]))
          instances[name][type] = make_list();
        if (isnull(instances[name][type + '_files']))
          instances[name][type + '_files'] = make_list();

        instances[name][type] = make_list(instances[name][type], id);
        instances[name][type + '_files'] = make_list(instances[name][type + '_files'], basename);
      }
    }

    fh = FindNextFile(handle:fh);
  }
}

##
# gets a list of instances in the given multiserver environment
#
# @anonparam path root path of the multiserver environment to get instances for
# @return a list of instances if any were discovered,
#         an empty list otherwise
##
function get_instances()
{
  var path, share, dir, rc, fh, length, blob, name, instance_dir, line, match, connector_path;
  path = _FCT_ANON_ARGS[0];

  share = ereg_replace(pattern:'^([A-Za-z]):.*', replace:'\\1$', string:path);
  dir = ereg_replace(pattern:'^[A-Za-z]:(.*)', replace:'\\1', string:path);

  rc = NetUseAdd(login:login, password:pass, domain:domain, share:share);
  if (rc != 1)
  {
    NetUseDel(close:FALSE);
    dbg::detailed_log(lvl:3, src:FUNCTION_NAME, msg:'get_instances: Can\'t connect to '+share+' share.');
    return;
  }

  fh = CreateFile(
    file:dir + '\\lib\\servers.xml',
    desired_access:GENERIC_READ,
    file_attributes:FILE_ATTRIBUTE_NORMAL,
    share_mode:FILE_SHARE_READ,
    create_disposition:OPEN_EXISTING
  );
  if (!isnull(fh))
  {
    length = GetFileSize(handle:fh);
    if (length > 32678) length = 32678;
    blob = ReadFile(handle:fh, offset:0, length:length);
    CloseFile(handle:fh);

    # poor man's xml parser, which should work fine since
    # this file isn't supposed to be edited manually
    foreach line (split(blob, sep:'\n', keep:FALSE))
    {
      if ('<server>' >< line)
      {
        name = NULL;
        instance_dir = NULL;
        continue;
      }

      match = pregmatch(string:line, pattern:'<name>([^<]+)</name>');
      if (!isnull(match))
      {
        name = match[1];
        continue;
      }

      match = pregmatch(string:line, pattern:'<directory>([^<]+)</directory>');
      if (!isnull(match))
      {
        instance_dir = str_replace(string:match[1], find:'{jrun.home}', replace:path);
        instance_dir = str_replace(string:instance_dir, find:'/', replace:'\\');

        if (instance_dir !~ '\\\\cfusion$')
          instance_dir += '\\cfusion.ear\\cfusion.war';
        else
          instance_dir += '\\cfusion-ear\\cfusion-war';
      }

      if ('</server>' >< line && !isnull(name) && !isnull(instance_dir))
      {
        instances[name]['webroot'] = instance_dir;
        instances[name]['cfroot'] = instance_dir;
        instances[name]['jrun_home'] = path;
        instances[name]['type'] = 'Multiserver';

        # it appears the optional 3rd party connector can only be used with the 'default' instance
        if (instance_dir =~ '\\\\cfusion-war')
        {
          connector_path = get_connector_path(dir);
          if (!isnull(connector_path))
            instances[name]['webroot'] = connector_path;
        }
      }
    }
  }
  else dbg::detailed_log(lvl:3, src:FUNCTION_NAME, msg:'Unable to open ' + dir + '\\lib\\servers.xml');

  NetUseDel(close:FALSE);
}

##
# gets the webroot of a multiserver instance when it's hosted by a 'connector',
# i.e. a 3rd party web server like IIS, Apache, Sun ONE
#
# this function assumes it's already connected to the relevant
# share, and 'path' is relative to that share
#
# @anonparam path root path of the multiserver environment
# @return path to the webroot if it was found,
#         NULL otherwise
##
function get_connector_path()
{
  var path, instance, bat, fh, length, blob, match, webroot;
  path = _FCT_ANON_ARGS[0];
  webroot = NULL;

  bat = FindFirstFile(pattern:path + "\ConnectorInstall*.bat");
  while (!isnull(bat[1]))
  {
    fh = CreateFile(
      file:path + '\\' + bat[1],
      desired_access:GENERIC_READ,
      file_attributes:FILE_ATTRIBUTE_NORMAL,
      share_mode:FILE_SHARE_READ,
      create_disposition:OPEN_EXISTING
    );
    if (!isnull(fh))
    {
      length = GetFileSize(handle:fh);
      if (length > 1024) length = 1024;  # this is going to be 2 lines of text, was less than 1k
      blob = ReadFile(handle:fh, offset:0, length:length);
      CloseFile(handle:fh);

      match = pregmatch(string:blob, pattern:'-cfwebroot *"([^"]+)"');
      if (!isnull(match))
      {
        webroot = match[1];
        break;
      }
    }
    bat = FindNextFile(handle:bat);
  }

  return webroot;
}


#
# plugin starts here
#

var app = 'Adobe ColdFusion';
var vendor = 'Adobe';
var product = 'ColdFusion';
var extras, cpe, path, chf_version, release_version;
var key, prod, key_h, item, tmp, match;
var i, subkey, key2, key2_h, info, cfroot, webroot;
var major, ver, build, type, jrun_home, hf, chf;

extras = make_list();

get_kb_item_or_exit('SMB/Registry/Enumerated');

var list = get_kb_list('SMB/Registry/HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall/*/DisplayName');
if (isnull(list)) audit(AUDIT_KB_MISSING, "SMB/Registry/HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall/*/DisplayName");
var multiserver = make_list();

# enumerate possible multiserver installs
foreach key (keys(list))
{
  prod = list[key];
  if (isnull(prod)) continue;

  # version < 8 does not have this key it seems
  if (prod =~ 'Adobe ColdFusion [89] with JRun 4' ||
      prod =~ 'Adobe ColdFusion 2018' ||
      prod =~ 'Adobe ColdFusion 2016')
  {
    key -= 'SMB/Registry/HKLM/';
    key -= '/DisplayName';
    key = str_replace(string:key, find:'/', replace:'\\');

    multiserver = make_list(multiserver, key);
  }
}

if(! smb_session_init()) audit(AUDIT_FN_FAIL, 'smb_session_init');
var rc = NetUseAdd(login:login, password:pass, domain:domain, share:'IPC$');
if (rc != 1)
{
  NetUseDel();
  audit(AUDIT_SHARE_FAIL, "IPC$");
}

# Connect to remote registry
var hklm = RegConnectRegistry(hkey:HKEY_LOCAL_MACHINE);
if (isnull(hklm))
{
  NetUseDel();
  audit(AUDIT_REG_FAIL);
}

# get Multiserver install path(s)
var multiserver_paths = make_list();
foreach key (multiserver)
{

  key_h = RegOpenKey(handle:hklm, key:key, mode:MAXIMUM_ALLOWED);
  if (!isnull(key_h))
  {
    item = RegQueryValue(handle:key_h, item:'InstallLocation');

    if(isnull(item))
    {
      item = RegQueryValue(handle:key_h, item:'DisplayIcon');
      if(!isnull(item))
      {
        tmp = str_replace(find:'"', replace:"", string:item[1]);
        tmp = str_replace(find:"'", replace:"", string:tmp);

        match = pregmatch(pattern:"^(.+)\\[^\\]*$", string:tmp);
        if(!isnull(match) && !isnull(match[1]))
          item[1] = match[1];
        else item = NULL;
      }
    }

    if(!isnull(item))
      multiserver_paths = make_list(multiserver_paths, item[1]);

    RegCloseKey(handle:key_h);

  }
}

# get (single) Server install path(s)
var keys = make_list('SOFTWARE\\Adobe\\Install Data', 'SOFTWARE\\Macromedia\\Install Data', 'SOFTWARE\\Wow6432Node\\Adobe\\Install Data');

foreach key (keys)
{
  key_h = RegOpenKey(handle:hklm, key:key, mode:MAXIMUM_ALLOWED);
  if (!isnull(key_h))
  {
    info = RegQueryInfoKey(handle:key_h);
    for (i=0; i<info[1]; ++i)
    {
      subkey = RegEnumKey(handle:key_h, index:i);
      dbg::detailed_log(lvl:3, src:'coldfusion_win_local_detect', msg:"Subkey found: " + subkey);
      match = pregmatch(string:subkey, pattern:"^(Adobe ColdFusion|ColdFusion MX) (\d+)$");

      if (isnull(match)) major = NULL;
      else major = match[1];

      if (!isnull(major))
      {
        key2 = key + "\" + subkey;
        key2_h = RegOpenKey(handle:hklm, key:key2, mode:MAXIMUM_ALLOWED);
        if (!isnull(key2_h))
        {
          cfroot = RegQueryValue(handle:key2_h, item:"CFMXRoot");
          webroot = RegQueryValue(handle:key2_h, item:"WebRoot");

          if (!isnull(cfroot) && !isnull(webroot))
          {
            # we'll generate a bogus instance name just to have a unique key.
            name = 'Server-' +  major +  '-' +  rand();
            instances[name]['cfroot'] = cfroot[1];
            instances[name]['type'] = 'Server';

            if (isnull(webroot[1]))
              instances[name]['webroot'] = cfroot[1] + "\wwwroot";
            else
              instances[name]['webroot'] = webroot[1];
          }
          RegCloseKey(handle:key2_h);
        }
      }
    }
    RegCloseKey(handle:key_h);
  }
}

RegCloseKey(handle:hklm);

# check if any potential multiserver or single server installs were detected in the registry
if (max_index(multiserver_paths) == 0 && max_index(keys(instances)) == 0)
{
  NetUseDel();
  audit(AUDIT_NOT_INST, "ColdFusion");
}
else NetUseDel(close:FALSE);

# gets the path of each instance used in a multiserver install. this info is
# stored in the global variable 'instances'
foreach path (multiserver_paths)
  get_instances(path);

# Checks if each instance is valid, and if so, collects version, build, and hotfix info
foreach name (keys(instances))
  check_instance(name);

NetUseDel();

info = NULL;

# Checks if any of the instances are valid, and starts building plugin output
foreach name (keys(instances))
{

  # we'll determine whether or not an instance is valid based on whether
  # we were able to determine its version number
  dbg::detailed_log(lvl:3, src:'coldfusion_win_local_detect', msg:"Checking instance: " + name);
  ver = instances[name]['version'];
  if (isnull(ver)) continue;

  # some instance names are artificially created by this plugin just to provide
  # a way to uniquely identify instances. they should only be used as a way of
  # getting instances from the KB, and should not be used in reports
  set_kb_item(name:'SMB/coldfusion/instance', value:name);
  set_kb_item(name:'SMB/coldfusion/' + name + '/version', value:ver);
  release_version = ver;
  if (instances[name]['build'])
  {
    build = instances[name]['build'];
    set_kb_item(name:'SMB/coldfusion/' + name + '/build', value:build);
  }
  if (instances[name]['type'])
  {
    type = instances[name]['type'];
    set_kb_item(name:'SMB/coldfusion/' + name + '/type', value:type);
  }
  if (instances[name]['cfroot'])
  {
    cfroot = instances[name]['cfroot'];
    set_kb_item(name:'SMB/coldfusion/' + name + '/cfroot', value:cfroot);
  }
  if (instances[name]['webroot'])
  {
    webroot = instances[name]['webroot'];
    set_kb_item(name:'SMB/coldfusion/' + name + '/webroot', value:webroot);
  }
  if (instances[name]['jrun_home'])
  {
    jrun_home = instances[name]['jrun_home'];
    set_kb_item(name:'SMB/coldfusion/' + name + '/jrun_home', value:jrun_home);
  }


  info +=
    '\n    ColdFusion root : ' + cfroot +
    '\n    Web root        : ' + webroot +
    '\n    Version         : ' + ver;

    extras['Web root'] = webroot;
  if (!isnull(build)) info += '.' + build;

  info += '\n    Instance type   : ' + type;

  foreach hf (instances[name]['hf'])
    set_kb_item(name:'SMB/coldfusion/' + name + '/hf', value:hf);

  # Initialize chf_version to 0 for hosts with no CHF hotfixes
  extras['chf_version'] = 0;

  foreach chf (instances[name]['chf'])
  {
    if (empty_or_null(chf))
      chf = 0;

    set_kb_item(name:'SMB/coldfusion/' + name + '/chf', value:chf);
    if (int(chf) > extras['chf_version'])
      extras['chf_version'] = int(chf);
  }

  if (max_index(instances[name]['hf']) > 0)
  {
    info += '\n    Hotfixes : ' + join(instances[name]['hf_files'], sep:', ');
    extras['Hotfixes'] = join(instances[name]['hf_files'], sep:', ');
  }
  if (max_index(instances[name]['chf']) > 0)
  {
    info += '\n    Cumulative Hotfixes : ' + join(instances[name]['chf_files'], sep:', ');
    extras['Cumulative Hotfixes'] = join(instances[name]['chf_files'], sep:', ');
  }
  info += '\n';

  register_install(
    app_name:app,
    vendor:vendor,
    product:product,
    extra:extras,
    path:cfroot,
    version: release_version
  );

}

report_installs(app_name: app);

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

11 Jun 2026 00:00Current
5.5Medium risk
Vulners AI Score5.5
30