# Songschat Security Posture

**최종 갱신:** 2026-04-24

> **관계 고지:** Songs Campus / Songschat 는 Anthropic PBC 와 어떠한 공식적 관계도 맺고 있지 않습니다.
> 본 문서에 나타나는 Anthropic 언급은 API 서비스 제공자로서의 맥락에 한정됩니다.
> 자세한 사항은 [`public/non-affiliation-notice.md`](public/non-affiliation-notice.md) 또는
> https://www.songschat.com/non-affiliation 을 참조하십시오.

---

## ⚠️ 이 문서를 읽기 전 반드시 알 것 — 쏭챗은 한 도메인 / 두 사업자

`songschat.com` 은 **서로 다른 두 운영 주체** 의 서비스를 한 도메인에서 호스팅합니다. 보안 모델과 책임 주체가 tier별로 다르므로 **섞어서 읽지 마세요.** 외부 분석 시 `/llms.txt` 를 먼저 참조하십시오.

| 구분 | **operated (직영)** | **tenant (입주)** |
|---|---|---|
| 운영 주체 | Songs Campus (본사) | 외부 강사/학원 (개별) |
| Anthropic API 키 | Songs Campus 자사 키 (서버 `.env`) | 입주자 BYOK (회원별 AES-256-GCM 암호화) |
| AI 비용 부담 | Songs Campus | 입주자 |
| 데이터 통제자(Controller) | Songs Campus | 각 입주자 |
| 대상 학생 | Songs Campus 수강생 | 입주 학원의 자체 학생 |
| 이 문서의 어느 섹션 | §A | §B |

---

# §A. Operated (직영) 보안 모델

**대상**: Songs Campus 가 자사 Anthropic API 키로 자사 학생에게 직접 제공하는 교육 도구.
**코드 위치**: `routes/operated/`, 게이트 `helpers/tier-guard.js`.

## A-1. Songs Campus Anthropic API 키 (단일 운영자 키)

- **저장 위치**: 서버 `.env` 의 `ANTHROPIC_API_KEY` (파일 권한 `0600`)
- **소유자**: Songs Campus
- **접근 주체**: 오직 서버 프로세스. 개발자·운영자 수동 조회는 로컬 기기에서만.
- **노출 방지**: `.env` 는 git 제외. 로그/응답 본문 어디에도 키 평문 미기록.
- **회전 정책**: 수동. 유출 의심 시 Anthropic 콘솔에서 즉시 revoke 후 신규 발급, `.env` 교체, PM2 재시작.

## A-2. 학생 대화 열람 정책 (교실 프레이밍)

- operated 계정은 **교실 모델** 로 설계되었습니다. 강사(Songs Campus 교수·조교)는 수강생의 AI 대화를 **실시간 열람** 할 수 있으며, 학생들 사이에도 제한적 공유가 가능합니다.
- 수강생 동의 경로: Songs Campus 오프라인/온라인 수강 신청 시점의 개인정보 수집·이용 동의서에서 수집 (별도 약관 문서 — `public/member-agreement-operated-*.md`, 준비 중).
- **구조적 한계 고지**: 수강생이 동의하지 않으면 수업 수강이 실질적으로 불가능한 구조이므로, 순수 동의의 자발성 측면에서 한계가 있음을 Songs Campus 는 인지하고 있습니다. 이 때문에 수집 범위를 **수업 맥락 내 대화** 로 최소화하고, 수업 종료 후 개인정보 제거된 형태로만 교재/게시판에 활용합니다.
- 원문 프롬프트·출력은 Songschat 서버 감사 로그(`.audit-log/`)에는 sha256 해시로만 보관됩니다 (§공통-1 참조). 원문 열람은 운영 주체인 Songs Campus 의 별도 저장소(강사 페이지 등)를 통해 이루어집니다.

## A-3. 비용 리스크

- 모든 AI 호출 비용은 Songs Campus 가 부담. 수강생 키 노출·대량 과금 리스크 **없음**.
- 외부 남용(봇·크롤러)에 의한 비용 리스크는 존재하며, 플랫폼 차원의 방어(§공통-3)로 대응.

---

# §B. Tenant (입주 BYOK) 보안 모델

**대상**: 외부 강사/학원이 `/dashboard` 로 가입해 **본인의 Anthropic API 키** 로 자체 학생에게 챗봇을 제공하는 호스팅 경로.
**코드 위치**: `routes/tenant/`, BYOK 헬퍼 `helpers/tenant/`.

## B-1. 회원 Anthropic API 키 (BYOK)

- **암호화 알고리즘:** AES-256-GCM (인증 암호화)
- **키 파생:** HKDF-SHA256(masterKey, salt=clientId, info="songschat-vault") → 학생별 32바이트 실효 키
- **저장 위치:** `.songschat-vault.json` (파일 권한 `0600`, 서버 로컬 파일시스템)
- **평문 수명:** 호출 시점에만 메모리에 존재 → 호출 종료 직후 버퍼 제로화
  (`helpers/crypto.js` 의 `decrypt` / `routes/tenant/chatbot-exec.js` 의 `apiKey = null`)
- **로그 미노출:** 평문·마스킹 포함 어떤 로그 경로에도 원본 키 기록 없음

## B-2. 마스터 키 (KEK)

**현 상태 (Phase 1 — 단일 서버 운영):**

- **저장 위치:** 서버 로컬 `.env` 파일 (`SONGSCHAT_MASTER_KEY`, 권한 `0600`)
- **생성:** 최초 기동 시 `helpers/crypto.js → ensureMasterKey()` 가 자동 생성
- **형식:** 64자리 hex (32바이트 무작위)
- **회전 정책:** 현재 수동. 회전 시 vault 전체 재암호화 절차 필요
  (마스터 키 변경 = 기존 암호문 복호화 불가)
