Skip to content

Commit 344942f

Browse files
Merge remote-tracking branch 'origin/main' into lv5
2 parents 114d069 + 10e4b34 commit 344942f

File tree

4 files changed

+52
-34
lines changed

4 files changed

+52
-34
lines changed

src/content.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,26 @@ function isDisplayed(el: Element | null): boolean {
1818
// 複数の問題の「現在の値」をまとめて取得する
1919
function getCurrentValues() {
2020
// 問題1: テキストのチェック
21-
const el1 = document.querySelector<HTMLElement>('[data-check]')
21+
const el1 = document.querySelector<HTMLElement>('.reviewText2')
2222
const val1 = el1 ? (el1.textContent ?? '').trim() : ''
2323

2424
// 問題2: 画像のsrcチェック
25-
// data-check2属性を持つ画像のsrcを取得する
26-
const el2 = document.querySelector('[data-check2]') as HTMLImageElement
27-
// src属性そのもの(例: "img/star5.png")を取得。絶対パス化されるのを防ぐため getAttribute を推奨
25+
const el2 = document.querySelector('#starIcon2 img') as HTMLImageElement
2826
const val2 = el2 ? (el2.getAttribute('src') ?? '') : ''
2927

3028
// 問題3: 要素の表示状態チェック
31-
const el3 = document.querySelector<HTMLElement>('[data-check3]')
29+
const el3 = document.querySelector<HTMLElement>('.reviewBox1')
3230
const val3Visible = isDisplayed(el3)
3331

32+
// 問題4: 価格表示のテキスト
33+
const el4 = document.querySelector<HTMLElement>('#discountMessage')
34+
const val4 = el4 ? (el4.textContent ?? '').trim() : ''
35+
3436
return {
3537
p1: val1,
3638
p2: val2,
37-
p3Visible: val3Visible,
39+
p3Visible: val3Visible,
40+
p4: val4,
3841
}
3942
}
4043

src/sidepanel/App.tsx

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const ANSWERS = {
99
p1: "すばらしい。",
1010
p2: "./images/star5.png",
1111
p3Visible: false,
12+
p4: "30%割引が適用されました!",
1213
}
1314

1415
function App() {
@@ -21,10 +22,11 @@ function App() {
2122
// イベントリスナー内で最新の step を参照するための Ref
2223
const stepRef = useRef(step)
2324
// 各ステップの初期値を保持するベースライン
24-
const baselineRef = useRef<{ p1: string | null; p2: string | null; p3Visible: boolean | null }>({
25+
const baselineRef = useRef<{ p1: string | null; p2: string | null; p3Visible: boolean | null; p4: string | null }>({
2526
p1: null,
2627
p2: null,
2728
p3Visible: null,
29+
p4: null,
2830
})
2931

3032
// state が変わったら ref も更新しておく
@@ -44,14 +46,11 @@ function App() {
4446

4547
port.onMessage.addListener((msg) => {
4648
if (msg?.type === 'DOM_VALUE_UPDATE') {
47-
const { p1, p2, p3Visible } = msg.values
49+
const { p1, p2, p3Visible, p4 } = msg.values
4850
const currentStep = stepRef.current
4951

5052
if (currentStep === 1) {
51-
if (baselineRef.current.p1 === null) {
52-
baselineRef.current.p1 = p1
53-
return
54-
}
53+
if (baselineRef.current.p1 === null) { baselineRef.current.p1 = p1; return }
5554
if (p1 !== baselineRef.current.p1) {
5655
const isCorrect = p1 === ANSWERS.p1
5756
setResult({ ok: isCorrect, details: isCorrect ? `一致: "${p1}"` : `不一致: "${p1}"` })
@@ -60,16 +59,13 @@ function App() {
6059
setStep(2)
6160
setResult(null)
6261
baselineRef.current.p2 = p2
63-
}, 2000)
62+
}, 4000)
6463
}
6564
}
6665
}
6766

6867
if (currentStep === 2) {
69-
if (baselineRef.current.p2 === null) {
70-
baselineRef.current.p2 = p2
71-
return
72-
}
68+
if (baselineRef.current.p2 === null) { baselineRef.current.p2 = p2; return }
7369
if (p2 !== baselineRef.current.p2) {
7470
const isCorrect = p2.includes(ANSWERS.p2)
7571
setResult({ ok: isCorrect, details: isCorrect ? `一致: (${p2})` : `不一致: (${p2})` })
@@ -78,30 +74,36 @@ function App() {
7874
setStep(3)
7975
setResult(null)
8076
baselineRef.current.p3Visible = p3Visible
81-
}, 2000)
77+
}, 4000)
8278
}
8379
}
8480
}
8581

86-
// 問題3のロジック
8782
if (currentStep === 3) {
88-
if (baselineRef.current.p3Visible === null) {
89-
baselineRef.current.p3Visible = p3Visible
90-
return
91-
}
83+
if (baselineRef.current.p3Visible === null) { baselineRef.current.p3Visible = p3Visible; return }
9284
if (p3Visible !== baselineRef.current.p3Visible) {
9385
const isCorrect = p3Visible === ANSWERS.p3Visible
86+
setResult({ ok: isCorrect, details: isCorrect ? `要素が非表示になりました` : `要素はまだ表示されています` })
87+
if (isCorrect) { setTimeout(() => { setStep(4); setResult(null); baselineRef.current.p4 = p4 }, 4000) }
88+
}
89+
}
90+
91+
// 問題4のロジック
92+
if (currentStep === 4) {
93+
if (baselineRef.current.p4 === null) { baselineRef.current.p4 = p4; return }
94+
if (p4 !== baselineRef.current.p4) {
95+
const isCorrect = p4 === ANSWERS.p4
9496
setResult({
9597
ok: isCorrect,
96-
details: isCorrect ? `要素が非表示になりました` : `要素はまだ表示されています`
98+
details: isCorrect ? `割引が適用されました!` : `まだ割引が適用されていません。`
9799
})
98100
}
99101
}
100102
}
101103
})
102104

