Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

VP JWT format and verification inconsistencies

オープン
#4,197 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
35/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
静か
技術スタック
go
領域
api, backend, security

調査の方向性

vcr/holder/presenter.go:buildJWTPresentation から始め、その claims を auth/api/iam/validation.go:validatePresentationAudience と比較します。次に、discovery/module.go、vcr/api/vcr/v2/api.go、discovery/client.go、auth/api/iam/openid4vp.go における VP の受け入れを追跡します。古いノードとの相互運用性を損なうことなく、段階的な検証の動作が一貫していれば完了です。

索引モデルが issue の本文から書いたものです。

説明

While working on #4191 (JWTProfile refactor) we surfaced a number of inconsistencies in how Verifiable Presentations are constructed and verified in this codebase. None are immediate vulnerabilities, but together they make it hard to reason about VP security and complicate consistent verification.

Findings

1. iss is not set on VP JWTs (spec deviation)

vcr/holder/presenter.go:buildJWTPresentation puts the holder DID in the sub claim and omits iss. Per W3C VC Data Model 1.1 §6.3.1, for a JWT VP iss MUST be the holder; sub is not specified.

Consequence: the signer identity has to be derived from the kid header, which means the standard iss-to-kid binding check we use for VCs (in crypto.IssuerKidValidator) cannot be applied to VPs.

2. aud is not consistently required on verification

VP builders set aud:

  • discovery: from service.ID (via Domain)
  • OpenID4VP: from ClientIDParam (via Audience)

But aud is only checked in the v2 OpenID4VP flow (validatePresentationAudience in auth/api/iam/validation.go). VerifyVP itself doesn't check it, so callers like discovery/module.go:269 and vcr/api/vcr/v2/api.go accept VPs regardless of audience. A VP intended for verifier A could be replayed against verifier B.

3. exp is not consistently required on verification

After #4191 the VP builder always sets exp (default 15 min), but the verifier still doesn't require it because other nodes may produce VPs without one. Caller-side max-age checks are inconsistent:

Caller Behavior when `exp` missing
`validateS2SPresentationMaxValidity` (s2s OpenID4VP) rejects ("missing creation or expiration date")
`discovery/module.go:247` silently passes (`time.Until(zeroTime)` is hugely negative)
`vcr/api/vcr/v2/api.go` (external API) no check
`discovery/client.go:372` no check
`auth/api/iam/openid4vp.go:539` no check
4. typ is "JWT" instead of "vp+jwt"

W3C VC Data Model 2.0 specifies typ: "vp+jwt" to prevent JWT type confusion. This was the root cause of GHSA-9hmg-827w-9rhj (VP replayed as access token). The fix for that advisory addressed the verifier side; updating the VP builder is out of scope for safety reasons (rolling-upgrade compatibility), but should be considered in a coordinated network upgrade.

Suggested actions

A consolidated fix would involve:

  1. Update buildJWTPresentation to set iss (in addition to sub, for backward compat) and typ: "vp+jwt".
  2. Fix discovery/module.go to properly reject VPs with missing exp (or use nbf + maxValidity as a fallback).
  3. Add audience checks to all VP-accepting endpoints, not just validatePresentationAudience.
  4. Once the network has been upgraded, tighten the vpJWTProfile to require exp, validate iss-to-kid binding, and reject typ != "vp+jwt".

Each step needs to be staged carefully to avoid breaking interop with older nodes.

主要言語
Go
スター
29
フォーク
24
平均マージ
2日 18時間
マージ済み PR(30日)
45

環境構築

  • Dockerfile または Docker Compose ファイルあり
  • プルリクエストのテンプレートなし
  • コントリビューションガイドなし

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

nuts-foundation/nuts-node のほかの issue

nuts-foundation/nuts-node の issue をすべて見る

似ている issue

Go の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。