- **백업 정책:** 운영자 오프라인 안전 보관(암호화 USB). 클라우드 미동기화.

**Phase 2 계획 (멀티 서버 or 트래픽 증가 시):**

- AWS KMS 또는 HashiCorp Vault 도입하여 envelope encryption 구조로 이행
- DEK(데이터 암호화 키) 는 KMS/Vault 가 감싸고, 서버는 KMS 호출 권한만 보유
- 6개월~1년 주기 정기 회전

**왜 현재 Phase 1 인가:** 1인 운영·단일 서버·선불 크레딧 기반이라 KMS 운영비가
보호 이득을 상회. Bus factor 1 전제에서 오프라인 백업이 더 단순하고 안전.
사용자 수·서버 수 증가 시 즉시 Phase 2 로 이행.

## B-3. HMAC 영수증 서명 키 (Receipt)

- **키 출처:** `SONGSCHAT_RECEIPT_KEY` 환경변수 (없으면 마스터 키에서 HKDF 파생)
- **알고리즘:** HMAC-SHA256, base64url 인코딩
- **버전 필드:** 영수증 payload 에 `sig_version` 포함 (현재 `v1`)
  → 키 회전 시 과거 영수증 검증을 위한 식별자
- **회전 정책:** 6~12개월 주기, 또는 유출 의심 즉시. 회전 시 `v2` 로 증가.

## B-4. 입주자의 대량 과금 리스크

- BYOK 구조상 외부 공격자가 입주자의 챗봇을 남용해 Anthropic 과금이 급증할 가능성은 **입주자 비용 리스크** 로 귀속됩니다. 플랫폼은 다음 방어선을 운영합니다:
  - 관문 10단계(goal/refusal/repeat/output-filter 등)
  - RPM 캡 (`helpers/tenant/rpm-cap.js`)
  - 일일 한도 (챗봇 레코드의 `dailyCap`)
  - Anthropic 콘솔 선불 크레딧 사용 권장 (약관 §5-1)
  - 이상 사용량 감지 시 자동 경보 이메일 + 한도 하향
- 위 방어에도 불구하고 대량 과금이 발생할 경우 **1차 책임은 키 소유자인 입주자** 에게 있음 (약관 v2 §5-2).
- **현실적 완화**: 학생이 키 탈취로 막대한 요금을 부담하는 극단 시나리오를 방지하기 위해 **선불 크레딧만 사용** 하는 것을 강하게 권장하며, 이를 가입 시 체크박스로 자기 확인받습니다.

## B-5. 입주자와 쏭챗의 역할 구분 (Controller/Processor)

- 각 tenant 챗봇의 대화 데이터에 대해 **데이터 통제자는 입주자**, 쏭챗은 처리 위탁자 지위입니다.
- 쏭챗 서버는 대화 원문을 보유하지 않으며 해시된 메타데이터(토큰 수, stop_reason 등)만 감사 로그에 기록합니다 (§공통-1).
- 입주자가 자체 학생에게 제공하는 약관·개인정보 처리 방침은 입주자가 스스로 발행해야 하며, 쏭챗은 해당 내용에 관여하지 않습니다.

---

# §공통. Songs Campus 플랫폼 공통 보안

## 공통-1. 감사 로그 (Audit Log)

- **위치:** `.audit-log/YYYY-MM-DD.jsonl` (일별 로테이션, 권한 `0600`)
- **저장 항목:** 타임스탬프, clientId, `userIdHash`(sha256 앞16자), chatbotId,
  model, stop_reason, 토큰 수, 비용, anthropic 에러
- **프롬프트/출력:** sha256 해시 (`promptSha`, `outputSha`) 로만 저장. 원문 미보관.
- **근거:** tenant 회원 약관 v2 제9조 2항 (Songschat 서버는 원문 미보유)
- **적용 범위:** operated·tenant 양쪽 모든 AI 호출

## 공통-2. 운영자 단일 장애점 (Bus factor 1) — 투명 고지

- **현재 상태**: Songs Campus 는 1인 운영(이성우) 입니다. 운영자 부재 시 tier별 영향:

| 영향 | operated | tenant |
|---|---|---|
| 신규 AI 호출 | **중단** (자사 키 회전 불가) | 계속 가능 (각 입주자 자체 키로 동작) |
| 기존 챗봇 페이지 | 서버 살아있는 한 동작 | 서버 살아있는 한 동작 |
| 위젯/MCP/starter-kit 재배포 | 중단 | 중단 |
| 신규 tenant 가입 승인 | — | 중단 |
| 서버 자체 장애 복구 | 중단 | 중단 |

- **완화 방향**: 키 회전·vault·영수증 검증 문서화는 이 SECURITY 문서 전체가 담당. 기술적 백업(암호화 USB) + 이메일 계정 접근권을 2차 신뢰자에게 위임하는 절차를 2026 하반기 중 공식화 예정.

## 공통-3. 남용·봇 방어

- 모든 `/:clientId/api/*` 경로에 `botGuard` 적용 (IP당 분당 60회, UA 패턴 차단)
- tenant BYOK 경로는 추가로 RPM 캡·일일 한도·영수증 검증 (§B-3, §B-4)
- 보안 헤더: `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`, `Cache-Control: no-store`

## 공통-4. 신고 접수

보안 취약점 발견 시: `1john324@naver.com` 로 제보 바랍니다.
모든 유효한 제보는 24시간 내 1차 회신합니다.