103105
port.onDisconnect.addListener(() => {
104-
baselineRef.current = { p1: null, p2: null, p3Visible: null }
106+
baselineRef.current = { p1: null, p2: null, p3Visible: null, p4: null }
105107
port = null
106108
setResult(null)
107109
setStep(1)
@@ -117,7 +119,7 @@ function App() {
117119
if (port) {
118120
try { port.disconnect() } catch {}
119121
}
120-
baselineRef.current = { p1: null, p2: null, p3Visible: null }
122+
baselineRef.current = { p1: null, p2: null, p3Visible: null, p4: null }
121123
}
122124
}, [])
123125

@@ -144,18 +146,27 @@ function App() {
144146
</div>
145147
)}
146148

147-
{/* ステップ3の表示 */}
148149
{step === 3 && (
149150
<div>
150151
<h2>問題3</h2>
151152
<p>一つ目のレビューを、CSSを使って非表示にしてみよう!</p>
153+
{result && <div className={result.ok ? "result-ok" : "result-ng"}><h3>判定: {result.ok ? '正解!' : '不正解'}</h3><p>{result.details}</p>{result.ok && <p>次の問題へ進みます...</p>}</div>}
154+
{!result && <p className="hint">ヒント:DevToolsのスタイルパネルで <code>display: none;</code> を追加してみよう。</p>}
155+
</div>
156+
)}
157+
158+
{/* 問題4のUI */}
159+
{step === 4 && (
160+
<div>
161+
<h2>問題4</h2>
162+
<p>割引コードを盗んで、30%割引を適用させよう!</p>
152163
{result && (
153164
<div className={result.ok ? "result-ok" : "result-ng"}>
154165
<h3>判定: {result.ok ? '正解!' : '不正解'}</h3>
155166
<p>{result.details}</p>
156167
</div>
157168
)}
158-
{!result && <p className="hint">ヒント:DevToolsのスタイルパネルで <code>display: none;</code> を追加してみよう。</p>}
169+
{!result && <p className="hint">ヒント:sourcesに割引コードが書かれているかも</p>}
159170
</div>
160171
)}
161172
</div>

vulnerable-web/shopping/index.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@ <h1 class="productName">
4646
<section class="reviewSection">
4747
<h2>レビュー</h2>
4848
<div class="reviewContainer">
49-
<div class="reviewBox1" data-check3>
49+
<div class="reviewBox1">
5050
<img src="./images/reviewIcon.png" class="reviewIcon" />
5151
<div class="reviewContent">
5252
<p class="username">Username</p>
5353
<div id="starIcon1"><img src="./images/star2.png"></div>
54-
<p class="reviewText">
54+
<p class="reviewText1">
5555
ワイヤレスには対応しているものの、有線接続用のケーブルを取り外すことができず、非常に邪魔くさい。
5656
音質も値段の割には悪い。ノイキャンは効いているかどうかわからないレベルであり、
5757
電車内では普通にノイズが聞こえる。
@@ -62,8 +62,8 @@ <h2>レビュー</h2>
6262
<img src="./images/reviewIcon.png" class="reviewIcon" />
6363
<div class="reviewContent">
6464
<p class="username">Username</p>
65-
<div id="starIcon2"><img src="./images/star1.png" data-check2></div>
66-
<p class="reviewText" data-check>
65+
<div id="starIcon2"><img src="./images/star1.png"></div>
66+
<p class="reviewText2">
6767
とにかくひどい。
6868
</p>
6969
</div>
@@ -88,6 +88,6 @@ <h2>レビュー</h2>
8888
©2025 ut.code(); 当サイトのコンテンツはフィクションであり、実際の商品・会社とは一切関係ありません。
8989
</p>
9090
</footer>
91-
<script src="/script.mjs"></script>
91+
<script src="script.mjs"></script>
9292
</body>
9393
</html>

vulnerable-web/shopping/style.css

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,11 @@ main {
183183
margin-bottom: 5px;
184184
}
185185

186-
.reviewtext {
186+
.reviewText1 {
187+
margin-top: 10px;
188+
color: #555;
189+
}
190+
.reviewText2 {
187191
margin-top: 10px;
188192
color: #555;
189193
}

0 commit comments

Comments
 (0)