Skip to content

fix: Chart.js を本体同梱の 4.x に切り替え、CSV に数式インジェクションガードを適用 (#91, #92) - #93

Open
ttokoro20240902 wants to merge 3 commits into
4.4from
fix/issue-91-92
Open

fix: Chart.js を本体同梱の 4.x に切り替え、CSV に数式インジェクションガードを適用 (#91, #92)#93
ttokoro20240902 wants to merge 3 commits into
4.4from
fix/issue-91-92

Conversation

@ttokoro20240902

Copy link
Copy Markdown

#90 のレビューで「本 PR の対応は不要」とされた 2 件に対応します。コミットを分けています。

⚠️ ベースブランチについて

本 PR は 4.4 ではなく #90 のブランチ feat-4.4 をベースにしています。

origin/4.4 はまだ SalesReport42composer.json の version は 4.3.0)で、SalesReport44 へのリネームは #90 が持ち込むものです。4.4 を直接ベースにすると旧コード名に対する変更になり #90 とコンフリクトするため、#90 の上に積んでいます。#90 のマージ後にレビュー・マージをお願いします#90 がマージされればベースは自動で 4.4 に切り替わります)。

Closes #91 — Chart.js

本体 4.4 は package.jsonchart.js: ^4.5.1 を同梱し、admin.bundle.js として default_frame.twig から全管理画面に読み込んでいます。そのため CDN の script タグは不要で、Chart はグローバルに存在します。

  • index.twig: cdnjs の script タグを削除
  • term / product / age.twig: Chart.js 4.x の API へ移行
    • tooltipsplugins.tooltiptitleplugins.titlelegendplugins.legend
    • tooltip の label コールバックを (tooltipItem, data) から (context) へ変更し context.parsed.y / context.label を使う
    • scales.yAxes[]scales.yscales.xAxes[]scales.x
    • beginAtZero / suggestedMinticks 配下から scales.y 直下へ移動
    • categoryPercentage は Chart.js 3 以降データセットのオプションなのでデータセットへ移動

実機確認(EC-CUBE 4.4 / PHP 8.2 / SQLite、Chart.js 4.5.1)

ブラウザで 3 画面を開き、生成された Chart インスタンスを直接検証しました。

検証項目 結果
Chart グローバルの供給元とバージョン admin.bundle.js 由来、Chart.version = 4.5.1
期間別(日別) type: line、365 点、canvas 描画あり
期間別(曜日別) type: bar、ラベル SunSat
商品別 type: bar、タイトル「商品別集計 上位20件」表示、凡例非表示、x 軸 90 度回転、categoryPercentage = 0.3 がデータセットに適用
年代別 type: bar、凡例非表示、categoryPercentage = 0.3
y 軸目盛のフォーマット 12345671,234,567
ツールチップ 購入合計: ¥9,876 / 商品A : ¥4,200
旧 API の残存 options.scalesxAxes / yAxes なし
cdnjs へのリクエスト ✅ 0 件
JS コンソールエラー / 警告 ✅ 0 件
PHPUnit ✅ 35 tests 54 assertions 成功

Closes #92 — CSV の数式インジェクションガード

本体の CsvExportService と同じく Eccube\Util\CsvFormulaGuard を使い、店舗設定 BaseInfo::isOptionSanitizeCsvFormulas() の ON/OFF を尊重して 3 つの CSV のデータ行を無害化します。

CsvFormulaGuard::escape()int|string|null を受けるため、round() が返す float 等を渡さないよう文字列のみを対象にしています(非文字列は escape() でもそのまま返るため挙動は変わりません)。

⚠️ 必要な本体バージョンと、ローカル検証ができていない点

CsvFormulaGuardBaseInfo::isOptionSanitizeCsvFormulas() は本体 4.4 ブランチに 2026-06-18 に追加されたもので、それ以前の 4.4 スナップショットには存在しません。本 PR はこれらを前提としています。

ローカルの docker 開発環境が使う ghcr.io/ec-cube/ec-cube-php:8.2-apache-4.4(本体 VERSION = 4.3.1-p1 相当)はこの API を含まないため、当該イメージでは以下が発生します

  • CSV 出力が Class not found で 500 になる
  • PHPUnit の CSV 出力テストが 1 件エラーになる
  • phpstan が 2 件報告する(BaseInfo::isOptionSanitizeCsvFormulas()method.notFoundCsvFormulaGuardclass.notFound

いずれも本体スナップショットが古いことによるもので、#92 の実装そのものはローカルでは検証できていません。CI は ref: '4.4' を checkout し CsvFormulaGuard を含むため、CI の結果を正としています。docker イメージの更新は別途対応が必要です。

この前提(未リリースの 4.4 の API に依存する)が受け入れられない場合は、class_exists() による互換ガードを入れる形にも変更できます。ご指示ください。

ttokoro20240902 and others added 2 commits August 4, 2026 14:36
管理画面のグラフが cdnjs から Chart.js 2.3.0 を読み込んでいたため、
外部 CDN 依存とバージョンの二重管理が残っていた。本体 4.4 は
package.json で chart.js ^4.5.1 を同梱し、admin.bundle.js として
default_frame.twig から全管理画面に読み込んでいるため、これを使う。

- index.twig: cdnjs の script タグを削除(Chart はグローバルに存在する)
- term / product / age.twig: Chart.js 4.x の API へ移行
  - tooltips -> plugins.tooltip、title -> plugins.title、legend -> plugins.legend
  - tooltip の label コールバックを (tooltipItem, data) から (context) へ変更し
    context.parsed.y / context.label を使う
  - scales.yAxes[] -> scales.y、scales.xAxes[] -> scales.x
  - beginAtZero / suggestedMin を ticks 配下から scales.y 直下へ移動
  - categoryPercentage は 3 以降データセットのオプションなので dataSet へ移動

実機確認(EC-CUBE 4.4 / PHP 8.2 / SQLite、Chart.js 4.5.1):

- 期間別(日別=line / 曜日別=bar)、商品別、年代別の 3 画面でグラフが描画され、
  canvas が空でないことを確認
- y 軸目盛のフォーマット(1234567 -> "1,234,567")と
  ツールチップ("購入合計: ¥9,876" / "商品A : ¥4,200")が動作
- options.scales に旧 xAxes/yAxes が残っていないこと、
  商品別の categoryPercentage がデータセットに適用されていることを確認
- cdnjs へのリクエストが発生しないこと、JS コンソールエラー 0 件を確認
- PHPUnit 35 tests 54 assertions 成功

Closes #91

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CSV 出力は fputcsv() を直接呼んでおり本体の CsvExportService を経由しないため、
店舗設定を ON にしても数式インジェクション対策が効いていなかった。

本体の CsvExportService と同じく Eccube\Util\CsvFormulaGuard を使い、
店舗設定 BaseInfo::isOptionSanitizeCsvFormulas() の ON/OFF を尊重して
期間別/商品別/年代別の 3 つの CSV のデータ行を無害化する。

CsvFormulaGuard::escape() は int|string|null を受けるため、round() が返す
float 等を渡さないよう文字列のみを対象にしている(非文字列は escape() でも
そのまま返るため挙動は変わらない)。

## 必要な本体バージョン

CsvFormulaGuard と BaseInfo::isOptionSanitizeCsvFormulas() は本体 4.4 ブランチに
2026-06-18 に追加されたもので、それ以前の 4.4 スナップショットには存在しない。
本コミットはこれらを前提とする。

ローカルの docker 開発環境(ghcr.io/ec-cube/ec-cube-php:8.2-apache-4.4、
本体 VERSION = 4.3.1-p1 相当)はこの API を含まないため、当該イメージでは

- CSV 出力が Class not found で 500 になる
- PHPUnit の CSV 出力テストが 1 件エラーになる
- phpstan が 2 件(method.notFound / class.notFound)を報告する

いずれも本体スナップショットが古いことによるもので、CI(ref: '4.4' を
checkout するため CsvFormulaGuard を含む)での検証結果を正とする。
docker イメージの更新は別途対応する。

Closes #92

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 871f92a4-ef5a-4736-b0d1-5948e95e3f4a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

CI の static-analysis で rector が下記の変更を提案して失敗していたため追従した。

    -        private BaseInfoRepository $baseInfoRepository,
    +        private readonly BaseInfoRepository $baseInfoRepository,

ローカルで rector --dry-run が変更なしになること、php-cs-fixer が差分なしに
なることを確認した。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ttokoro20240902
ttokoro20240902 changed the base branch from feat-4.4 to 4.4 August 7, 2026 07:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant