You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: vulnerability_auditor.rb
    path of file: ./repos/dependabot-core/npm_and_yarn/lib/dependabot/npm_and_yarn/update_checker
    
    the code of the file until where you have to start completion: # typed: true
# frozen_string_literal: true

require "stringio"
require "dependabot/dependency"
require "dependabot/errors"
require "dependabot/logger"
require "dependabot/npm_and_yarn/file_parser"
require "dependabot/npm_and_yarn/helpers"
require "dependabot/npm_and_yarn/native_helpers"
require "dependabot/npm_and_yarn/update_checker"
require "dependabot/npm_and_yarn/update_checker/dependency_files_builder"
require "dependabot/shared_helpers"

module Dependabot
  module NpmAndYarn
    class UpdateChecker < Dependabot::UpdateCheckers::Base
      class VulnerabilityAuditor
        def initialize(dependency_files:, credentials:)
          @dependency_files = dependency_files
          @credentials = credentials
        end

        # rubocop:disable Metrics/MethodLength
        # Finds any dependencies in the `package-lock.json` or `npm-shrinkwrap.json` that have
        # a subdependency on the given dependency that is locked to a vuln version range.
        #
        # NOTE: yarn is currently not supported.
        #
        # @param dependency [Dependabot::Dependency] the dependency to check
        # @param security_advisories [Array<Dependabot::SecurityAdvisory>] advisories for the dependency
        # @return [Hash<String, [String, Array<Hash<String, String>>]>] the audit results
        #   * :depend
    
        def validate_audit_result(audit_result, security_advisories)
          return :fix_unavailable unless audit_result["fix_available"]
          return :dependency_still_vulnerable if dependency_still_vulnerable?(audit_result, security_advisories)
          return :downgrades_dependencies if downgrades_dependencies?(audit_result)
          return :fix_incomplete if fix_incomplete?(audit_result)

          :viable
        end

        def dependency_still_vulnerable?(audit_result, security_advisories)
          # vulnerable dependency is removed if the target version is nil
          return false unless audit_result["target_version"]

          version = Version.new(audit_result["target_version"])
          security_advisories.any? { |a| a.vulnerable?(version) }
        end

        def downgrades_dependencies?(audit_result)
          return true if downgrades_version?(audit_result["current_version"], audit_result["target_version"])

          audit_result["fix_updates"].any? do |update|
            downgrades_version?(update["current_version"], update["target_version"])
          end
        end

        def downgrades_version?(current_version, target_version)
          return false unless target_version

          current = Version.new(current_version)
          target = Version.new(target_version)
          current > target
        end

        def fix_incomplete?(audit_result)
          audit_result["fix_updates"].any? { |update| !update.key?("target_version") } ||
            audit_result["fix_updates"].empty?
        end

        def log_helper_subprocess_failure(dependency, error)
          # See `Dependabot::SharedHelpers.run_helper_subprocess` for details on error context
          context = error.error_context || {}

          builder = ::StringIO.new
          builder << "VulnerabilityAuditor: "
          builder << "#{context[:function]} " if context[:function]
          builder << "failed"
          builder << " after #{context[:time_taken].truncate(2)}s" if context[:time_taken]
          builder << " while auditing #{dependency.name}: "
          builder << error.message
          builder << "\n" << context[:trace]

          msg = builder.string
          Dependabot.logger.info(msg) # TODO: is this the right log level?
        end
      end
    end