go-cve-dictionaryのNVD API対応を確認する。

# go-cve-dictionaryとは？
* 脆弱性スキャナvulsの[サブプロジェクト](https://github.com/vulsio/go-cve-dictionary)
* NVD、JVNなど公開脆弱性データのローカルDBを構築する
* 脆弱性情報はcve、cpe識別子によりクエリーが可能となる

# NVD APIへの対応が必要な背景
* 公開脆弱性データベースNVDは、APIとデータフィードによるNVDデータフェッチを提供していたが、2023年後期にデータフィードを停止すると発表した。
* go-cve-dictionaryはデータフィードによりNVDデータをフェッチする仕様のため、APIによるフェッチに仕様変更する必要がある

    * [NISTのアナウンス](https://nvd.nist.gov/general/news/changes-to-feeds-and-apis)
    ```
    Future Changes to the API and Data Feeds
    To better serve its growing user base the NVD is modernizing 
    its support for web-based automation. In late 2023, the NVD 
    will retire its data feeds while working to guide any legacy 
    users to updated application-programming interfaces (APIs). 
    APIs have many benefits over data feeds and have been the 
    proven and preferred approach to web-based automation for 
    over a decade.
    ```
                
# go-cvd-dictionaryの対応
* API対応PR: [PR:348](https://github.com/vulsio/go-cve-dictionary/pull/348)
    * コメントにあるように、go-cve-dictionaryからNVD APIにアクセスしているのではなく、NVD APIからの取得データが保存されているvulsioのリポジトリから取得しているとのこと
        
        ```
        Since we are not fetching directly from the NVD API, an API KEY is 
        not required. This time, the results of the NVD API are saved in this 
        repository(https://github.com/vulsio/vuls-data-raw-nvd-api-cve), and 
        go-cve-dictionary uses that repository.
        ```
* リポジトリ変更PR: [PR:418](https://github.com/vulsio/go-cve-dictionary/pull/418)
    * 上記nvdデータリポジトリをghcrコンテナに変更
    * go-cvd-dictionaryから直接APIアクセスしない仕様には変更なし

# 実際の動作を確認する
1. docker-hubからオフィシャルのイメージを検索
    ```
    tetsuohino@Mac docker % docker search go-cve-dictionary
    NAME                                       DESCRIPTION                                     STARS     OFFICIAL
    vuls/go-cve-dictionary                     Official image of go-cve-dictionary.            3         
    oppara/go-cve-dictionary                                                                   0         
    slazzaris/go-cve-dictionary                                                                0         
    ・・・
    ```

2. vuls/go-cve-dictionaryをpull
    ```
    tetsuohino@Mac docker % docker image pull vuls/go-cve-dictionary
    Using default tag: latest
    latest: Pulling from vuls/go-cve-dictionary
    4f4fb700ef54: Pull complete 
    b4aaf4380938: Pull complete 
    222d79399f71: Pull complete 
    6e771e15690e: Pull complete 
    Digest: sha256:40ca3ec96ac5164b4724fd50075f51c66edb4cb804da76ea1c6280b1ecc87286
    Status: Downloaded newer image for vuls/go-cve-dictionary:latest
    docker.io/vuls/go-cve-dictionary:latest
    tetsuohino@Mac docker %     
    ```

    ```
    tetsuohino@Mac go-cve-dictionary % docker images
    REPOSITORY                 TAG       IMAGE ID       CREATED         SIZE
    vuls/go-cve-dictionary     latest    40ca3ec96ac5   39 hours ago    87.2MB
    ```

## versionを確認
    ```
    tetsuohino@Mac go-cve-dictionary % docker run --rm vuls/go-cve-dictionary version
    go-cve-dictionary  d557c12
    ```

## nvd fetchの実行
    ```
    tetsuohino@Mac go-cve-dictionary % docker run --rm \
    -v /Users/tetsuohino/Develop/workspace/docker/go-cve-dictionary/storage:/vuls \
    vuls/go-cve-dictionary \
    fetch nvd 2025 --dbpath=/vuls/cve.sqlite3

    t=2025-06-16T07:46:43+0000 lvl=info msg="Inserting NVD into DB (sqlite3)."
    t=2025-06-16T07:46:43+0000 lvl=info msg="Deleting NVD tables..."
    t=2025-06-16T07:46:43+0000 lvl=info msg="Fetching CVE information from NVD."
    t=2025-06-16T07:49:38+0000 lvl=info msg="Fetching CVE information from NVD(2025)."
    t=2025-06-16T07:49:38+0000 lvl=info msg="Inserting fetched CVEs(2025)..."
    1125 / 15193 [----->___________________________________________________________________] 7.40% ? p/s1957 / 15193 [--------->______________________________________________________________] 12.88% ? p/s2377 / 15193 [----------->____________________________________________________________] 15.65% ? p/s3084 / 15193 [-------------->______________________________________________________] 20.30% 3265 p/s4407 / 15193 [-------------------->________________________________________________] 29.01% 3265 p/s5280 / 15193 [----------------------->_____________________________________________] 34.75% 3265 p/s6446 / 15193 [----------------------------->_______________________________________] 42.43% 3416 p/s7666 / 15193 [---------------------------------->__________________________________] 50.46% 3416 p/s8520 / 15193 [-------------------------------------->______________________________] 56.08% 3416 p/s9859 / 15193 [-------------------------------------------->________________________] 64.89% 3563 p/s10951 / 15193 [------------------------------------------------->__________________] 72.08% 3563 p/s12033 / 15193 [----------------------------------------------------->______________] 79.20% 3563 p/s13108 / 15193 [---------------------------------------------------------->_________] 86.28% 3682 p/s14291 / 15193 [--------------------------------------------------------------->____] 94.06% 3682 p/s15193 / 15193 [-------------------------------------------------------------------] 100.00% 5446 p/st=2025-06-16T07:49:41+0000 lvl=info msg="Refreshed 15193 CVEs."
    t=2025-06-16T07:49:43+0000 lvl=info msg="Finished fetching NVD."
    ```

## nvdデータの確認
### サーバを起動し、HTTPアクセスでデータを確認する。(NG)
1. サーバ起動
    ```
    tetsuohino@Mac go-cve-dictionary % docker run --rm \
    -v /Users/tetsuohino/Develop/workspace/docker/go-cve-dictionary/storage:/vuls \
    -p 1323:1323 \
    vuls/go-cve-dictionary \
    server --dbpath=/vuls/cve.sqlite3
     
    t=2025-06-17T03:23:57+0000 lvl=info msg="Starting HTTP Server..."
    t=2025-06-17T03:23:57+0000 lvl=info msg="Listening on 127.0.0.1:1323"

    ____    __
    / __/___/ /  ___
    / _// __/ _ \/ _ \
    /___/\__/_//_/\___/ v4.13.3
    High performance, minimalist Go web framework
    https://echo.labstack.com
    ____________________________________O/_______
                                        O\
    ⇨ http server started on 127.0.0.1:1323
    ```
2. localhost:1323にアクセス
    * 全てのアクセスポイントが"Not Found"を応答
    * サーバモードの利用は想定されなくなった？
    ```
    {"time":"2025-06-17T03:49:40.992327925Z",
    "id":"","remote_ip":"192.168.65.1",
    "host":"127.0.0.1:1323",
    "method":"GET",
    "uri":"/",
    "user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36",
    "status":404,
    "error":"code=404, 
    message=Not Found",
    "latency":43250,
    "latency_human":"43.25µs",
    "bytes_in":0,
    "bytes_out":24}
    ```
### コンテナにアタッチし、sqllite3を実行して直接DBを確認する
* 15193件のcveを確認

```
tetsuohino@Mac go-cve-dictionary % docker run --rm -it \
-v /Users/tetsuohino/Develop/workspace/docker/go-cve-dictionary/storage:/vuls \
alpine sh

/ # sqlite3 /vuls/cve.sqlite3
sh: sqlite3: not found
/ # apk add sqlite
fetch https://dl-cdn.alpinelinux.org/alpine/v3.22/main/aarch64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.22/community/aarch64/APKINDEX.tar.gz
(1/4) Installing ncurses-terminfo-base (6.5_p20250503-r0)
(2/4) Installing libncursesw (6.5_p20250503-r0)
(3/4) Installing readline (8.2.13-r1)
(4/4) Installing sqlite (3.49.2-r0)
Executing busybox-1.37.0-r18.trigger
OK: 10 MiB in 20 packages
/ # sqlite3 /vuls/cve.sqlite3
SQLite version 3.49.2 2025-05-07 10:39:52
Enter ".help" for usage hints.
sqlite> 
sqlite> select count(*) from nvds;
15193
sqlite>                                 
```
* nvdsテーブルスキーマに変更あり？
    * description, summary相当カラムが無い
    
    ```
    sqlite> .schema nvds
    CREATE TABLE `nvds` (`id` integer PRIMARY KEY AUTOINCREMENT,`cve_id` varchar(255),`published_date` datetime,`last_modified_date` datetime);
    CREATE INDEX `idx_nvds_cveid` ON `nvds`(`cve_id`);
    ```

# まとめ・考察
* go-cve-dictionaryはNVD APIに直接アクセスするのではなく、専用リポジトリにキャッシュされたNVDデータからNVDデータを取得している
* 上記、キャッシュの更新頻度などは不明。いづれにせよ、直接NVDにAPIアクセスできる仕様でなければ即時性は得られない
* nvdアクセス以外にも、いくつか問題が。これはDockerHub版固有の問題かも？
    * serverモードで、全てのアクセスポイントがNot Found (404)を応答
    * nvdsテーブルスキーマに変更あり
        * 脆弱性ローカルデータベースとして参照していたアプリケーションにとっては破壊的変更