| 
									
										
										
										
											2020-10-10 14:16:11 +02:00
										 |  |  | # typed: true | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | require "utils/curl" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-26 09:42:39 +02:00
										 |  |  | # Auditing functions for rules common to both casks and formulae. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # @api private | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  | module SharedAudits | 
					
						
							| 
									
										
										
										
											2020-10-10 15:23:03 +02:00
										 |  |  |   include Utils::Curl | 
					
						
							|  |  |  |   extend Utils::Curl | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  |   module_function | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 21:52:35 +02:00
										 |  |  |   def github_repo_data(user, repo) | 
					
						
							|  |  |  |     @github_repo_data ||= {} | 
					
						
							|  |  |  |     @github_repo_data["#{user}/#{repo}"] ||= GitHub.repository(user, repo) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 14:21:06 +02:00
										 |  |  |     @github_repo_data["#{user}/#{repo}"] | 
					
						
							| 
									
										
										
										
											2020-07-20 21:52:35 +02:00
										 |  |  |   rescue GitHub::HTTPNotFoundError | 
					
						
							|  |  |  |     nil | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-13 16:17:47 +02:00
										 |  |  |   def github_release_data(user, repo, tag) | 
					
						
							|  |  |  |     id = "#{user}/#{repo}/#{tag}" | 
					
						
							|  |  |  |     @github_release_data ||= {} | 
					
						
							|  |  |  |     @github_release_data[id] ||= GitHub.open_api("#{GitHub::API_URL}/repos/#{user}/#{repo}/releases/tags/#{tag}") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @github_release_data[id] | 
					
						
							|  |  |  |   rescue GitHub::HTTPNotFoundError | 
					
						
							|  |  |  |     nil | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 05:41:58 +02:00
										 |  |  |   def github_release(user, repo, tag, formula: nil, cask: nil) | 
					
						
							|  |  |  |     release = github_release_data(user, repo, tag) | 
					
						
							|  |  |  |     return unless release | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 10:51:29 -05:00
										 |  |  |     exception, name, version = if formula | 
					
						
							|  |  |  |       [tap_audit_exception(:github_prerelease_allowlist, formula.tap, formula.name), formula.name, formula.version] | 
					
						
							|  |  |  |     elsif cask | 
					
						
							|  |  |  |       [tap_audit_exception(:github_prerelease_allowlist, cask.tap, cask.token), cask.token, cask.version] | 
					
						
							| 
									
										
										
										
											2020-09-05 05:41:58 +02:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 10:51:29 -05:00
										 |  |  |     return "#{tag} is a GitHub pre-release." if release["prerelease"] && [version, "all"].exclude?(exception) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-24 13:36:18 -05:00
										 |  |  |     if !release["prerelease"] && exception | 
					
						
							|  |  |  |       return "#{tag} is not a GitHub pre-release but '#{name}' is in the GitHub prerelease allowlist." | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2020-09-05 05:41:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return "#{tag} is a GitHub draft." if release["draft"] | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 21:52:35 +02:00
										 |  |  |   def gitlab_repo_data(user, repo) | 
					
						
							|  |  |  |     @gitlab_repo_data ||= {} | 
					
						
							|  |  |  |     @gitlab_repo_data["#{user}/#{repo}"] ||= begin | 
					
						
							| 
									
										
										
										
											2020-11-10 00:11:22 +11:00
										 |  |  |       out, _, status = curl_output("https://gitlab.com/api/v4/projects/#{user}%2F#{repo}") | 
					
						
							|  |  |  |       JSON.parse(out) if status.success? | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2020-07-20 21:52:35 +02:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-13 16:17:47 +02:00
										 |  |  |   def gitlab_release_data(user, repo, tag) | 
					
						
							|  |  |  |     id = "#{user}/#{repo}/#{tag}" | 
					
						
							|  |  |  |     @gitlab_release_data ||= {} | 
					
						
							|  |  |  |     @gitlab_release_data[id] ||= begin | 
					
						
							| 
									
										
										
										
											2020-11-10 00:11:22 +11:00
										 |  |  |       out, _, status = curl_output( | 
					
						
							| 
									
										
										
										
											2020-09-05 13:29:48 -04:00
										 |  |  |         "https://gitlab.com/api/v4/projects/#{user}%2F#{repo}/releases/#{tag}", "--fail" | 
					
						
							| 
									
										
										
										
											2020-08-13 16:17:47 +02:00
										 |  |  |       ) | 
					
						
							| 
									
										
										
										
											2020-11-10 00:11:22 +11:00
										 |  |  |       JSON.parse(out) if status.success? | 
					
						
							| 
									
										
										
										
											2020-08-13 16:17:47 +02:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 12:53:12 -05:00
										 |  |  |   def gitlab_release(user, repo, tag, formula: nil, cask: nil) | 
					
						
							| 
									
										
										
										
											2020-09-05 06:07:55 +02:00
										 |  |  |     release = gitlab_release_data(user, repo, tag) | 
					
						
							|  |  |  |     return unless release | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return if Date.parse(release["released_at"]) <= Date.today | 
					
						
							| 
									
										
										
										
											2020-12-21 12:53:12 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 10:51:29 -05:00
										 |  |  |     exception, version = if formula | 
					
						
							|  |  |  |       [tap_audit_exception(:gitlab_prerelease_allowlist, formula.tap, formula.name), formula.version] | 
					
						
							| 
									
										
										
										
											2020-12-21 12:53:12 -05:00
										 |  |  |     elsif cask | 
					
						
							| 
									
										
										
										
											2020-12-22 10:51:29 -05:00
										 |  |  |       [tap_audit_exception(:gitlab_prerelease_allowlist, cask.tap, cask.token), cask.version] | 
					
						
							| 
									
										
										
										
											2020-12-21 12:53:12 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2020-12-22 10:51:29 -05:00
										 |  |  |     return if [version, "all"].include?(exception) | 
					
						
							| 
									
										
										
										
											2020-09-05 06:07:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     "#{tag} is a GitLab pre-release." | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 21:52:35 +02:00
										 |  |  |   def github(user, repo) | 
					
						
							|  |  |  |     metadata = github_repo_data(user, repo) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  |     return if metadata.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 12:53:12 -05:00
										 |  |  |     return "GitHub fork (not canonical repository)" if metadata["fork"] | 
					
						
							| 
									
										
										
										
											2020-09-05 19:08:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  |     if (metadata["forks_count"] < 30) && (metadata["subscribers_count"] < 30) && | 
					
						
							|  |  |  |        (metadata["stargazers_count"] < 75) | 
					
						
							|  |  |  |       return "GitHub repository not notable enough (<30 forks, <30 watchers and <75 stars)" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return if Date.parse(metadata["created_at"]) <= (Date.today - 30) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     "GitHub repository too new (<30 days old)" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def gitlab(user, repo) | 
					
						
							| 
									
										
										
										
											2020-07-20 21:52:35 +02:00
										 |  |  |     metadata = gitlab_repo_data(user, repo) | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return if metadata.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return "GitLab fork (not canonical repository)" if metadata["fork"] | 
					
						
							|  |  |  |     if (metadata["forks_count"] < 30) && (metadata["star_count"] < 75) | 
					
						
							|  |  |  |       return "GitLab repository not notable enough (<30 forks and <75 stars)" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return if Date.parse(metadata["created_at"]) <= (Date.today - 30) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     "GitLab repository too new (<30 days old)" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def bitbucket(user, repo) | 
					
						
							|  |  |  |     api_url = "https://api.bitbucket.org/2.0/repositories/#{user}/#{repo}" | 
					
						
							|  |  |  |     out, _, status= curl_output("--request", "GET", api_url) | 
					
						
							|  |  |  |     return unless status.success? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     metadata = JSON.parse(out) | 
					
						
							|  |  |  |     return if metadata.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return "Uses deprecated mercurial support in Bitbucket" if metadata["scm"] == "hg" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return "Bitbucket fork (not canonical repository)" unless metadata["parent"].nil? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return "Bitbucket repository too new (<30 days old)" if Date.parse(metadata["created_on"]) >= (Date.today - 30) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     forks_out, _, forks_status= curl_output("--request", "GET", "#{api_url}/forks") | 
					
						
							|  |  |  |     return unless forks_status.success? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     watcher_out, _, watcher_status= curl_output("--request", "GET", "#{api_url}/watchers") | 
					
						
							|  |  |  |     return unless watcher_status.success? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     forks_metadata = JSON.parse(forks_out) | 
					
						
							|  |  |  |     return if forks_metadata.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     watcher_metadata = JSON.parse(watcher_out) | 
					
						
							|  |  |  |     return if watcher_metadata.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-19 12:02:59 -04:00
										 |  |  |     return if forks_metadata["size"] >= 30 || watcher_metadata["size"] >= 75
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     "Bitbucket repository not notable enough (<30 forks and <75 watchers)" | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2020-09-09 08:57:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def github_tag_from_url(url) | 
					
						
							|  |  |  |     url = url.to_s | 
					
						
							|  |  |  |     tag = url.match(%r{^https://github\.com/[\w-]+/[\w-]+/archive/([^/]+)\.(tar\.gz|zip)$}) | 
					
						
							|  |  |  |              .to_a | 
					
						
							|  |  |  |              .second | 
					
						
							|  |  |  |     tag ||= url.match(%r{^https://github\.com/[\w-]+/[\w-]+/releases/download/([^/]+)/}) | 
					
						
							|  |  |  |                .to_a | 
					
						
							|  |  |  |                .second | 
					
						
							|  |  |  |     tag | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def gitlab_tag_from_url(url) | 
					
						
							|  |  |  |     url = url.to_s | 
					
						
							|  |  |  |     url.match(%r{^https://gitlab\.com/[\w-]+/[\w-]+/-/archive/([^/]+)/}) | 
					
						
							|  |  |  |        .to_a | 
					
						
							|  |  |  |        .second | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2020-12-21 12:53:12 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def tap_audit_exception(list, tap, formula_or_cask, value = nil) | 
					
						
							|  |  |  |     return false if tap.audit_exceptions.blank? | 
					
						
							|  |  |  |     return false unless tap.audit_exceptions.key? list | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     list = tap.audit_exceptions[list] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case list | 
					
						
							|  |  |  |     when Array | 
					
						
							|  |  |  |       list.include? formula_or_cask | 
					
						
							|  |  |  |     when Hash | 
					
						
							| 
									
										
										
										
											2020-12-22 10:51:29 -05:00
										 |  |  |       return false if list.exclude? formula_or_cask | 
					
						
							| 
									
										
										
										
											2020-12-21 12:53:12 -05:00
										 |  |  |       return list[formula_or_cask] if value.blank? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       list[formula_or_cask] == value | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2020-04-23 21:16:17 +02:00
										 |  |  | end |