peass-ng/PEASS-ng · error · RuntimeError

Invalid URL

Error message

Invalid URL

What it means

load_peass() parses the configured PEASS URL with URI.parse and validates that the scheme is http/https and a host is present. A URL failing either check raises 'Invalid URL', guarding against malformed custom WINPEASS/LINPEAS option values.

Source

Thrown at metasploit/peass.rb:278

    else
      response.value
    end
  end
 
  def load_peass
    # Load the PEASS script from a local file or from Internet
    peass_script = ""
    url_peass = ""
    # If no URL is set, use the default one
    if datastore['CUSTOM_URL'] != ""
      url_peass = datastore['CUSTOM_URL']
    else
      url_peass = datastore['WINPEASS'].to_s.strip.downcase == 'true' ? "https://github.com/peass-ng/PEASS-ng/releases/latest/download/winPEASany_ofs.exe" : "https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh"
    end
    # If URL is set, check if it is a valid URL or local file
    if url_peass.include?("http://") || url_peass.include?("https://")
      target = URI.parse url_peass
      raise 'Invalid URL' unless target.scheme =~ /https?/
      raise 'Invalid URL' if target.host.to_s.eql? ''
      
      res = fetch(target)
      peass_script = res.body

      raise "Something failed downloading PEASS script from #{url_peass}" if peass_script.length < 500

    else
      raise "PEASS local file (#{url_peass}) does not exist!" unless ::File.exist?(url_peass)        
      peass_script = File.read(url_peass)
      raise "Something falied reading PEASS script from #{url_peass}" if peass_script.length < 500
    end

    return peass_script
  end

  def aes_enc_peass(peass_script)
    # Encrypt the PEASS script with AES (CBC Mode)

View on GitHub (pinned to 53fb989abc)

Solutions

  1. Correct the URL to a full http(s) URL including host, e.g. https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh
  2. Validate with URI.parse in Ruby beforehand or curl the URL
  3. If serving a local file, use a local path without http:// instead of the URL mode

Example fix

# before
set LINPEAS https:/myhost.local/linpeas.sh
# after
set LINPEAS https://myhost.local/linpeas.sh
Defensive patterns

Strategy: validation

Validate before calling

require 'uri'
u = URI.parse(datastore['LINPEAS'].to_s)
raise "Invalid URL" unless u.scheme =~ /https?/ && !u.host.to_s.empty?

Type guard

def valid_peass_url?(str)
  return false unless str.is_a?(String) && str.include?('http')
  u = URI.parse(str) rescue return false
  u.scheme =~ /https?/ && !u.host.to_s.empty?
end

Try / catch

begin
  target = URI.parse url_peass
  raise 'Invalid URL' unless target.scheme =~ /https?/ && !target.host.to_s.empty?
rescue URI::InvalidURIError, RuntimeError => e
  print_error("Bad PEASS URL: #{url_peass} (#{e.message}); using default release URL")
end

Prevention

When it happens

Trigger: Running peass with a custom URL in datastore['WINPEASS']/'LINPEAS' that includes http(s):// but has no host (e.g. 'https://') or a non-http scheme after URI.parse (ftp:, file:).

Common situations: Typo'd URLs like 'https:/host/path' (single slash), truncated paste of a URL, pointing at a local file path that happens to contain 'http', or scheme typos like 'https//'.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of peass-ng/PEASS-ng@53fb989abc (2026-09-02). Data as JSON: /api/errors/3ac01140430c964b. Report an issue: GitHub.