[P0][security] /v1/sign keyless signing endpoint 인증/권한 및 replay 방어 추가 #20

Closed
opened 2026-05-02 04:34:03 +00:00 by boxqkrtm · 1 comment

문제

crates/portal-relay/src/api/mod.rs/v1/sign 경로가 별도 인증 없이 keyless::sign()을 호출합니다. crates/portal-relay/src/api/keyless.rskey_id, algorithm, digest, timestamp, nonce 등 freshness 중심 검증은 하지만 요청자가 권한 있는 client인지 보장하지 못합니다.

위험

public endpoint로 노출되면 relay TLS private key 기반 서명 oracle이 될 수 있습니다. 공격자는 임의 digest에 대해 relay 인증서 private key 서명을 받아낼 수 있습니다. timestamp ±30초와 nonce는 freshness 체크일 뿐이며, nonce replay 저장소도 없습니다.

제안

  • lease access token, mTLS, 또는 내부 전용 listener 등으로 endpoint 접근 제한
  • key_id + nonce 기반 replay cache 추가 및 TTL 만료 처리
  • 허용 algorithm/key_id/digest length를 명시적으로 제한
  • 가능하면 digest가 실제 TLS handshake transcript/protocol state와 바인딩되는지 검증
  • public API router와 keyless signer 경계를 분리하고 audit log 추가

완료 기준

  • 인증 없는 /v1/sign 요청은 401/403으로 실패
  • 같은 nonce replay 요청은 거부
  • 권한 없는 lease/client의 signing 요청이 거부
  • keyless signing misuse 회귀 테스트 추가

검토 기준: 업로드된 Rust portal-relay 코드 정적 리뷰. 리뷰 환경에서는 cargo check/test/clippy를 실행하지 못했습니다.

## 문제 `crates/portal-relay/src/api/mod.rs`의 `/v1/sign` 경로가 별도 인증 없이 `keyless::sign()`을 호출합니다. `crates/portal-relay/src/api/keyless.rs`는 `key_id`, `algorithm`, `digest`, timestamp, nonce 등 freshness 중심 검증은 하지만 요청자가 권한 있는 client인지 보장하지 못합니다. ## 위험 public endpoint로 노출되면 relay TLS private key 기반 **서명 oracle**이 될 수 있습니다. 공격자는 임의 digest에 대해 relay 인증서 private key 서명을 받아낼 수 있습니다. timestamp ±30초와 nonce는 freshness 체크일 뿐이며, nonce replay 저장소도 없습니다. ## 제안 - lease access token, mTLS, 또는 내부 전용 listener 등으로 endpoint 접근 제한 - `key_id + nonce` 기반 replay cache 추가 및 TTL 만료 처리 - 허용 algorithm/key_id/digest length를 명시적으로 제한 - 가능하면 digest가 실제 TLS handshake transcript/protocol state와 바인딩되는지 검증 - public API router와 keyless signer 경계를 분리하고 audit log 추가 ## 완료 기준 - 인증 없는 `/v1/sign` 요청은 401/403으로 실패 - 같은 nonce replay 요청은 거부 - 권한 없는 lease/client의 signing 요청이 거부 - keyless signing misuse 회귀 테스트 추가 --- 검토 기준: 업로드된 Rust `portal-relay` 코드 정적 리뷰. 리뷰 환경에서는 `cargo check/test/clippy`를 실행하지 못했습니다.
Owner

수용했습니다. PR #62에서 /v1/sign에 lease access token 기반 인증, key_id+nonce replay cache, digest length/algorithm 제한, raw error 축소를 추가했습니다. 검증: cargo test --locked, cargo clippy --locked --all-targets -- -D warnings.

수용했습니다. PR #62에서 /v1/sign에 lease access token 기반 인증, key_id+nonce replay cache, digest length/algorithm 제한, raw error 축소를 추가했습니다. 검증: cargo test --locked, cargo clippy --locked --all-targets -- -D warnings.
gofix closed this issue 2026-05-03 18:58:00 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
gofix/portal-tunnel-rs#20
No description provided.