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-20 - [html4tree] μ›μžμ  이동(Atomic Move)을 ν†΅ν•œ Race Condition λ°©μ§€
**Vulnerability:** 파일 μ €μž₯ μ‹œ μ“°κΈ° μž‘μ—…μ΄ μ§„ν–‰ μ€‘μ΄κ±°λ‚˜ μž„μ‹œ νŒŒμΌμ—μ„œ μ΅œμ’… 파일둜 κ΅μ²΄λ˜λŠ” λ™μ•ˆ λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€κ°€ νŒŒμΌμ„ 읽으면 λΆˆμ™„μ „ν•œ λ‚΄μš©μ„ 읽게 될 μœ„ν—˜(Race Condition)이 μ‘΄μž¬ν•¨.
**Learning:** `Files.move`λŠ” μ›μžμ„±μ„ 보μž₯ν•˜μ§€ μ•Šμ„ 수 있으며, μ΄λŠ” `REPLACE_EXISTING` ν”Œλž˜κ·Έλ§Œ μ‚¬μš©ν•  경우 파일 μ‹œμŠ€ν…œμ— 따라 λΆ€λΆ„μ μœΌλ‘œλ§Œ μž‘μ„±λœ 파일이 λ…ΈμΆœλ  수 μžˆμŒμ„ 배움.
**Prevention:** `Files.move`에 `StandardCopyOption.ATOMIC_MOVE` μ˜΅μ…˜μ„ μš°μ„ μ μœΌλ‘œ μ μš©ν•˜κ³ , 파일 μ‹œμŠ€ν…œμ—μ„œ μ§€μ›ν•˜μ§€ μ•ŠλŠ” 경우 μ˜ˆμ™Έ(`AtomicMoveNotSupportedException`)λ₯Ό μž‘μ•„ `REPLACE_EXISTING`으둜 폴백(fallback)ν•˜μ—¬ 데이터λ₯Ό 보닀 μ•ˆμ „ν•˜κ²Œ μ €μž₯함.
16 changes: 14 additions & 2 deletions src/main/kotlin/html4tree/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,24 @@ fun process_ignore_file(curr_dir: File, dirFilesNames: Array<String>? = null): S
return files_to_exclude
}

fun write_index_file(curr_dir: File, content: String) {
// λ³΄μ•ˆ ν–₯상: μž„μ‹œ νŒŒμΌμ—μ„œ μ΅œμ’… 파일둜 ꡐ체할 λ•Œ μ›μžμ  이동(Atomic Move)을 μš°μ„  μ‚¬μš©ν•˜μ—¬,
// λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€κ°€ λΆˆμ™„μ „ν•œ μƒνƒœμ˜ index.html을 μ½λŠ” 것(Race Condition)을 λ°©μ§€ν•©λ‹ˆλ‹€. (Atomicity)
fun write_index_file(
curr_dir: File,
content: String,
moveOp: (java.nio.file.Path, java.nio.file.Path) -> Unit = { src, dst ->
Files.move(src, dst, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING)
}
) {
val indexPath = curr_dir.toPath().resolve("index.html")
val tempPath = Files.createTempFile(curr_dir.toPath(), ".index-", ".html")
try {
Files.write(tempPath, content.toByteArray(Charsets.UTF_8))
Files.move(tempPath, indexPath, StandardCopyOption.REPLACE_EXISTING)
try {
moveOp(tempPath, indexPath)
} catch (e: java.nio.file.AtomicMoveNotSupportedException) {
Files.move(tempPath, indexPath, StandardCopyOption.REPLACE_EXISTING)
}
} finally {
Files.deleteIfExists(tempPath)
}
Expand Down
17 changes: 17 additions & 0 deletions src/test/kotlin/html4tree/MainTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,23 @@ class MainTest {
assertTrue(htmlContent.contains("margin: 0 auto;"))
}

@Test
fun testWriteIndexFileAtomicMoveFallback() {
val tempDir = Files.createTempDirectory("test-atomic").toFile()
try {
var moveOpCalled = false
write_index_file(tempDir, "content") { src, dst ->
moveOpCalled = true
throw java.nio.file.AtomicMoveNotSupportedException(src.toString(), dst.toString(), "Test Fallback")
}
assertTrue(moveOpCalled, "moveOp should be called")
assertTrue(File(tempDir, "index.html").exists(), "index.html should still be created via fallback")
assertEquals("content", File(tempDir, "index.html").readText())
} finally {
tempDir.deleteRecursively()
}
}

@Test
fun testWriteIndexFileCleansUpTempFileOnFailure() {
// Files.move cannot replace a non-empty directory, so this drives the
Expand Down
Loading