제 7 장 보안 모델

Fayger 의 보안 모델은 두 갈래로 구성됩니다:

  • 출처 신뢰: BuF 산출물 자체에 서명할 수 있고, 적재 시 출처와 무결성을 검증합니다.
  • 실행 통제: BuF_Instance 는 실행 중 명시적으로 부여된 권한만 사용할 수 있고, 선언되지 않은 권한은 일절 보이지 않습니다.

두 갈래는 각각 로더 계층과 어댑터 계층에 자리 잡고, 제 6 장의 오류 모델과 제 4 장의 장애 격리에서 보강됩니다.

7.1 출처 신뢰: 서명과 다이제스트

다이제스트

각 Section 은 BuF_Manifest 에 digest 를 선언합니다. 적재 사슬의 Verify Digest 단계에서 각 Section 의 다이제스트를 다시 계산하여 비교:

  • 어느 단이라도 불일치면 LDR_DIGEST_MISMATCH 반환.
  • 오류 context 는 실패한 section_id 포함.

Trailer 의 manifest_digest 는 동시에 Manifest 자체가 잘리거나 수정되지 않았음을 검증합니다.

서명 범위

서명이 커버하는 바이트 범위:

Header || Manifest_minus_signature || Section_Index

설계 의도:

  • 공격자가 서명 후 Manifest 의 어떤 필드(signature 블록 자체 제외)라도 수정하면 서명이 무효화됩니다.
  • Section 오프셋, 길이, 다이제스트의 변경도 서명을 무효화합니다(Section_Index 가 서명 범위 내이기 때문).
  • Section 본체 자체는 서명 범위 내에 직접 포함되지 않으나, 각 단의 digest 가 Manifest 내에 있어 간접적으로 커버됩니다.

이 "manifest 에 서명, digest 가 sections 를 연쇄" 방식은 OCI Image 서명과 같은 절충: 서명 입력 크기는 통제 가능하고 검증 속도는 예측 가능합니다.

지원 서명 알고리즘 (1 단계)

  • ed25519
  • ecdsa-p256
  • rsa-pss-sha256

알고리즘 식별자와 공개 키 참조는 모두 Manifest 의 signature 블록에서 명시 선언하여, ASN.1 / X.509 기반 암묵적 협상을 피합니다.

서명 검증 결정표

조건기대 결과
강제 서명 ON ∧ 서명 없음Err(LDR_SIGNATURE_FAIL), 사유 MissingSignature
서명 있음 ∧ 검증 실패Err(LDR_SIGNATURE_FAIL), 사유 InvalidSignature
서명 있음 ∧ 검증 통과Ok
강제 서명 OFF ∧ 서명 없음Ok (개발 편의)

7.2 강제 서명 모드

강제 서명 모드(enforce signature)는 LoaderPolicy.require_signature 가 통제하는 적재 정책 스위치입니다:

struct LoaderPolicy {
  require_signature: bool
  trusted_roots: TrustedRootSet
  allowed_schema_versions: VersionRange
}

행위 제약:

  • 켜짐: 어떤 BuF 도 서명을 가지고 검증을 통과해야 하며, 그렇지 않으면 적재 거부.
  • 꺼짐: 서명 없는 BuF 도 적재 가능(개발 편의), 서명을 가졌으나 무효한 BuF 는 여전히 거부("서명한 척" 을 허용하지 않음).

릴리스 시나리오(프로덕션, 신뢰 가능 배포 채널)에서는 설정 계층에서 require_signature 를 기본 true 로 두기를 권장합니다.

7.3 신뢰 루트 관리

interface TrustStore {
  current_roots() -> TrustedRootSet
  update(roots: TrustedRootSet)
  enforce_signature() -> bool
}

업데이트 가시성 제약:

  • 작업 시퀀스 Ops(Update(roots)Load(buf) 의 혼합)에 대해, 매 Load(buf) 가 서명 검증에 사용하는 신뢰 루트 집합은 그 Load 직전 마지막 Update 가 설정한 roots 와 같아야 합니다.
  • 이 제약은 "적재 도중 root 집합이 바뀌는" 경합을 의미상 불가능하게 만듭니다.

