urbanadventurer/WhatWeb · error · Net::HTTPBadResponse

wrong header line format

Error message

wrong header line format

What it means

Net::HTTPBadResponse raised by each_response_header in lib/extend-http.rb when a header line from an HTTP response cannot be parsed into a key:value pair (the split on the ':' separator yields no value). The library uses this custom header parser (handling continuation lines starting with space/tab) and treats an unparseable line as a malformed response, aborting parsing. It indicates the remote server sent a response that does not conform to the HTTP header format.

Solutions

  1. Verify the target port actually speaks HTTP (curl -v http://host:port) before scanning
  2. Skip or re-target ports that are not HTTP services; use a plain TCP probe first
  3. If you control the server, fix it to emit RFC-compliant headers (each line must be 'Name: value')
  4. Check for a broken/misconfigured proxy between you and the target stripping or corrupting headers

Example fix

// before: any port treated as HTTP
Target.new('http://example.com:22')
// after: confirm HTTP first or catch
begin
  Target.new('http://example.com:22')
rescue Net::HTTPBadResponse
  puts 'target does not speak HTTP'
end
Defensive patterns

Strategy: try-catch

Validate before calling

// Ruby: probe that the port speaks HTTP before scanning
def http?(host, port)
  sock = TCPSocket.new(host, port)
  sock.puts "HEAD / HTTP/1.0\r\nHost: #{host}\r\n\r\n"
  first = sock.gets.to_s
  sock.close
  first.start_with?('HTTP/')
rescue StandardError
  false
end

Type guard

def valid_target?(url)
  uri = URI.parse(url) rescue nil
  !uri.nil? && %w[http https].include?(uri.scheme)
end

Try / catch

begin
  target = Target.new(url)
rescue Net::HTTPBadResponse => e
  logger.warn("malformed HTTP response from #{url}: #{e.message}")
  next # skip this target
end

Prevention

When it happens

Trigger: Calling Target#open or any WhatWeb plugin scan against a server whose response contains a header line without a ':' separator and no valid key already parsed (e.g. a raw garbage line, a binary/HTML body starting in the header area, or a non-HTTP service on the target port). Reached via read_new -> each_response_header during response reading.

Common situations: Scanning a port where a non-HTTP service (SSH, FTP, custom TCP daemon) answers; misconfigured proxies that inject non-header text; servers emitting malformed headers (missing colon, bare continuation lines without a preceding key); headless/embedded devices with broken HTTP implementations.


AI-assisted analysis of urbanadventurer/WhatWeb@d279d93042 (2026-09-15). Data as JSON: /api/errors/8f9bfb997e2d6776. Report an issue: GitHub.

Appendix: source

Thrown at lib/extend-http.rb:330

    [str] + m.captures
  end

  def each_response_header(sock)
    key = value = nil
    loop do
      line = sock.readuntil("\n", true).sub(/\s+\z/, '')
      # added for whatweb
      @rawlines << line + "\n" unless line.nil?
      #
      break if line.empty?

      if line[0] == ' ' || line[0] == "\t" && value
        value << ' ' unless value.empty?
        value << line.strip
      else
        yield key, value if key
        key, value = line.strip.split(/\s*:\s*/, 2)
        raise Net::HTTPBadResponse, 'wrong header line format' if value.nil?
      end
    end
    yield key, value if key
  end
  end

  ###################

  public

  #    include HTTPHeader

  def initialize(httpv, code, msg) #:nodoc: internal use only
    @http_version = httpv
    @code         = code
    @message      = msg
    initialize_http_header nil
    @body = nil

View on GitHub (pinned to d279d93042)