# SBOM — AX HUB MCP Server - 산출물: `AXHUB_MCP_Server_SBOM_CycloneDX1.5.json` (CycloneDX 1.5 정본), `AXHUB_MCP_Server_SBOM_CycloneDX1.5.xlsx` (검토용) - 대상: `ax-hub-mcp-server@0.1.0` (Java 21 / Spring Boot 3.5.11) - 생성 기준일: 2026-08-18 ## 대상 범위 `build.gradle`이 직접 선언한 오픈소스는 `io.modelcontextprotocol.sdk:mcp-json-jackson2:2.0.0` 하나이며, 이 SBOM은 그 **런타임 전이 의존 전체**와 **빌드 환경**을 담는다. Spring Boot starter 계열(web / validation / data-redis / actuator)은 glow f/w가 제공하는 플랫폼 구성이라 범위 밖이다. | 구분 | 개수 | 내용 | |---|---|---| | 런타임 의존성 (scope: required) | 12 | 실행 산출물 classpath에 올라가는 라이브러리 | | 빌드 환경 (scope: optional) | 2 | JDK 21, Gradle 8.14.3 | | 합계 | 14 | | 라이선스는 Apache-2.0 9건, MIT 3건, MIT-0 1건, 미확정 1건(JDK)이다. copyleft는 0건이라 소스 공개 의무가 없다. JDK는 toolchain이 `languageVersion = 21`만 고정하고 벤더를 지정하지 않으므로, 실제 배포판이 정해지면 라이선스를 확정해 기재한다. ## 빌드 환경(scope: optional)과 제외 devDependencies의 차이 둘은 다르다. 혼동하지 않도록 구분해 둔다. - **빌드 환경 (scope: optional)** — BOM에 **수록한다**. JDK 21, Gradle 8.14.3처럼 빌드에 필요하지만 실행 산출물에는 들어가지 않는 것들이다. - **제외 devDependencies** — BOM에 **수록하지 않는다**. Java에서는 `test` scope와 `annotationProcessor`가 여기 해당한다. 선언 4건이다. - `spring-boot-starter-test`, `com.squareup.okhttp3:mockwebserver:4.12.0`, `org.junit.platform:junit-platform-launcher` (test scope) - `org.springframework.boot:spring-boot-configuration-processor` (annotationProcessor) 나머지 제외 항목과 사유는 엑셀 `Exclusions` 시트에 있다. 핵심은 세 가지다. - `joni`, `graal-js`, `graal-sdk` — json-schema-validator의 `optional`. ECMA262 정규식 검증을 쓰지 않아 해석되지 않으므로 약 50MB가 빠진다. - `jakarta.servlet-api:6.1.0` — mcp-core의 `provided`. 산출물에 포함되지 않고 서블릿 컨테이너가 제공한다. - `mcp:2.0.0`(aggregate), `mcp-json-jackson3:2.0.0` — Jackson 3 경로를 쓰지 않아 선언하지 않는다. 자세한 배경은 [mcp-java-sdk-adoption.md](../mcp-java-sdk-adoption.md) 참고. ## 적용된 보안 통제 `com.networknt:json-schema-validator`는 schema의 `$ref`가 문서 밖을 가리키면 그 주소로 직접 조회를 시도한다. `inputSchema`는 Tool Service 매니페스트에서 오므로, 통제가 없으면 매니페스트가 서버의 outbound 호출 대상을 정하게 된다. `ToolSchemaReferencePolicy`가 `ToolMetadata` 생성 시점에 문서 밖 `$ref`·`$dynamicRef`와 2020-12가 아닌 `$schema`를 거부한다. 근거와 검토한 대안은 [ADR-0011](../decisions/ADR-0011-tool-input-schema-stays-in-document.md)에 있다. 정규식도 같은 자리에서 막는다. optional인 `joni`·`graal-js`를 해석하지 않아 `pattern` 검증이 JDK 정규식 엔진으로 처리되고 백트래킹 폭증이 가능하므로, `ToolSchemaPatternPolicy`가 반복 구조와 수량자 개수, 정규식 길이를 제한하고 `pattern` 필드에 `maxLength`(≤256) 동반 선언을 요구한다. key 길이를 묶을 자리가 없는 `patternProperties`는 사용을 금지한다. 규칙은 JDK 21 실측에 근거하며 근거와 한계는 [ADR-0012](../decisions/ADR-0012-tool-input-schema-pattern-budget.md)에 있다. 남은 위험은 문자 집합이 겹치면서 무한 수량자가 3개 이하인 정규식이다. 이 조합은 통과하며 `maxLength`가 256이면 수백 ms가 걸릴 수 있다. 두 통제는 위험을 없애지 않고 측정된 폭증 구간 밖으로 옮긴다. ## 산출 방법과 한계 버전과 해시는 `build.gradle` 선언에서 출발해 Gradle 로컬 캐시의 실제 `pom`을 따라가 그래프를 만들고, 캐시된 실제 jar 바이너리에서 SHA-512 / SHA-1을 직접 계산했다. Gradle 배포본의 SHA-256은 wrapper의 `distributionSha256Sum` 값을 그대로 옮겼다. `gradlew dependencies`로 해석 결과를 대조하려 했으나 sandbox에서 gradle daemon이 뜨지 않아 (`Unable to establish loopback connection`) 실행하지 못했다. 따라서 다음 버전 정렬은 pom과 Spring Boot BOM 판독에 근거한 것이며, 빌드 환경에서 한 번 확인해야 한다. ```bash ./gradlew dependencies --configuration runtimeClasspath ``` | 컴포넌트 | pom 요청 버전 | 수록 버전 | 근거 | |---|---|---|---| | jackson-databind | 2.20.1 (mcp-json-jackson2) | 2.19.4 | Spring Boot 3.5.11 → jackson-bom 2.19.4 | | jackson-databind | 2.18.3 (json-schema-validator) | 2.19.4 | 위와 동일 | | reactor-core | 3.7.0 (mcp-core) | 3.7.16 | Spring Boot 3.5.11 → reactor-bom 2024.0.15 | | slf4j-api | 2.0.16 (mcp-core) | 2.0.17 | Spring Boot 3.5.11 관리 버전 | 가장 확인이 필요한 항목은 jackson-databind다. SDK가 요청한 2.20.1이 `io.spring.dependency-management`에 의해 2.19.4로 내려가므로, initialize / tools/list / tools/call 직렬화 계약 테스트로 동작을 확인한다. CycloneDX 1.5 공식 JSON Schema 원본 대조는 폐쇄망이라 수행하지 않았다. 대신 생성 시점에 `dependencies`의 모든 `ref` / `dependsOn`이 실재하는 `bom-ref`를 가리키는지, 컴포넌트가 빠짐없이 `dependencies`에 등장하는지 구조 점검을 통과시켰다.