RYX

Blog

Shopifyアプリ開発者がやるべきセキュリティ対策|偽の決済画面の攻撃から考える7つのこと【2026年10月】

開発 — 2026.10.19

← ブログ一覧に戻る

はじめに

  • 他社のアプリ経由でストアが攻撃されたと聞いて、自分のアプリが心配になった
  • アプリのセキュリティで、何から手を付ければいいのか分からない
  • Shopifyが開発者に求めていることを、まとめて知りたい

このような方のための記事です。

この記事では、2026年10月にShopifyのストアで起きた偽の決済画面への誘導を、アプリ開発者の側から見直します。そのうえで、Shopify公式のセキュリティの指針と、実際に自社のアプリを点検して見つかった漏れをもとに、開発者が固めておくべきことを7つにまとめます。

アプリ開発者から見た今回の攻撃

ストア運営者向けの経緯と確認の手順は偽の決済画面の記事にまとめています。開発者として見ておきたいのは、攻撃が入ってきた場所です。

被害が出たアプリのひとつは、店がアプリの管理画面に書いた「カスタムJavaScript」を、開発元のサーバーから配信してストアの全訪問者のブラウザで動かす作りでした。もうひとつのアプリでは、開発元の内部ツールに不正にアクセスされ、一部のストアの設定に悪意あるスクリプトが入りました。

外部記事Shopify tells Australian store to stay shut after hijacked extensions divert shoppersMalicious Javascript in add-ons sent shoppers to fake checkouts.itnews.com.auShopify tells Australian store to stay shut after hijacked extensions divert shoppers

どちらも、アプリのコードそのものではなく、開発元のサーバーや管理の仕組みが入り口になっています。アプリを入れているストアから見れば、開発元のサーバーは自分のページにコードを流し込める場所です。そこを押さえられると、入っている全ストアに一度に届きます。

アプリ開発者の側で攻撃が入りうる3つの場所。デプロイの権限、アプリのサーバーとデータベース、依存パッケージ。どれもストアのページに届く

Shopify公式の指針は、店がアプリを入れた時点で、Shopifyが店から預かった信頼が開発者に渡ると書いています。そのうえで、外から来る入力はShopifyから来たものも含めて、確かめるまで信用しないよう求めています。

外部記事Following security best practicesA primer on building and operating secure Shopify apps, themes, and integrations. Covers common vulnerabilities, input handling, infrastructure, supply-chain risk, and AI.shopify.devFollowing security best practices

1. 店頭で動くコードは固定のファイルにする

ストアに読み込ませるJavaScriptは、テーマアプリ拡張に同梱した固定のファイルにしてください。テーマアプリ拡張のファイルはShopifyのCDNから配信され、中身を変えるにはshopify app deployで新しい版を出す必要があります。サーバーが乗っ取られても、それだけで店頭のコードは書き換わりません。

逆に、サーバーから受け取った文字列をevalやnew Functionで動かす作りや、外部のURLからscriptを差し込む作りは避けてください。店に任意のJavaScriptを書かせる機能も、自分のサーバーを攻撃者の配信網にしかねません。要望があっても入れない、と決めておくのが安全です。

古い仕組みのスクリプトタグは、2027年3月1日にストアで動かなくなるとShopifyが告知しています。まだ使っているアプリは、テーマアプリ拡張かWebピクセルへの移行が必要です。

2. サーバーから来た値はすべてエスケープして出す

コードを固定のファイルにしても、サーバーの値をそのままHTMLに出していれば同じことが起きます。メタフィールドやApp Proxyの応答を書き換えられると、その値の中のscriptがストアで動くからです。

公式の指針は、Liquidは出力を自動でエスケープしないと明記しています。HTMLの本文と属性にはescape、scriptの中にはjsonを使い、JavaScriptではinnerHTMLではなくtextContentのように文字だけを扱う方法で入れるよう勧めています。

自社で開発しているアプリを点検したところ、次の4つの形の漏れが見つかりました。どれも今は直してリリースしています。

メタフィールドの値を素のまま出していた

会員ランクの名前など、アプリのサーバーがメタフィールドに書いた値をそのまま出していました。値は店が管理画面で付けたものですが、サーバーを乗っ取られれば何でも入れられます。

{%- comment -%} 修正前 {%- endcomment -%}
<li>会員ランク {{ rp_pts.tier.name }}</li>

{%- comment -%} 修正後 {%- endcomment -%}
<li>会員ランク {{ rp_pts.tier.name | escape }}</li>

数値のつもりの値でも、属性に入るならescapeを付けてください。型を決めているのは自分のサーバーなので、乗っ取られたときは文字列が来ます。

エスケープの関数が引用符を変換していなかった

要素のtextContentに入れてinnerHTMLで読み戻す、よく見かけるエスケープの書き方です。この方法は<や&は変換しますが、"は変換しません。属性の値に使うと、"で属性の外に抜けられます。

