
VEX 문서를 수집하고 VEX Hub 업데이트
vexhub-crawler는 소스 저장소에서 VEX 문서를 자동으로 검색하는 VEX Hub의 구성 요소입니다.
크롤러는 등록된 PURL(Package URL)에서 소스 저장소를 식별하고 VEX 문서를 VEX Hub로 복사합니다. 이 프로세스를 통해 VEX Hub는 다양한 소프트웨어 패키지에 대한 최신 VEX 문서 컬렉션을 유지할 수 있습니다.
다음 다이어그램은 npm을 예로 들어 VEX Hub 크롤러의 높은 수준의 프로세스 흐름을 보여줍니다:
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 크롤러는 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 목록은 Pull Request를 통해 누구나 업데이트할 수 있습니다. 오픈소스 프로젝트의 소스 저장소에 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.xml.maven-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 문서는 pkg:npm/malicious의 제품 ID를 가져야 합니다. pkg:npm/[email protected]과 같은 다른 제품 ID를 가진 VEX 문서는 무시됩니다.
이 접근 방식은 관련성이 있고 신뢰할 수 있는 VEX 문서만 VEX Hub에 포함되도록 보장합니다.
현재 VEX Hub 크롤러는 패키지 소스 저장소를 식별하기 위해 레지스트리 API를 사용합니다. 그러나 이 접근 방식은 저장소 정보를 패키지 유지 관리자가 자유롭게 설정할 수 있어 변조에 취약하므로 잠재적인 보안 위험이 있습니다.
이 문제를 해결하기 위해 향후에는 출처 증명(provenance attestation)을 사용하여 더 안정적인 소스 저장소 확인을 고려하고 있습니다. 출처 증명을 사용하면 패키지가 빌드된 실제 저장소 URL을 신뢰할 수 있는 방식으로 얻을 수 있으며, 패키지의 소스 코드와 게시된 아티팩트 간의 관계를 암호학적으로 검증할 수 있습니다.
특히 npm은 이미 레지스트리에 출처 증명을 구현했습니다. 이 구현을 통해 출처 데이터를 사용하여 PURL에서 직접 소스 저장소 정보를 검색할 수 있습니다. 이 접근 방식이 패키지의 소스 저장소 확인 프로세스의 신뢰성을 향상시킬 수 있다고 믿습니다.