GitHub GraphQL APIでVulnerability Alertを取得する

2022.05.02

こんにちは、CX事業本部 IoT事業部の若槻です。

Dependabot alertのalert一覧を取得したく方法を調べていたところ、REST APICLIにはAPIが無く、GraphQL APIにのみAPIが用意されていました。

今回は、GitHub GraphQL APIでのVulnerability Alert(Dependabot alert)の取得を試してみました。

基本的な使い方(curl)

GitHub GraphQL APIの基本的な使い方はこちらに書いてあります。

curlで試してみます。Personal access tokensが必要なのでこちらで発行しておきます。

$ GH_API_TOKEN=<GH_API_TOKEN>
$ query="\"query { viewer { login }}\""

$ curl \
  -H "Authorization: bearer $GH_API_TOKEN" \
  -X POST -d "{ \"query\": ${query}}" \
  https://api.github.com/graphql
{"data":{"viewer":{"login":"cm-rwakatsuki"}}}

クエリ結果が取得できていますね。

Vulnerability Alertの取得(Explorer)

GitHubが用意しているExplorerでGraphQL APIを試すこともできます。

こちらを参考にExplorerでVulnerability Alertの一覧を取得してみます。

取得対象のRepositoryでは、Open中のalert1件とClose済みのalert1件が記録されています。

次のようにクエリを実行します。

query($repo_name:String!, $owner:String!) {
  repository(name: $repo_name, owner: $owner) {
    vulnerabilityAlerts(first: 100) {
      nodes {
        createdAt
        dismissedAt
        state
        securityVulnerability {
          package {
            name
          }
          advisory {
            description
          }
        }
      }
    }
  }
}

{
  "owner": "cm-rwakatsuki",
  "repo_name": "aws-cdk-v2-project"
}

すべてのalertが取得できました。

取得結果

{
  "data": {
    "repository": {
      "vulnerabilityAlerts": {
        "nodes": [
          {
            "createdAt": "2022-04-28T14:12:40Z",
            "dismissedAt": "2022-05-02T14:26:44Z",
            "state": "DISMISSED",
            "securityVulnerability": {
              "package": {
                "name": "log4js"
              },
              "advisory": {
                "description": "### Impact\r\nDefault file permissions for log files created by the file, fileSync and dateFile appenders are world-readable (in unix). This could cause problems if log files contain sensitive information. This would affect any users that have not supplied their own permissions for the files via the mode parameter in the config.\r\n\r\n### Patches\r\nFixed by:\r\n* https://github.com/log4js-node/log4js-node/pull/1141\r\n* https://github.com/log4js-node/streamroller/pull/87\r\n\r\nReleased to NPM in log4js@6.4.0\r\n\r\n### Workarounds\r\nEvery version of log4js published allows passing the mode parameter to the configuration of file appenders, see the documentation for details.\r\n\r\n### References\r\n\r\nThanks to [ranjit-git](https://www.huntr.dev/users/ranjit-git) for raising the issue, and to @peteriman for fixing the problem.\r\n\r\n### For more information\r\nIf you have any questions or comments about this advisory:\r\n* Open an issue in [logj4s-node](https://github.com/log4js-node/log4js-node)\r\n* Ask a question in the [slack channel](https://join.slack.com/t/log4js-node/shared_invite/enQtODkzMDQ3MzExMDczLWUzZmY0MmI0YWI1ZjFhODY0YjI0YmU1N2U5ZTRkOTYyYzg3MjY5NWI4M2FjZThjYjdiOGM0NjU2NzBmYTJjOGI)\r\n* Email us at [gareth.nomiddlename@gmail.com](mailto:gareth.nomiddlename@gmail.com)\r\n"
              }
            }
          },
          {
            "createdAt": "2022-04-30T14:14:00Z",
            "dismissedAt": "2022-04-30T14:21:10Z",
            "state": "OPEN",
            "securityVulnerability": {
              "package": {
                "name": "moment"
              },
              "advisory": {
                "description": "### Impact\nThis vulnerability impacts npm (server) users of moment.js, especially if user provided locale string, eg `fr` is directly used to switch moment locale.\n\n### Patches\nThis problem is patched in 2.29.2, and the patch can be applied to all affected versions (from 1.0.1 up until 2.29.1, inclusive).\n\n### Workarounds\nSanitize user-provided locale name before passing it to moment.js.\n\n### References\n_Are there any links users can visit to find out more?_\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue in [moment repo](https://github.com/moment/moment)\n"
              }
            }
          }
        ]
      }
    }
  }
}

次にOPENStateのAlertのみフィルターして取得してみます。クエリ内でstateパラメータを指定します。

query($repo_name:String!, $owner:String!) {
  repository(name: $repo_name, owner: $owner) {
    vulnerabilityAlerts(first: 100, states: [OPEN]) {
      nodes {
        createdAt
        dismissedAt
        state
        securityVulnerability {
          package {
            name
          }
          advisory {
            description
          }
        }
      }
    }
  }
}

{
  "owner": "cm-rwakatsuki",
  "repo_name": "aws-cdk-v2-project"
}

open中のalertのみ取得できていますね!

取得結果

{
  "data": {
    "repository": {
      "vulnerabilityAlerts": {
        "nodes": [
          {
            "createdAt": "2022-04-30T14:14:00Z",
            "dismissedAt": "2022-04-30T14:21:10Z",
            "state": "OPEN",
            "securityVulnerability": {
              "package": {
                "name": "moment"
              },
              "advisory": {
                "description": "### Impact\nThis vulnerability impacts npm (server) users of moment.js, especially if user provided locale string, eg `fr` is directly used to switch moment locale.\n\n### Patches\nThis problem is patched in 2.29.2, and the patch can be applied to all affected versions (from 1.0.1 up until 2.29.1, inclusive).\n\n### Workarounds\nSanitize user-provided locale name before passing it to moment.js.\n\n### References\n_Are there any links users can visit to find out more?_\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue in [moment repo](https://github.com/moment/moment)\n"
              }
            }
          }
        ]
      }
    }
  }
}

ただ単に「Open中のalertが1件以上あるか」確認したいなら次のように実行します。idプロパティを最低限指定する必要があります。

query($repo_name:String!, $owner:String!) {
  repository(name: $repo_name, owner: $owner) {
    vulnerabilityAlerts(first: 1, states: [OPEN]) {
      nodes {
        id
      } 
    }
  }
}

{
  "owner": "cm-rwakatsuki",
  "repo_name": "aws-cdk-v2-project"
}

Open中のalertの最初の1件が取得できており、Open中のalertが1件以上あることが分かります。また取得結果がすっきりしています。

取得結果

{
  "data": {
    "repository": {
      "vulnerabilityAlerts": {
        "nodes": [
          {
            "id": "RVA_kwDOHJiaXM6K9Q7q"
          }
        ]
      }
    }
  }
}

Open中のalertが0件の場合は次のようになります。

取得結果

{
  "data": {
    "repository": {
      "vulnerabilityAlerts": {
        "nodes": []
      }
    }
  }
}

おわりに

GitHub GraphQL APIでのVulnerability Alert(Dependabot alert)の取得を試してみました。

今回方法が分かったので、「Open中のVulnerability Alertが1件以上あればWorkflow実行をFailさせる」なんていう処理をCI/CD上で作ることもできそうです。

参考

以上