Skip to content

fix: 게임 빌드 시크릿 기본값을 없애고 비어 있으면 웹훅·업로드 토큰을 모두 막는다 - #143

Merged
ff1451 merged 2 commits into
mainfrom
fix/game-webhook-secret
Oct 16, 2026
Merged

ff1451 merged 2 commits into
mainfrom
fix/game-webhook-secret

Conversation

@ff1451

@ff1451 ff1451 commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

#141(테스트 인프라) 위에 쌓인 PR이다. #141이 머지되면 base가 main으로 바뀐다.

요약

app.game-build.secret은 홈페이지 서버와 공유하는 값으로 완료 웹훅 인증과 업로드 토큰 HMAC 서명에 함께 쓰인다. 기존 설정에는 세 가지 문제가 있었다.

  1. ${GAME_BUILD_SECRET:local-dev-secret} — 환경변수가 빠지면 저장소에 공개된 값으로 웹훅과 업로드 토큰을 둘 다 위조할 수 있었다.
  2. 환경변수가 빈 문자열이면, 웹훅 컨트롤러가 헤더 기본값을 ""로 받으므로 "".equals("")가 되어 시크릿 헤더 없는 웹훅이 통과했다(/v1/games/**는 permitAll이라 시크릿이 유일한 인증이다).
  3. String.equals 비교라 응답 시간으로 값이 드러날 수 있었다.

변경

  • 기본값 제거: secret: ${GAME_BUILD_SECRET:}.
  • GameBuildProperties.matchesSecret(): 설정이 비었거나 헤더가 비면 항상 불일치, 아니면 SHA-256 후 MessageDigest.isEqual(봇 서비스 토큰 인증과 같은 방식).
  • 시크릿이 비어 있으면 업로드 토큰 발급은 503 GAME_BUILD_UPLOAD_NOT_CONFIGURED(이전에는 빈 키로 HMAC을 만들다 500).
  • .env.example에 GAME_BUILD_SECRET 설명 추가.

배포 전 확인

운영 deploy.yml은 GAME_BUILD_SECRET 저장소 시크릿을 넘긴다. 이 시크릿이 설정돼 있으면 동작 변화 없음. 비어 있으면 머지 후 게임 빌드 업로드가 503이 되므로, 홈페이지 서버와 같은 값을 넣어야 한다. 로컬 개발에서 게임 빌드 업로드를 쓰려면 .env에 값을 넣는다.

테스트

  • GameBuildPropertiesTest(단위): 일치/불일치, 빈 설정에서 빈 값도 불일치, 빈 설정에서 토큰 발급 거부.
  • GameBuildWebhookNoSecretIntegrationTest: 시크릿 미설정 서버에서 헤더 없음·빈 헤더 웹훅 모두 401.
  • AdminGameBuildIntegrationTest는 저장소 기본값 대신 테스트 프로퍼티로 시크릿을 받는다.
  • 로컬 전체 ./gradlew test: 537건 중 536 통과, 1 스킵.

Summary by CodeRabbit

  • Security
    • Game-build uploads now require a configured secret; otherwise, the server reports that uploads are unavailable.
    • Webhook secrets are validated securely, and missing or empty secrets are rejected.
    • The default secret is now empty, so a secret must be configured explicitly.

- application.yml의 GAME_BUILD_SECRET 기본값(local-dev-secret)을 제거한다. 이 값은 웹훅 인증과
  업로드 토큰 HMAC 서명에 함께 쓰여, 환경변수가 빠지면 저장소에 공개된 값으로 둘 다 위조할 수 있었다.
- 시크릿이 비어 있으면 웹훅은 401(이전에는 빈 시크릿과 빈 헤더가 일치해 통과), 토큰 발급은 503으로 막는다.
- 웹훅 시크릿 비교를 SHA-256 후 MessageDigest.isEqual로 바꿔 상수 시간으로 비교한다.
@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 44 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 6cfd15d9-7616-4fd1-a99a-5c05dffda6fa
📥 Commits

Reviewing files that changed from the base of the PR and between 3d13848 and 6f3e230.

📒 Files selected for processing: 9
  • .env.example
  • src/main/java/com/bcsdlab/bcsdinternalapiv2/game/config/GameBuildProperties.java
  • src/main/java/com/bcsdlab/bcsdinternalapiv2/game/exception/GameExceptionType.java
  • src/main/java/com/bcsdlab/bcsdinternalapiv2/game/service/GameBuildTokenService.java
  • src/main/java/com/bcsdlab/bcsdinternalapiv2/game/service/GameBuildWebhookService.java
  • src/main/resources/application.yml
  • src/test/java/com/bcsdlab/bcsdinternalapiv2/game/AdminGameBuildIntegrationTest.java
  • src/test/java/com/bcsdlab/bcsdinternalapiv2/game/GameBuildPropertiesTest.java
  • src/test/java/com/bcsdlab/bcsdinternalapiv2/game/GameBuildWebhookNoSecretIntegrationTest.java

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 245b2c71-b9f6-43ae-a000-babf7a1588e2
📥 Commits

Reviewing files that changed from the base of the PR and between 012c531 and 3d13848.

📒 Files selected for processing: 9
  • .env.example
  • src/main/java/com/bcsdlab/bcsdinternalapiv2/game/config/GameBuildProperties.java
  • src/main/java/com/bcsdlab/bcsdinternalapiv2/game/exception/GameExceptionType.java
  • src/main/java/com/bcsdlab/bcsdinternalapiv2/game/service/GameBuildTokenService.java
  • src/main/java/com/bcsdlab/bcsdinternalapiv2/game/service/GameBuildWebhookService.java
  • src/main/resources/application.yml
  • src/test/java/com/bcsdlab/bcsdinternalapiv2/game/AdminGameBuildIntegrationTest.java
  • src/test/java/com/bcsdlab/bcsdinternalapiv2/game/GameBuildPropertiesTest.java
  • src/test/java/com/bcsdlab/bcsdinternalapiv2/game/GameBuildWebhookNoSecretIntegrationTest.java

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📝 Walkthrough

Game-build secret configuration now has no default value. Token issuance rejects requests when the secret is not configured, and webhook authentication uses secret-matching logic that rejects missing or empty presented values.

Changes: Game-build secret handling

Layer / File(s) Summary
Configure and validate the shared secret
.env.example, src/main/resources/application.yml, src/main/java/com/bcsdlab/bcsdinternalapiv2/game/config/GameBuildProperties.java
The example documents the shared secret, and the application fallback is empty. GameBuildProperties checks for a configured secret and compares SHA-256 digests.
Reject token issuance without a configured secret
src/main/java/com/bcsdlab/bcsdinternalapiv2/game/exception/GameExceptionType.java, src/main/java/com/bcsdlab/bcsdinternalapiv2/game/service/GameBuildTokenService.java, src/test/java/com/bcsdlab/bcsdinternalapiv2/game/GameBuildPropertiesTest.java, src/test/java/com/bcsdlab/bcsdinternalapiv2/game/AdminGameBuildIntegrationTest.java
Token issuance throws the new service-unavailable exception when the secret is not configured. Tests cover secret matching, token issuance, and a configured test secret.
Validate webhook secrets
src/main/java/com/bcsdlab/bcsdinternalapiv2/game/service/GameBuildWebhookService.java, src/test/java/com/bcsdlab/bcsdinternalapiv2/game/GameBuildWebhookNoSecretIntegrationTest.java
Webhook authentication uses matchesSecret. Integration tests expect HTTP 401 for missing and empty secret headers.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 3d138

No actionable merge-blocking issue is identified. Game-build uploads require a configured secret after deployment.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 7 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly summarizes the main changes: removing the default game-build secret and blocking webhook authentication and upload-token issuance when the secret is empty.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 7 files. (2 skipped: 2 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ff1451
ff1451 changed the base branch from refactor/test-infra to main October 16, 2026 07:07
@ff1451
ff1451 merged commit 40063c7 into main Oct 16, 2026
2 checks passed
@ff1451
ff1451 deleted the fix/game-webhook-secret branch October 16, 2026 07:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant