Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,8 @@
**Vulnerability:** ์ •์  HTML ์ƒ์„ฑ ๋„๊ตฌ์—์„œ ๋งค๋ฒˆ ๋‹ค๋ฅธ Nonce๋ฅผ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•˜์—ฌ CSP์— ์ ์šฉํ•˜๋Š” ๊ฒƒ์€, ์บ์‹ฑ ํšจ์œจ์„ ์ €ํ•˜์‹œํ‚ฌ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ •์  ๋ฐฐํฌ ํ™˜๊ฒฝ(์˜ˆ: GitHub Pages ๋“ฑ)์—์„œ ์˜ฌ๋ฐ”๋ฅธ ๋ณด์•ˆ ์ •์ฑ… ์ˆ˜๋ฆฝ์„ ๋ฐฉํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ์•ˆํ‹ฐ ํŒจํ„ด์ž…๋‹ˆ๋‹ค.
**Learning:** ์ •์ ์œผ๋กœ ๊ณ ์ •๋œ ์ธ๋ผ์ธ ์Šคํƒ€์ผ์ด๋‚˜ ์Šคํฌ๋ฆฝํŠธ์—๋Š” ๋‚œ์ˆ˜ํ™”๋œ Nonce๋ณด๋‹ค ์ฝ˜ํ…์ธ  ์ž์ฒด์˜ ํ•ด์‹œ(SHA-256 ๋“ฑ)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•˜๊ณ  ์ผ๊ด€๋œ ๋ฐฉ์‹์ž„์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.
**Prevention:** ์ž๋™ ์ƒ์„ฑ๋˜๋Š” ์ •์  HTML์˜ ์ฝ˜ํ…์ธ  ๋ณด์•ˆ ์ •์ฑ…(CSP)์—๋Š” `style-src 'sha256-<HASH>'` ๋ฐฉ์‹์„ ์ ์šฉํ•˜๊ณ , `<style>` ํƒœ๊ทธ์—์„œ ๋ถˆํ•„์š”ํ•œ `nonce` ์†์„ฑ์„ ์ œ๊ฑฐํ•˜์—ฌ ๋ธŒ๋ผ์šฐ์ €์˜ ๋ฌด๊ฒฐ์„ฑ ๊ฒ€์ฆ ๊ธฐ๋Šฅ์„ ์ ๊ทน ํ™œ์šฉํ•˜์‹ญ์‹œ์˜ค.

## 2024-07-23 - [html4tree] ํ™•์žฅ์ž ๊ธฐ๋ฐ˜ ๋ฏผ๊ฐ ํŒŒ์ผ ๋™์  ์ œ์™ธ
**Vulnerability:** ๋ฏผ๊ฐํ•œ ํ™•์žฅ์ž๋ฅผ ๊ฐ€์ง„ ํŒŒ์ผ(์˜ˆ: `.pem`, `.db`, `.log`, `.sqlite`, `.key` ๋“ฑ)์ด ๊ธฐ๋ณธ ์ œ์™ธ ๋ชฉ๋ก์— ๋ช…์‹œ๋˜์–ด ์žˆ์ง€ ์•Š์•„ ๋””๋ ‰ํ† ๋ฆฌ ์ธ๋ฑ์Šค์— ๋…ธ์ถœ๋  ์œ„ํ—˜ (Information Exposure).
**Learning:** ๊ธฐ๋ณธ ์ œ์™ธ ๋ชฉ๋ก์— ๊ณ ์ •๋œ ํŠน์ • ํŒŒ์ผ๋ช…(์˜ˆ: `id_rsa`)๋งŒ ํฌํ•จํ•˜๋Š” ๊ฒƒ์€ ์ƒˆ๋กœ์šด ์ด๋ฆ„์˜ ํ‚ค๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํŒŒ์ผ ๋“ฑ์„ ๋ณดํ˜ธํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์ˆจ๊น€ ํŒŒ์ผ ์ œ์™ธ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํŠน์ • ๋ฏผ๊ฐํ•œ ํ™•์žฅ์ž๋ฅผ ๊ฐ€์ง„ ํŒŒ์ผ์„ ๋™์ ์ด๊ณ  ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„ ์—†์ด ์ œ์™ธํ•˜๋Š” ๊ฒƒ์ด ๋ณด๋‹ค ๊ฐ•๋ ฅํ•œ ์‹ฌ์ธต ๋ฐฉ์–ด(defense-in-depth)๋ฅผ ์ œ๊ณตํ•จ์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.
**Prevention:** ์ •์  ๋ชฉ๋ก์„ ์œ ์ง€ํ•˜๋˜, `toLowerCase().endsWith(ext)`์™€ ๊ฐ™์ด ๋™์ ์œผ๋กœ ํ™•์žฅ์ž๋ฅผ ๊ฒ€์‚ฌํ•˜์—ฌ ๋ฏผ๊ฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ํŒŒ์ผ์„ ์‚ฌ์ „ ์ฐจ๋‹จ(Secure by Default)ํ•˜์‹ญ์‹œ์˜ค.
10 changes: 10 additions & 0 deletions src/main/kotlin/html4tree/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,19 @@ fun process_ignore_file(curr_dir: File, dirFilesNames: Array<String>? = null): S
files_to_exclude.addAll(defaultSensitiveFiles)