// 属性にも入れるので引用符まで変換する
function escapeHtml(text) {
  return String(text)
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
}

リンク先にjavascript:が入った

ボタンのリンク先やリダイレクト先をエスケープしていても、javascript:で始まるURLはそのまま通ります。押した瞬間やページを開いた瞬間にコードが動くので、URLは種類まで確かめてください。

// 相対パスと http(s) だけを通す
function safeUrl(value, fallback) {
  try {
    const url = new URL(value, location.href);
    return url.protocol === 'http:' || url.protocol === 'https:' ? value : fallback;
  } catch {
    return fallback;
  }
}

色の値をstyleの中にそのまま入れていた

管理画面で選んだ色を<style>の中に書いていたため、色の値に</style>を入れると、その後ろにHTMLを書けました。色はCSS.supports("color", value)や正規表現で、色として読める形だけを通すようにしています。

3. デプロイの権限とアカウントを守る

いちばん影響が大きいのは、Partnerのアカウントやデプロイの権限を取られることです。不正な版をshopify app deployで出されると、入っている全ストアに正規の更新として届きます。

公式の指針は、パッケージのレジストリとソース管理のすべてのアカウントで2段階認証を必須にするよう求めています。Shopifyのパートナーのアカウント、GitHub、npm、サーバーとデータベースのホスティング、ドメインの管理まで、ストアに届く道を持つアカウントはすべて対象です。組織のメンバーとCLIのトークンも、使っていないものは消してください。

アプリがストアのAPIに使うオフラインのアクセストークンは、期限付きのものへの移行が必須になっています。期限は1時間で、盗まれても自然に使えなくなります。期限の無いトークンは、2027年1月1日以降にGraphQL Admin APIで拒否されます。

4. 依存パッケージから入るのを防ぐ

店頭の固定のファイルも、ビルドに使うパッケージに不正なコードが混ざれば一緒に配信されます。公式の指針は、ロックファイルをコミットしてCIで固定のインストールを強制すること、新しい版は公開から7日以上たってから入れることを勧めています。依存は少なく保ち、脆弱性の知らせが出たものは早めに上げてください。

5. リリースのたびにshopify app security checkを通す

2026年10月15日、Shopify CLIにshopify app security checkが加わりました。アプリのコード、拡張の設定、依存パッケージを手元で検査し、見つけた問題をファイルと行、重さ、直し方の例つきで出します。提出の前とリリースのたびに通すよう勧められています。

外部記事Build with confidence: Shopify AI Toolkit's security check - Shopify developer blogCheck your app for security vulnerabilities with `shopify app security check`. Run it before you submit an app, and on every release, to catch problems in your own code and get rem...shopify.devBuild with confidence: Shopify AI Toolkit's security check - Shopify developer blog

shopify app security check

自社のアプリで通したときは、エスケープ済みの値を入れているinnerHTMLも指摘に出ました。機械的に拾う検査なので、出た指摘は1件ずつ中身を確かめる必要があります。公式も、問題が出ないことは安全の保証ではないと書いています。上の2のような漏れは、Liquidとサーバーの値の流れを自分で追わないと見つかりませんでした。

6. 本番のストアで毎日見張る

コードを直しても、設定やサーバーが外から書き換えられる心配は残ります。自分のアプリを入れた開発ストアで、毎日決まった確認を自動で回しておくと、何か起きたときに早く気づけます。

RYXでは毎朝、本番のアプリを入れた開発ストアで商品をカートに入れて「チェックアウト」を押し、自分のストアのドメインの決済画面に着くかを確かめています。あわせて、ページが読み込んだスクリプトの送り元を一覧にし、前の日にはなかったドメインが増えていないかを見ています。

7. 何かあったときの連絡先と手順を決めておく

侵害が疑われるときは、確証を待たずにShopifyのsecurity@shopify.comへ知らせるよう、公式の指針は求めています。漏れたかもしれないシークレットは、確かめる前に失効か入れ替えをしてください。

今回の攻撃では、被害店の店主がShopifyより開発元からのほうが多くの情報を得られたと話しています。入っているストアへ何を、どこから知らせるかも、あらかじめ決めておくと慌てずに済みます。

さいごに

今回の攻撃は、アプリのコードではなく、開発元のサーバーや管理の仕組みから入りました。店頭のコードを固定のファイルにし、サーバーから来た値をすべてエスケープして出せば、サーバーを押さえられても店頭まで届く道はかなり細くなります。そのうえで、アカウントとデプロイの権限を固め、リリースのたびに検査し、本番を毎日見張ってください。

自社アプリの点検やセキュリティの見直しは、お問い合わせからお気軽にご相談ください。

Contact

Shopifyのご相談はこちら

構築・移行・改修・運用改善まで。状況を伺って最短ルートをご提案します。

相談・見積もり無料 / 24時間以内に返信

相談する