Skip to content

Security — Threat model + defense layers

위협 모델

#위협영향방어
T-1MFA bombing (approval fatigue)사용자 무심코 [승인] 탭6자리 number_match + 10분 cool-down + in-flight 흡수 + Rack::Attack throttle
T-2에이전트 토큰 탈취임의 승인 요청 발사signed 모드 = Ed25519 키 분리 (토큰만으론 무효), 즉시 revoke 가능, IP 화이트리스트 옵션
T-3푸시 미도달 (Focus 모드)TTL 초과 → 작업 차단iOS time-sensitive notification + FCM HIGH priority + 사용자 정의 TTL 30s-30min
T-4책임 전가 (사용자 부인)분쟁 시 "내가 누른 게 아니다"WebAuthn assertion + display_payload_hash 봉인 + binding_message + 디바이스 ID + IP 기록
T-5감사 로그 유출고가치 거래 데이터 노출Application-layer encryption (encrypts :context_ciphertext), hash chain + DB WORM trigger, retention 정책 분리
T-6에이전트가 logi 우회룰 무시하고 직접 실행logi 가 막을 수 없음 — 사후 감사 대조 cookbook 제공
T-7에이전트 ID 도용다른 에이전트 척 행세등록 시 비대칭키 발급, 요청 서명에 사용, 사용자 인박스에 "검증됨" 뱃지
T-8Replay 공격캡처된 서명을 재전송timestamp ±5분 + nonce 1회용 (5분 윈도우) + idempotency_key 1회용
T-9display tampering에이전트 표시 ≠ 서버 기록display_payload_hash 가 사용자가 본 모든 필드 SHA-256 봉인. 결정 시 검증
T-10auth_mode 다운그레이드signed 에이전트를 bearer_only 로 강등 시도auth_mode 는 DB row 에서만 로드. 요청 파라미터 무시
T-11Host bypass공격자 호스트에서 mobile API 호출모바일 endpoint 는 api.1pass.dev exact-match host constraint (end_user_host_constraint)
T-12Hash chain race동시 write 로 체인 분기chronological.lock.last + transaction (Authentication::AuditLogger 패턴 차용)

방어 layer 상세

6자리 Number Matching

사용자 폰 화면과 에이전트 측 화면에 동일한 6자리가 표시됩니다. 일치 확인 후 Face ID. 100만 분의 1 추측 확률.

SecureRandom.random_number(1_000_000) 균등 분포. modulo 편향 없음.

2자리 (1%) 는 안전하지 않습니다 — random_number(100) 균등 분포라도 100번 시도면 당장 통과합니다.

Ed25519 서명 (signed mode)

매 요청의 canonical 문자열에 method/path/timestamp/nonce/body-digest/agent-id 가 모두 들어갑니다. 어느 하나라도 변조되면 서명이 깨집니다.

키는 등록 시 한 번만 표시되고, 서버는 public key 만 보관 — 키 유출 시 사용자가 콘솔에서 rotate_credentials! 를 누르면 in-flight 요청 포함 전부 무효화됩니다.

in-flight suppression

같은 (user, agent, action_type) 으로 pending/delivered 가 이미 있으면 새 요청은 기존 row 를 그대로 반환. 새 push 안 보냅니다. 1초에 100번 POST 해도 사용자 폰엔 알림 1건만.

Cool-down

거절 결정 후 10분간 동일 action_type 새 요청 → 429 차단. 무한 재시도 차단.

WORM (Write-Once-Read-Many)

agent_action_audit_logs 는:

  1. Rails readonly? true — update! / destroy! 시도 시 ActiveRecord::ReadOnlyRecord
  2. PostgreSQL trigger — raw SQL UPDATE / DELETE 도 차단 (logi.allow_agent_audit_purge 세션 플래그로만 우회)
  3. Hash chain — 한 row 만 위조해도 그 이후 체인이 깨짐

사용자 통제

logi 모바일 앱의 "에이전트" 탭에서 사용자는:

  • 등록된 에이전트 목록 / 마지막 사용 시각 확인
  • 개별 에이전트 즉시 revoke
  • 의심스러운 활동을 logi 보안팀에 신고

bearer_only 모드 사용 시 주의

항목권고
환경demo / dev / 로컬 테스트만
토큰 만료default 30일, 짧을수록 좋음
IP 화이트리스트필수. 단일 IP / 좁은 CIDR
Production환경변수 AGENT_BEARER_ONLY_ALLOWED=false 로 차단 가능
감사모든 요청에 auth_mode 가 기록되므로 사후 분리 가능

bearer_only 토큰 1개 유출 = 즉시 임의 승인 요청 100% 가능. signed 모드를 default 로 받으세요.

보안 이슈 신고

security@1pass.dev 로 PGP 또는 평문 모두 환영. 24시간 내 회신.

bounty 프로그램은 준비 중입니다. 별도 페이지로 추후 공지 예정.

최종 수정:

MIT License · Identity가 제품의 신뢰를 만듭니다.