// ๋ณด์•ˆ ํ–ฅ์ƒ: .env, .git ๋“ฑ ๋ฏผ๊ฐํ•œ ์ •๋ณด๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ๋Š” ์ˆจ๊น€ ํŒŒ์ผ(.์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ชจ๋“  ํ•ญ๋ชฉ)์„ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋…ธ์ถœํ•˜์ง€ ์•Š๋„๋ก ์ œ์™ธ (์ •๋ณด ๋…ธ์ถœ ๋ฐฉ์ง€)
// ๋ณด์•ˆ ํ–ฅ์ƒ: ๋ฏผ๊ฐํ•œ ํ™•์žฅ์ž(.pem, .db ๋“ฑ)๋ฅผ ๋™์ ์œผ๋กœ ๊ฒ€์‚ฌํ•˜์—ฌ ๋…ธ์ถœ๋˜์ง€ ์•Š๋„๋ก ์ œ์™ธ
val sensitiveExtensions = listOf(".pem", ".key", ".keystore", ".truststore", ".sqlite", ".db", ".bak", ".log", ".pcap", ".sql")
(dirFilesNames ?: curr_dir.list())?.forEach {
if (it.startsWith(".")) {
files_to_exclude.add(it)
} else {
val lowerCaseName = it.toLowerCase()
for (ext in sensitiveExtensions) {
if (lowerCaseName.endsWith(ext)) {
files_to_exclude.add(it)
break
}
}
}
}

Expand Down
24 changes: 24 additions & 0 deletions src/test/kotlin/html4tree/MainTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,30 @@ class MainTest {
assertFalse(excluded.contains("test.txt"))
}

@Test
fun testProcessIgnoreFileSensitiveExtensions() {
// Create files with sensitive extensions (case-insensitive test as well)
File(tempDir, "private.pem").createNewFile()
File(tempDir, "database.DB").createNewFile()
File(tempDir, "app.log").createNewFile()
File(tempDir, "backup.BAK").createNewFile()
File(tempDir, "cert.key").createNewFile()
File(tempDir, "dump.sql").createNewFile()
// Create normal file to ensure it's not excluded
File(tempDir, "test.txt").createNewFile()
File(tempDir, "image.png").createNewFile()

val excluded = process_ignore_file(tempDir)
assertTrue(excluded.contains("private.pem"))
assertTrue(excluded.contains("database.DB"))
assertTrue(excluded.contains("app.log"))
assertTrue(excluded.contains("backup.BAK"))
assertTrue(excluded.contains("cert.key"))
assertTrue(excluded.contains("dump.sql"))
assertFalse(excluded.contains("test.txt"))
assertFalse(excluded.contains("image.png"))
}

@Test
fun testIgnoreFileIsDirectory() {
val ignoreDir = File(tempDir, ".html4ignore")
Expand Down
Loading