v0.6.22 — 前の版で直したつもりの欠陥が、2 か所残っていました
v0.6.22 — 前の版で直したつもりの欠陥が、2 か所残っていました
⚠ 先に読むところ
1. 同じ根が 3 か所ありました。前の版で直したのは 1 か所です
v0.6.21 で「oneOf の枝が $ref のとき参照先の変更が見えない」を直しました。
外部監査が、同じ根の反例を 2 件返してきました。
原因は 1 つです。判定器は「節の文字列が変わっていない」を
「意味が変わっていない」の証拠にしていました。$ref は参照先を指すだけなので、
指す先が変われば、文字列は同じまま意味が変わります。
その置き方が 3 か所ありました。
| 場所 | 直した版 | 見つけた人 |
|---|---|---|
oneOf の枝の比較 |
v0.6.21 | こちらの property-based 試験 |
| 同上・枝に sibling がある形 | この版 | 外部監査 |
allowlist ゲート(未対応 keyword が $ref を包む) |
この版 | 外部監査 |
anyOf / allOf の早期 continue |
この版 | こちら |
3 つ目は監査の指摘にありません。直す前に
「文字列の一致を意味の一致と置いた箇所」を数え直したときに出ました。
1 件目だけ直して終わりにすると、次の監査で同じものが返ってきます。
2. どちらも危険側です。受け手が拒む向きの誤りです
反例1 oneOf の枝が { $ref: '#/definitions/d0', description: 'branch' }
旧 d0.type = 'string' → 新 d0.type = ['string','null']
反例2 definitions.outer = { not: { $ref: '#/definitions/inner' } } ← 新旧まったく同じ
旧 inner.type = ['string','null'] → 新 inner.type = 'string'
どちらも ajv {"x":null} が旧 invalid → 新 valid = **言語が広がっている**
判定 HOLD(据え置き可) ← **上げるべきなのに上げない**
反例 2 は not の中が狭まると外は広がる形です。
**受け手への影響。**版が据え置かれると、受け手は旧 schema を pin したままになります。
新しい版が null を出した瞬間、受け手の検証が落ちます。
現行 schema への影響はありません。$ref + sibling は現行 schema に 3 件
(evidenceGrade が 3 版すべてでこの形)ありますが、いずれも properties の位置で、
そこは前から正しく判定していました。
実 schema 194 対(現行 25 schema × 直近 8 tag)で判定は 1 件も変わっていません。
3. 回帰テストを先に入れてから直しました
v0.5.1 / v0.5.2 / v0.6.21 と同じ順序です。
① 回帰テストを入れる(条文 ①-c4 / ①-c5) → 2 件とも落ちることを実測
② 判定器を直す
③ 通ることを確認
④ 直した 3 か所を 1 つずつ戻す → A 落ちる / B 落ちる / **C 落ちない**
⑤ C 用のテスト(①-c6)を足す → C も落ちるようになった
④ で 1 か所が「外しても落ちない行」になっていました。
anyOf/allOf の経路に実害のある反例が在ることを ajv で確かめてから、
テストを足しています。変異で落ちない修正は、入れた証拠がありません。
4. 前の版の試験が見逃した理由は 2 つで、どちらも「0 件」でした
v0.6.21 の notes に、こう書きました。
値は schema 対から作りますが、作れない値があれば広がりを見逃します。
そこがそのまま当たりました。
v0.6.21 v0.6.22
枝・property 位置の $ref + sibling 0 件 20 件 ← 形を作れていなかった
候補値のうち「property が null」 0 件 85 件 ← 証人を作れていなかった
監査の反例 2 件は、どちらも証人が {"x": null} です。
当時の生成器は 300 種を作ってその形を 1 件も含めず、
証人合成は 6,219 候補を作って**「1 つの key だけが null」を 1 件も作りません**でした。
どちらか片方でも 0 なら、判定器を直しても試験は自力で見つけられません。
補強したうえで v0.6.21 の判定器に対して回すと、自力で反例を出しました
(seed 266・枝が {$ref, description}・参照先の type が広がった形)。
手書きの反例を抜いた状態での実測です。
5. schemaId を名乗りながら、その schema を配っていませんでした
release-stage-attestation.v1.json(最終関門の記録)は前から
schemaId: trs-jack-3d-release-stage-attestation.v1 と名乗っていましたが、
**対応する schema を配っていませんでした。**受け手は名乗っている形を検証できません。
記録の中身は正しいものでした。欠けていたのは確かめる手段です。
検査していたのは stageRelease.mjs の文字列だけで
(「exitCode: と書いてあるか」)、生成された実物は見ていませんでした。
この版で schemas/release-stage-attestation.v1.schema.json を配ります。
release:stage は記録を書く前に実 object を検証し、
合わなければ記録も SHA256SUMS も出さずに止まります
(書いてから検証すると、落ちたときに「途中まで正しく見える記録」が残ります)。
testEvidenceCrossBound を必須欄へ入れました——それまで必須一覧にありませんでした。
6. tag の中の SECURITY.md が、恒久的に 1 版古くなっていました
v0.6.18 の tag → 「現時点では v0.6.17」
v0.6.19 の tag → 「現時点では v0.6.18」
v0.6.20 の tag → 「現時点では v0.6.19」
v0.6.21 の tag → 「現時点では v0.6.20」 4/4 tag で実測
**工程上どうやっても直りません。**release を作る commit の時点では、
その版はまだ公開されていないので、書ける最新は 1 つ前です。
検査は手元の控えの最大版数でこの行を縛っていたので main では常に正しく、
だからこそ誰も気づきませんでした。受け手が読むのは tag の中身です。
版数を書かず「GitHub Releases で Latest と表示されている 1 本」を指す形へ変え、
版数を書き足したら止まる検査を入れました。
版数を上げていない根拠(すべて実測)
toolVersion 20 / CLI 結果契約 schemaVersion 2 / profile schemaVersion 3 のままです。
判定器は配布物か **違う**(releaseAssets に 0 回)
配る検算ツール v0.6.20・v0.6.21 と **byte 一致**
実 schema での判定 **194 対中 0 件が変化**(現行 25 schema × 直近 8 tag)
CLI 出力の 10 経路 基準と byte 一致
profile のモデル数値 **0 件が変化**(葉 2267 / 3130 のうち、動いたのは由来 8 件だけ)
**それが今回直した欠陥です。**現行 schema にその形が無いので、
実 schema での判定が変わらなかっただけです。
配る asset は 27 件 → 28 件になりました(attestation の schema を足したため)。
足したのは schema だけで、記録そのものは索引の外のままです(自己参照を避けるため)。
依存の advisory(踏む経路つき)
npm audit が high を 1 件出します。踏む経路は無いと測りました。
nanoid 3.3.16 (<3.3.18) GHSA-2v37-7h3g-55p8
経路 vite → postcss → nanoid(推移依存)
区分 **dev のみ**(npm ls nanoid --omit=dev が空。対照として three は解決する)
出荷物 **入っていない**(dist/assets/*.js に nanoid が 0 件。対照として three は 1 件)
**まだ上げていません。**詳しくは SECURITY.md に書きました。
まだやっていないこと
- **実測が 1 件も来ていません。**接点位置は全部仮定のままで、
導通測定も音響測定もしていません(verifiedPhysicalはfalse)。 - property-based 試験が見ているのは 1 つの性質だけです
(「新だけが通す値が実在するなら BUMP」)。今回その限界がそのまま当たりました。
補強しましたが、次に見逃す形も、いまは 0 件に見えます。 - BusyBox を oracle に足すこと(開発機にも CI にもありません)。
- annotated tag への署名(v0.6.22 も署名なしです)。
- 公開済み asset の定期確認(
npm run check:published-assetsは在りますが、
定期実行にはしていません)。
数えたもの
| v0.6.21 | v0.6.22 | |
|---|---|---|
| 単体テスト | 1410 | 1433(skip 0 / 失敗 0) |
| 配る asset | 27 | 28(attestation の schema) |
| schema | 25 | 26 |
| 検算ツール | toolVersion 20 |
変わらず 20 |
| CLI 結果契約 | schemaVersion 2 |
変わらず 2 |
| 止め方の名前(catalog) | 82 種類 | 変わらず 82 |
| 出力の基準(経路) | 10 | 変わらず 10(全件 byte 一致) |
検証対象(validate:profiles) |
14 | 14 |
| 記録された入力 | 32 | 32 |
| 区間 / event | TRS 23/32・TRRS 30/36 | 変わらず |
変わっていないもの
- **モデルの数値。**接点位置も走査結果も同じです。
verifiedPhysicalはfalse。実測記録は依然 0 件です。- IV028 は 13.30–13.52 mm /
ASSUMPTION/ground-open-differential/
RETURN_OPEN_L_AND_R_ON_DISTINCT_CONDUCTORSのままです。 toolVersion20 / CLI 結果契約schemaVersion2 / profileschemaVersion3 / catalog 82 種類。- 止め方の名前の一覧・
archivePolicy・status・終了コードの意味。