Files
2nd/00_Raw/ASTRA 파일 경로 경계 가드 2026-06-19.md
T
koriweb 8957890d13 위키 동기화 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>
2026-06-19 18:29:23 +09:00

6.5 KiB

id, title, category, status, verification_status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, created_at, updated_at, review_reason, merge_history, tags, raw_sources, applied_in, github_commit
id title category status verification_status canonical_id aliases duplicate_of source_trust_level confidence_score created_at updated_at review_reason merge_history tags raw_sources applied_in github_commit
astra-path-boundary-guard-20260619 ASTRA 파일 경로 경계 가드 — validatePath prefix 약점 + brain:read 클램핑 Security applied validated
validatePath 경계
path traversal 방지
prefix 혼동 취약점
path.sep 경계
brain:read 클램핑
isWithinRoot
IPC 경로 가드
경로 탈출 차단
S 0.94 2026-06-19 2026-06-19
security
astra
path-traversal
ipc
electron
troubleshooting
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
E:/Wiki/astraai @ branch (uncommitted, 2026-06-19)

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 validatePath: trusted.some(root => normalizedTarget.startsWith(root)) — 구분자 가드 부재.
  • 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)

// 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);
});
// 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 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)

📚 출처 (Sources)

  • [S1] E:/Wiki/astraai/src/security.tsvalidatePath sep 경계 수정.
  • [S2] E:/Wiki/astraai/desktop/main.tsisWithinRoot + astra:brain:read 클램핑.
  • [S3] E:/Wiki/astraai/src/agent/actions/fileCreateEdit.tscreate_dir 절대경로 의도(미변경 근거).
  • [S4] E:/Wiki/astraai/tests/validatePath.test.ts — 회귀 테스트.

📝 변경 이력 (Change history)

  • 2026-06-19: 보안 감사에서 발견한 prefix 경계 약점 + 무가드 IPC 읽기 수정 후 최초 문서화(Claude Opus 4.8).