Module: Homebrew::Vulns::OSV Private

Defined in:
vulns/osv.rb

Overview

This module is part of a private API. This module may only be used in the Homebrew/brew repository. Third parties should avoid using this module if possible, as it may be removed or changed without warning.

Client for https://google.github.io/osv.dev/api/.

Defined Under Namespace

Classes: ApiError, Error

Constant Summary collapse

API_BASE =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

"https://api.osv.dev/v1"
BATCH_SIZE =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

1000
MAX_PAGES =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

100

Class Method Summary collapse

Class Method Details

.query_batch(packages) ⇒ Array<Array<Hash{String => T.untyped}>>

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

POST /v1/querybatch. Returns one array of vuln hashes per input package, in the same order. Follows per-result next_page_token continuations.

Parameters:

Returns:



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'vulns/osv.rb', line 24

def self.query_batch(packages)
  return [] if packages.empty?

  results = Array.new(packages.size) { [] }

  packages.each_slice(BATCH_SIZE).with_index do |batch, batch_index|
    offset = batch_index * BATCH_SIZE
    pending = batch.map.with_index do |pkg, index|
      {
        slot:  offset + index,
        query: { package: { name: pkg.fetch(:repo_url), ecosystem: "GIT" }, version: pkg.fetch(:version) },
      }
    end

    page = 0
    while pending.any?
      page += 1
      if page > MAX_PAGES
        raise ApiError, "OSV API returned more than #{MAX_PAGES} pages for a querybatch; aborting"
      end

      response = post("#{API_BASE}/querybatch", { queries: pending.map { |p| p.fetch(:query) } })
      batch_results = response["results"]
      if !batch_results.is_a?(Array) || batch_results.length != pending.length
        got = batch_results.is_a?(Array) ? batch_results.length : batch_results.class
        raise ApiError,
              "OSV API querybatch: expected #{pending.length} results, got #{got}"
      end

      continued = []
      batch_results.each_with_index do |result, index|
        entry = pending.fetch(index)
        results.fetch(entry.fetch(:slot)).concat(Array(result["vulns"]))
        token = result["next_page_token"]
        next if token.to_s.empty?

        continued << {
          slot:  entry.fetch(:slot),
          query: entry.fetch(:query).merge(page_token: token),
        }
      end
      pending = continued
    end
  end

  results
end

.vulnerability(id) ⇒ Hash{String => T.untyped}

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

GET /v1/vulns/id.

Parameters:

Returns:



74
75
76
# File 'vulns/osv.rb', line 74

def self.vulnerability(id)
  get("#{API_BASE}/vulns/#{ERB::Util.url_encode(id)}")
end