Google Safe Browsing API を JavaScript で活用する方法

## Google Safe Browsing APIとは

Google Safe Browsing APIは、Googleが提供するサービスで、URLから危険なサイトかどうかを判定するためのAPI

- **フィッシングサイトの検出**
> 偽のウェブサイトに誘導し、個人情報を盗み出すことを目的としたフィッシングサイトであるか

- **マルウェアやその他不正なソフトウエアの検知:**
> ウェブサイトからダウンロードされるファイルが、マルウェアや不正なソフトウェアを含んでいる可能性があるか

(APIを実行したその時点での情報ではなく、通報などを受けて確認された結果からブラックリストが作られ、指定のURLがそのブラックリストに含まれるかを確認するもの)

## 準備

### 僕の環境

|JavaScriptランタイム|バージョン|
|---|---|
|Node.js|v18.20.3|

### APIを使うためのAPIキーを取得

- [Google Cloud Console](https://console.cloud.google.com/) を開く
(ログインしてなければ、ログインする)

-  左上の「My First Project」をクリックして、新しいプロジェクトを作成
(名前は何でもいい)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3875230/37ec9009-6c66-2a35-a108-d9158d3c1a70.png)

- 少し待つと作成されるので、もう一回「プロジェクトを選択」を開いて、さっき作成したプロジェクトに移動

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3875230/5abbdeb7-9760-c3c5-1b00-d8dcf93e1938.png)

- クイック アクセスの「APIとサービス」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3875230/7239eef6-b384-e4d9-1f2e-abbaac323bf4.png)

- 「API とサービス」の文字の左にある「API」とサービスを有効にするをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3875230/1cc5e0bd-b207-97fc-e7e7-3e2a5ef5bf8a.png)

- 「API ライブラリ」に飛ぶので、「safe browsing api」と検索

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3875230/e84ba70a-36c4-2463-34d4-72a5e5f067be.png)

- 2つ出てくると思いますが、Legacyではない方の「Safe Browsing API」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3875230/e745f01b-326d-539d-05a5-09c360a42928.png)

- 「有効にする」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3875230/1d41674d-42ad-7c83-0f61-d22fdf8f26a0.png)

- 「この API を使用するには、認証情報が必要になる可能性があります。」と出るので、「認証情報の作成」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3875230/aed6d846-187e-c95f-7247-32912bcf1eb5.png)

- 「一般公開データ」をクリックして、「次へ」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3875230/332030ce-a787-a444-bd36-077e232edd5e.png)

- APIキーが出るのでどっかにメモる

- 使用できる環境を制限すべきという警告が出るけど、今回は使われても痒くも痛くないので無視して「完了」
(Google Safe Browsingは、制限があるけど無料: 1日10,000リクエストまで行けた気がする)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3875230/7a994aa5-0fb0-e9bf-f126-053b03f964da.png)

## 実装

`googleapis`というパッケージを使えばもっと簡単に書けるらしいけど、今回はこれで

```js
const API_GOOGLE_SAFEBROWSING_KEY = "ここにさっきのAPIキーを貼る";
const API_GOOGLE_SAFEBROWSING_ENDPOINT = `https://safebrowsing.googleapis.com/v4/threatMatches:find?key=${API_GOOGLE_SAFEBROWSING_KEY}`;

/**
 * @param { string } url
 */
async function checkUrlSafety(url) {
  const req = await fetch(API_GOOGLE_SAFEBROWSING_ENDPOINT, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Accept: 'application/json',
    },
    body: JSON.stringify({
      client: {
        // clientIdとclientVersionは、何指定してもいいらしい
        clientId: 'demo',
        clientVersion: '1.0',
      },
      threatInfo: {
        threatEntries: [{ url: url }],
        threatTypes: [
          'MALWARE',
          'SOCIAL_ENGINEERING',
          'UNWANTED_SOFTWARE',
          'THREAT_TYPE_UNSPECIFIED',
          'POTENTIALLY_HARMFUL_APPLICATION',
        ],
        platformTypes: ['PLATFORM_TYPE_UNSPECIFIED', 'ANY_PLATFORM'],
        threatEntryTypes: ['URL'],
      },
    }),
  });

  const res = await req.json();

  return res;
}

(async () => {
  const result = await checkUrlSafety("https://testsafebrowsing.appspot.com/s/phishing.html");
  console.log(result.match ? "危険" : "安全");
  console.log(result);
})();
```

### 使い方

```js
checkUrlSafety("https://testsafebrowsing.appspot.com/s/phishing.html")
```
のURLのところは、[(Safe) Safe Browsing Testing Links](https://testsafebrowsing.appspot.com/) に他にもテスト用リンクが載っているのでそれでテストしてみて

## 参考にしたもの

- [概要 | Safe Browsing APIs (v4)](https://developers.google.com/safe-browsing/v4?hl=ja)
- なぜか、{}しか返ってこない時の解決方法: [**Google Safe Browsing API v4 - Empty response**](https://groups.google.com/g/google-safe-browsing-api/c/-Peow2YWmlo)