
VEX ドキュメントを収集し、VEX Hub を更新する
vexhub-crawler は、ソースリポジトリから VEX ドキュメントを自動的に取得する VEX Hub のコンポーネントです。
クローラーは、登録された PURLs (Package URLs) からソースリポジトリを特定し、VEX ドキュメントを VEX Hub にコピーします。 このプロセスにより、VEX Hub はさまざまなソフトウェアパッケージ向けの最新の VEX ドキュメントコレクションを維持できます。
次の図は、npm を例として、VEX Hub Crawler の高レベルのプロセスフローを示しています:
flowchart TD
Dev[Developer] -->|Register package| PL[Package List]
PL -->|Provide packages for crawling| Crawler
Crawler -->|Identify repository URL| Registry[Package Registry]
Crawler -->|Retrieve VEX documents| Src
Crawler -->|Validate and update VEX documents| Hub
subgraph crawler [VEX Hub Crawler]
Crawler
PL
end
subgraph bottom [ ]
direction LR
Registry
Src
Hub[VEX Hub]
subgraph Src[Source Repository]
direction TB
VEX[VEX documents<br>under .vex/ directory]
end
end
classDef dev fill:#b3d9ff,stroke:#2a4d69,stroke-width:1px,color:#2a4d69;
classDef vexHub fill:#ffd9e6,stroke:#4b3832,stroke-width:1px,color:#4b3832;
classDef crawler fill:#c2f0c2,stroke:#1e4d2b,stroke-width:1px,color:#1e4d2b;
classDef npmReg fill:#ffe6cc,stroke:#5e3023,stroke-width:1px,color:#5e3023;
classDef sourceRepo fill:#e6ccff,stroke:#3b2e58,stroke-width:1px,color:#3b2e58;
classDef pkgList fill:#ccf2ff,stroke:#1c4e5a,stroke-width:1px,color:#1c4e5a;
classDef invisible fill:none,stroke:none;
class Dev dev;
class Hub vexHub;
class crawler crawler;
class Registry npmReg;
class Src,VEX sourceRepo;
class PL pkgList;
class bottom invisible;VEX Hub Crawler は、VEX ドキュメントを発見するための PURL のリスト を管理しています。 PURL 定義ファイルの形式は次のとおりです:
pkg:
npm:
- namespace: "@angular"
name: animations
golang:
- name: github.com/aquasecurity/trivy
pypi:
- name: django
maven:
- namespace: org.junit.jupiter
name: junit-jupiter-api
oci:
- name: trivy
qualifiers:
- key: repository_url
value: index.docker.io/aquasec/trivy
- name: trivy
qualifiers:
- key: repository_url
value: ghcr.io/aquasecurity/trivy
PURL を指定する際には、以下のコンポーネントが必要です:
version は省略する必要があります。
namespace、qualifiers、subpath は、oci などの特定のエコシステムでは必要になる場合があります。
PURL の構成に関する詳細については、PURL 仕様書 を参照してください。
PURL のリスト は、プルリクエストを通じて誰でも更新できます。 オープンソースプロジェクトのソースリポジトリに VEX ドキュメントがすでに保存されている場合、プロジェクトのメンテナー以外の方も VEX Hub に PURL を登録できます。
現在、クローラーは以下のエコシステムをサポートしています:
ソースリポジトリを特定する方法は、エコシステムによって異なります:
npm レジストリ API を使用してソースリポジトリを解決します。 各パッケージには、リポジトリを定義する セクションがあります。
React の例では、次のようになります:
$ curl -s https://registry.npmjs.org/react | jq .repository.url
"git+https://github.com/facebook/react.git"
vexhub-crawler は、https://github.com/facebook/react に保存されている VEX ファイルを自動的に取得します。
go-import からリポジトリを特定するために HTTP アクセスが行われます。
curl -s "https://k8s.io/client-go?go-get=1"
<html><head>
<meta name="go-import"
content="k8s.io/client-go
git https://github.com/kubernetes/client-go">
<meta name="go-source"
content="k8s.io/client-go
https://github.com/kubernetes/client-go
https://github.com/kubernetes/client-go/tree/master{/dir}
https://github.com/kubernetes/client-go/blob/master{/dir}/{file}#L{line}">
</head></html>
リポジトリを解決するために PyPI API が使用されます。
curl -s https://pypi.org/pypi/<package-name>/json | jq .info.project_urls.Source
リポジトリを解決するために crates.io API が使用されます。
curl -s https://crates.io/api/v1/crates/<crate-name> | jq .crate.repository
Maven パッケージの場合、ソースリポジトリを特定するために以下の手順を実行します:
repository_url を取得します。デフォルトの URL は https://repo.maven.apache.org/maven2 です。maven-metadata.xml ファイルの URL を構築します。たとえば、com.fasterxml.jackson.core:jackson-databind の場合、URL は次のようになります:https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-core/maven-metadata.xmlmaven-metadata.xml から最新バージョンを抽出します。scm.url または url フィールドを調べてソースリポジトリを特定します。OCI イメージの場合、ソースリポジトリは latest タグの org.opencontainers.image.source ラベルまたはアノテーションを調べることで特定されます。
このメタデータは通常、イメージのビルドプロセス中に設定され、ソースコードリポジトリを参照するための標準化された方法を提供します。
プロセスは次のとおりです:
repository_url と :latest タグを追加して完全なイメージ参照を構築します。latest タグのイメージマニフェストと設定を取得します。org.opencontainers.image.source キーを探します:
Labels フィールドannotations フィールドcrane を使用してソース URL を取得する例:
$ crane config ghcr.io/aquasecurity/trivy:latest | jq -r '.config.Labels["org.opencontainers.image.source"]'
https://github.com/aquasecurity/trivy
ソースリポジトリが特定されると(現在は git リポジトリのみがサポートされています)、vexhub-crawler はリポジトリのルートにある .vex/ ディレクトリ内で VEX ドキュメントを検索します。
クローラーは、以下のパターンに一致するファイルを VEX ドキュメントと見なします:
クローラーは以下の検証を実行します:
クローラーは、発見したファイルを元のファイル名で VEX Hub にコピーします。 VEX Hub のディレクトリ構造は、Package URL (PURL) に基づいて作成され、バージョン、qualifiers、subpath は除外されます。
クローラーは、ソースリポジトリに保存されている VEX ドキュメントに基づく信頼モデルを採用しています。 検証のセクションで述べたように、元の PURL とは異なる製品を宣言する VEX ドキュメントを除外します。
たとえば、PURL pkg:npm/malicious が VEX Hub に登録され、ソースリポジトリ github.com/org/malicious に解決される場合、そこに保存されている VEX ドキュメントはすべて製品 ID が pkg:npm/malicious でなければなりません。
pkg:npm/[email protected] など、異なる製品 ID を持つ VEX ドキュメントは無視されます。
このアプローチにより、関連性があり信頼できる VEX ドキュメントのみが VEX Hub に含まれることが保証されます。
現在、VEX Hub Crawler はパッケージのソースリポジトリを特定するためにレジストリ API を使用しています。 しかし、このアプローチは、リポジトリ情報がパッケージメンテナーによって自由に設定できるため、改ざんされやすいという潜在的なセキュリティリスクがあります。
この課題に対処するため、将来的にはより信頼性の高いソースリポジトリの解決に provenance attestation(来歴証明)の使用を検討しています。 Provenance attestation により、パッケージがビルドされた実際のリポジトリ URL を信頼できる方法で取得でき、パッケージのソースコードと公開された成果物との関係を暗号的に検証できます。
特に、npm はすでにレジストリに provenance を実装しています。 この実装により、provenance データを使用して PURL から直接ソースリポジトリ情報を取得できます。 このアプローチにより、パッケージのソースリポジトリ解決プロセスの信頼性を高めることができると考えています。