구현 전략:

  • LoaderPipeline.load 입구에서 TrustStore 의 스냅샷을 찍고, 해당 적재 전체가 그 스냅샷을 사용.
  • 적재 기간 동안 가변 신뢰 루트 집합의 공유를 명시적으로 거부.

7.4 실행 통제: 권한 보안 모델

어댑터 계층은 capability-based security(WASI 와 동일)를 채택합니다. BuF 는 Manifest 에서 권한 요청을 선언하고, Platform_Adapter 와 호스트 정책이 공동으로 부여를 결정합니다.

형식:

granted = requested ∩ available ∩ host_policy
denied  = requested \ granted

시작 게이트

manifest.required_capabilities \ granted ≠ ∅ 인 경우:

  • start() 는 반드시 오류 반환.
  • 오류 context.missing 은 차집합과 같음.
  • 인스턴스는 Running 으로 진입하지 않음.

이는 "권한 부족 시 시작 금지" 의 단단한 제약입니다.

기본 거부

  • 선언되지 않은 권한은 BuF 에 보이지 않습니다.
  • Platform_Adapter 는 "어쨌든 비트가 그럴듯하니 통과" 같은 식으로 선언되지 않은 권한을 제공해서는 안 됩니다.
  • 인식되지 않은 Universal_Instruction 카테고리는 일률 ADP_UNSUPPORTED_INSTRUCTION 을 반환하며 "조용한 통과" 가 없습니다.

7.5 권한 분류와 축소 요점 (호스트별)

호스트 클래스전형적 사용 가능전형적 사용 불가비고
데스크톱io.*, net.*, ui.*, time, random, crypto, proc.*, host.*플랫폼과 권한에 따름권한 거의 전체 집합
서버io.*, net.*, time, random, crypto, proc.*ui.* 전부 비활성GUI 없음이 기본
브라우저net.fetch, net.websocket, ui.dom, time, random, crypto 의 부분proc.*, 대부분의 io.*강한 축소
In-App호스트가 명시 주입기본 전부 비활성가장 엄격, 호스트가 최종 결정권

7.6 보안 장벽으로서의 리소스 격리

리소스 격리는 안정성 요구이자 보안 장벽의 일부입니다:

  • 단일 BuF_Instance 의 장애가 다른 인스턴스로 전파되지 않습니다(제 4 장 장애 격리 성질).
  • 쿼터 초과는 일시 정지를 유발하여 한 인스턴스가 호스트 자원을 소진하는 것을 방지합니다.
  • 인스턴스 간 RuntimeDataArea 는 상호 불가시이며, 데이터 계층에서 사이드 채널 정보 누설을 방지합니다.

7.7 보안 / 오류의 상호작용

서명과 권한 관련 실패는 통일 오류 모델로 외부에 반환됩니다:

  • 서명 실패: LDR_SIGNATURE_FAIL, MissingSignature / InvalidSignature 등 사유 포함.
  • 권한 거부: ADP_CAPABILITY_DENIED, 거부된 권한 집합 포함.
  • 시작 게이트 실패: ADP_CAPABILITY_DENIED 재사용. context.missing 에 차집합.

오류 체인은 제 6 장과 일치: 하위 계층 오류는 cause 에, 상위 계층 오류는 자신의 source_layer 를 표시. 호출자는 체인을 따라 위치를 파악할 수 있습니다.

7.8 보안 감사 권장

감사 자체는 Fayger 의 내부 범위가 아니지만, Fayger 의 이벤트 버스, Lifecycle 이벤트, Loader 이벤트는 외부 감사 시스템에 충분한 앵커를 제공합니다:

  • 적재 사슬 각 단계의 성공 / 실패 이벤트는 출처 검증의 감사 지점.
  • Lifecycle 이벤트는 각 인스턴스의 시작 / 일시 정지 / 종료 시간선 기록.
  • 권한 축소 결과는 보안 결정의 감사 지점.
  • 서명 실패, 권한 거부, 쿼터 초과 이벤트는 외부 SIEM / 감사 파이프라인에서 구독 가능.