SAML POST 서명 AuthnRequest 검증 + 이메일 Workers/Node 추상화(B6) - #76
Merged
Conversation
- verify-xml-signature.ts: verifyEnvelopedXmlSignature(xml, certPem). xmldsigjs SignedXml.Verify 에 **sp.cert 공개키를 명시 주입**해 검증 — KeyInfo 내부 인증서를 신뢰하지 않음(자기서명+자기cert 위조 차단). - XSW(서명 래핑) 다층 방어: ds:Signature 는 루트 직계 자식 1개, Reference URI==루트 ID, enveloped transform 필수, 중복 ID 거부, SignatureMethod/DigestMethod SHA-256+ 화이트리스트(SHA-1 은 opt-in). - saml/sso POST: 기존 "서명 있으면 무조건 거부"를 실제 검증으로 교체. wantAuthnRequestsSigned 또는 서명 존재 시 sp.cert 로 검증(cert 없거나 검증 실패 → 400). 미서명+미요구는 통과. XML 은 상단에서 1회 디코드해 파서·검증기가 동일 원본을 보게 함. - 유닛 테스트 8건(정상 통과/타 키 실패/본문·서명 변조 실패/무서명/XSW 루트 불일치·중복ID/빈 cert). - ※ 자체 검증만 보장 — 실제 SP interop 은 별도 테스트 권장. 로그아웃+wantSigned resume 완성은 서버측 pending-request 보관이 필요한 후속 과제(현재 fail-closed=거부). vitest 62 passed(10 files), svelte-check 0 errors, eslint·build 통과. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- 문제: nodemailer(raw TCP SMTP)가 Cloudflare Workers 에서 미동작 → Workers 배포에서 비밀번호 재설정/아이디 찾기 메일이 런타임 실패(실제 프로덕션 결함). - email.ts send(to,subject,html,platform) 런타임 분기: platform.env.EMAIL(send_email 바인딩) 있으면 Cloudflare Email Sending(EMAIL.send, text+html), 없으면 nodemailer. nodemailer 는 동적 import 로 전환 → Workers 번들에 net/tls 미유입(빌드로 실증). - sendFindIdEmail/sendPasswordResetEmail 에 platform 스레딩(find-id/find-password 호출부). 기존 보안(escapeHtml/safeAbsoluteUrl/waitUntil 타이밍 분리/응답 균일성) 100% 보존. - app.d.ts 에 Platform.env.EMAIL?: SendEmail. wrangler.example.jsonc 에 send_email 바인딩 + EMAIL_FROM 예시·온보딩 주석. 실사용 wrangler.jsonc 는 사용자 관리(미변경). - 사용자 조치: `wrangler email sending enable <domain>` + 실사용 wrangler 에 바인딩/EMAIL_FROM 추가. adapter-cloudflare·adapter-node 빌드 성공, vitest 62 passed, svelte-check 0 errors, eslint 통과. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- CodeQL js/incomplete-multi-character-sanitization·js/double-escaping (email.ts htmlToText) 해소. - HTML 을 정규식으로 역파싱(<[^>]+> 태그 제거 + 엔티티 언이스케이프)하던 방식을 제거하고, 각 발송 함수(findId/passwordReset)가 text/plain 본문을 명시적으로 작성해 send() 에 넘긴다. 실제 취약점은 아니었으나(우리가 생성한 escape된 HTML → text/plain, 미실행) 더 정확·안전. svelte-check 0 errors, eslint·build 통과. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
개요
PR #75 이후 남았던 두 항목을 처리합니다. 둘 다 독립 에이전트 구현 + 게이트 검증.
검증: vitest 62 passed(10 files) · svelte-check 0 errors(1359 files) · eslint 통과 · adapter-cloudflare·adapter-node 빌드 성공.
1. SAML POST 바인딩 서명 AuthnRequest 검증
이전엔 서명된 POST AuthnRequest를 "검증기 없음"으로 거부했습니다. 이제 enveloped XML 서명을 검증해 수용합니다.
verify-xml-signature.ts:verifyEnvelopedXmlSignature(xml, certPem)— xmldsigjsVerify에 우리가 신뢰하는sp.cert공개키를 명시 주입(KeyInfo 내부 인증서 불신 → 자기서명+자기cert 위조 차단).ds:Signature는 루트 직계 자식 1개 · Reference URI==루트 ID · enveloped transform 필수 · 중복 ID 거부 · SignatureMethod/DigestMethod SHA-256+ 화이트리스트(SHA-1은 opt-in).saml/ssoPOST: 서명 존재 또는wantAuthnRequestsSigned시sp.cert로 검증(없거나 실패 → 400). 미서명+미요구는 통과. GET(Redirect) 흐름 무변경.2. 이메일 발송 Workers/Node 추상화 (B6, 프로덕션 결함)
nodemailer(raw TCP SMTP)는 Cloudflare Workers에서 동작하지 않아, Workers 배포에서 비밀번호 재설정/아이디 찾기 메일이 런타임 실패했습니다.email.ts런타임 분기:platform.env.EMAIL(Cloudflaresend_email바인딩) 있으면 Cloudflare Email Sending, 없으면 nodemailer. nodemailer는 동적 import → Workers 번들에 net/tls 미유입(빌드로 실증).platform스레딩. 기존 보안(HTML escape/URL scheme 검증/waitUntil 타이밍 분리/응답 균일성) 100% 보존.app.d.ts에Platform.env.EMAIL?: SendEmail.wrangler.example.jsonc에send_email바인딩 +EMAIL_FROM예시·온보딩 주석.사용자 조치 (Cloudflare Email 활성화 — 이거 해야 Workers에서 메일 발송됨)
wrangler email sending enable <yourdomain.com>(SPF/DKIM/DMARC DNS 설정 동반).wrangler.jsonc(및wrangler.prod.jsonc)에send_email: [{ "name": "EMAIL" }]추가.EMAIL_FROM(온보딩 도메인 주소) 설정, 선택적으로EMAIL_FROM_NAME.SMTP_*그대로.🤖 Generated with Claude Code