위키 동기화 2026-06-19: 보안 트러블슈팅 노트·회의록·lessons·Digests + ASTRA 성장 산출물

- 00_Raw: ASTRA 보안 가이드 3종(SSRF/셸 명령/파일 경로 경계), 회의록 p/q/r 추가
- Topics: Digests 5종, lessons 4종, 메모리 에피소드/장기기억 갱신
- .astra: growth(decay/regression/weakness)·eval(corrections/report) 학습 산출물 갱신

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-19 18:29:23 +09:00
parent e2c5471046
commit 8957890d13
46 changed files with 1494 additions and 102 deletions
@@ -0,0 +1,106 @@
---
id: astra-path-boundary-guard-20260619
title: "ASTRA 파일 경로 경계 가드 — validatePath prefix 약점 + brain:read 클램핑"
category: "Security"
status: "applied"
verification_status: "validated"
canonical_id: ""
aliases: ["validatePath 경계", "path traversal 방지", "prefix 혼동 취약점", "path.sep 경계", "brain:read 클램핑", "isWithinRoot", "IPC 경로 가드", "경로 탈출 차단"]
duplicate_of: ""
source_trust_level: "S"
confidence_score: 0.94
created_at: 2026-06-19
updated_at: 2026-06-19
review_reason: ""
merge_history: []
tags: [security, astra, path-traversal, ipc, electron, troubleshooting]
raw_sources: ["E:/Wiki/astraai/src/security.ts", "E:/Wiki/astraai/desktop/main.ts", "E:/Wiki/astraai/src/agent/actions/fileCreateEdit.ts", "E:/Wiki/astraai/tests/validatePath.test.ts"]
applied_in: ["E:/Wiki/astraai @ branch (uncommitted, 2026-06-19)"]
github_commit: ""
---
# [[ASTRA 파일 경로 경계 가드]]
## 🎯 한 줄 통찰 (One-line insight)
**`startsWith(root)` 한 줄이 `…/astraai``…/astraai-secrets`까지 통과시키던 경계 혼동을 `path.sep` 단위 비교로 막고, 두뇌 뷰어 IPC(`brain:read`)의 임의 파일 읽기를 두뇌 루트로 클램핑했다.**
## 🧠 핵심 개념 (Core concepts)
- **prefix 혼동 (prefix confusion)**: 구분자 가드 없는 `startsWith``/foo``/foobar`를 경계 안으로 오인한다 — 반드시 `root + path.sep` 또는 `path.relative` 기반 비교.
- **realpath 경계 검사**: 심볼릭 링크 우회를 막으려면 대상의 *실제 경로*를 풀어 비교(`isWithinRoot`).
- **채널별 경계**: 두뇌 뷰어(`brain:read`)는 두뇌 루트로 제한 가능하나, 범용 파일 편집기(`fs:read/write`)는 *의도적으로* 전체 FS 접근 — 채널 목적에 맞는 경계를 둔다.
## 🩺 증상 (Symptom)
1. `validatePath`가 신뢰 루트 `e:\wiki\astraai`에 대해 `e:\wiki\astraai-secrets\x` 같은 형제 경로를 통과시켰다(접두 문자열 일치).
2. 데스크톱 IPC `astra:brain:read`가 경로 검증 없이 임의 절대경로를 최대 200KB 읽어 반환.
## 🌐 환경 / 범위 (Environment & scope)
- 프로젝트: ASTRA (`E:/Wiki/astraai`). `validatePath`는 에이전트 파일 액션(create/edit/read/delete)의 샌드박스 근간.
- 데스크톱 IPC 핸들러(`desktop/main.ts`)는 렌더러가 호출하는 파일 채널.
## 🔁 재현 절차 (Reproduction)
1. 작업폴더 `C:\sandboxroot`(부모가 드라이브 루트라 widening 없음)에서 `validatePath(root, 'C:\\sandboxroot-evil\\x')` 호출 → 기존엔 통과(BUG).
2. `window.astra.brain.read('C:\\Windows\\win.ini')` → 기존엔 임의 파일 내용 반환.
## 🔥 영향 및 심각도 (Impact & severity)
**High.** prefix 혼동은 샌드박스 형제 디렉토리 탈출을 허용. `brain:read` 무제한은 침해/주입된 렌더러가 임의 파일을 읽는 정보노출 경로.
## 🧠 근본 원인 (Root cause)
- [security.ts](E:/Wiki/astraai/src/security.ts) `validatePath`: `trusted.some(root => normalizedTarget.startsWith(root))` — 구분자 가드 부재.
- [main.ts](E:/Wiki/astraai/desktop/main.ts) `astra:brain:read`: 경계 검사 없는 `fs.readFileSync(filePath)`.
## 🔎 조사 과정 (Investigation)
- 보안 감사로 `security.ts:52` prefix 비교 약점과 `main.ts:321` 무가드 읽기 식별.
- 렌더러 사용처 추적: `brain:read`는 Brain 뷰어가 `brain:list` 결과만 읽음 → 두뇌 루트 클램핑이 기능 손실 0.
- 반면 `fs:read/write`는 Explorer/FileEditor의 **범용 편집기**(FileTree `goParent` 상위 탐색 + "연 파일이 진실의 원천"이라는 명시 주석)라 클램핑 시 문서화된 기능 파괴 → 제외 판단.
## 🛠️ 해결 (Resolution / applied fix)
1. `validatePath` 경계 비교를 `path.sep` 단위로 교정: `normalizedTarget === r || normalizedTarget.startsWith(r + path.sep)`.
2. `desktop/main.ts`에 모듈 레벨 `isWithinRoot(root, target)`(realpath + sep 가드) 추가, `astra:brain:read`를 활성 두뇌 폴더로 클램핑.
## 💻 코드 패턴 (Code patterns)
```ts
// security.ts — sep 단위 경계 비교
const isTrusted = trusted.some(root => {
const r = root.endsWith(path.sep) ? root.slice(0, -1) : root;
return normalizedTarget === r || normalizedTarget.startsWith(r + path.sep);
});
```
```ts
// desktop/main.ts — 두뇌 뷰어 채널 클램핑
H('astra:brain:read', async (_e, filePath: string) => {
try {
const root = getActiveBrainProfile().localBrainPath;
if (!root || !isWithinRoot(root, filePath)) return ''; // 두뇌 폴더 밖 → 거부
return fs.readFileSync(filePath, 'utf-8').slice(0, 200000);
} catch { return ''; }
});
```
## ✅ 검증 (Verification)
- 신규 [tests/validatePath.test.ts](E:/Wiki/astraai/tests/validatePath.test.ts) 6개: 내부 경로 허용, 형제 prefix(`…root-evil`) 차단, `..` 탈출 차단.
- `tsc` 0 에러, esbuild 양쪽 빌드 성공, 전체 716 통과.
## ⚖️ 모순 및 업데이트 (Contradictions & updates)
- **의도적으로 클램핑하지 않은 것**: `fs:read`/`fs:write`(범용 편집기, FileTree `goParent`로 전체 FS 편집이 설계 의도이자 테스트됨), `create_dir` 절대경로(주석상 "저위험·비파괴 mkdir", 테스트 보장). 이들의 본질 위협(렌더러 침해)은 `sandbox:true`+navigation 가드가 올바른 완화책 — 별도 후속 과제.
- 즉 "모든 IPC를 workingDir로 묶는" 기계적 적용은 문서화된 기능을 깨므로 **채널 목적별 경계**가 정답.
## ✅ 검증 상태 및 신뢰도
- **상태:** applied (미커밋)
- **검증 단계:** validated
- **출처 신뢰도:** S
- **신뢰 점수:** 0.94
- **중복 검사 결과:** 신규 생성
## 🔗 지식 그래프 (Knowledge Graph)
- **상위/루트:** [[ASTRA]]
- **관련 개념:** [[ASTRA 에이전트 셸 명령 실행 보안 게이트]], [[ASTRA SSRF 방어 URL fetch 경계]], [[Electron 보안 하드닝]]
- **참조 맥락:** 에이전트/IPC가 파일시스템에 접근할 때의 경계(sandbox) 설계 기준.
## 📚 출처 (Sources)
- [S1] `E:/Wiki/astraai/src/security.ts``validatePath` sep 경계 수정.
- [S2] `E:/Wiki/astraai/desktop/main.ts``isWithinRoot` + `astra:brain:read` 클램핑.
- [S3] `E:/Wiki/astraai/src/agent/actions/fileCreateEdit.ts``create_dir` 절대경로 의도(미변경 근거).
- [S4] `E:/Wiki/astraai/tests/validatePath.test.ts` — 회귀 테스트.
## 📝 변경 이력 (Change history)
- 2026-06-19: 보안 감사에서 발견한 prefix 경계 약점 + 무가드 IPC 읽기 수정 후 최초 문서화(Claude Opus 4.8).