Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughToken-based request validation is added to the webhook dispatcher. A new DispatchRequestWithToken option allows callers to provide a security token, which is validated against the X-Gitlab-Token header before webhook dispatch. A corresponding ErrInvalidToken error is introduced for validation failures. Changes
Sequence DiagramsequenceDiagram
participant Caller
participant Dispatcher
participant Validator as Token Validator
participant Listener
Caller->>Dispatcher: DispatchRequest(req, DispatchRequestWithToken(token))
Dispatcher->>Validator: Read X-Gitlab-Token header
alt Token configured
alt Header present
Validator->>Validator: constant-time compare(header, token)
alt Match
Validator-->>Dispatcher: valid
Dispatcher->>Listener: invoke OnPush()
Listener-->>Dispatcher: handled
Dispatcher-->>Caller: success
else Mismatch
Validator-->>Dispatcher: ErrInvalidToken
Dispatcher-->>Caller: ErrInvalidToken
end
else Header missing
Validator-->>Dispatcher: ErrInvalidToken
Dispatcher-->>Caller: ErrInvalidToken
end
else No token configured
Dispatcher->>Listener: invoke OnPush()
Listener-->>Dispatcher: handled
Dispatcher-->>Caller: success
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
Summary of ChangesHello @flc1125, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a significant security enhancement by adding token validation for incoming GitLab webhook requests. It allows users to configure a secret token, which the dispatcher will then verify against the Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## v2.x #194 +/- ##
==========================================
- Coverage 94.73% 92.27% -2.47%
==========================================
Files 1 1
Lines 190 207 +17
==========================================
+ Hits 180 191 +11
- Misses 8 11 +3
- Partials 2 5 +3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Code Review
This pull request introduces a valuable feature for validating GitLab webhook requests using a secret token. The implementation is clear and is accompanied by a comprehensive set of tests covering various scenarios. My main feedback is a security concern regarding the token comparison method, which is susceptible to timing attacks. I've provided a suggestion to use a constant-time comparison on token hashes to mitigate this vulnerability.
dispatcher.go
Outdated
| if token != o.token { | ||
| return ErrInvalidToken | ||
| } |
There was a problem hiding this comment.
The direct string comparison token != o.token is vulnerable to timing attacks. An attacker could potentially deduce the secret token by measuring response time variations. For a secure comparison, you should use a constant-time comparison function. The recommended approach is to compare the SHA-256 hashes of the tokens, which ensures the comparison is always performed on fixed-length inputs, thus preventing length leakage.
Remember to add the necessary imports:
import (
"crypto/sha256"
"crypto/subtle"
) expectedTokenHash := sha256.Sum256([]byte(o.token))
receivedTokenHash := sha256.Sum256([]byte(token))
if subtle.ConstantTimeCompare(expectedTokenHash[:], receivedTokenHash[:]) != 1 {
return ErrInvalidToken
}There was a problem hiding this comment.
Pull Request Overview
This PR adds token validation support for webhook requests, allowing users to secure their GitLab webhooks by validating an authentication token sent in the request header.
- Adds
ErrInvalidTokenerror andDispatchRequestWithToken()option function - Implements token validation logic in
DispatchRequest()that checks theX-Gitlab-Tokenheader - Provides comprehensive test coverage for token validation scenarios including valid tokens, invalid tokens, missing tokens, and no validation
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| dispatcher.go | Adds token validation infrastructure including new error type, option function, and validation logic in request dispatch |
| dispatcher_test.go | Adds comprehensive test suite with 4 test cases covering various token validation scenarios |
| README.md | Updates documentation to showcase the new token validation feature with usage example |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // check token if provided | ||
| if o.token != "" { | ||
| token := req.Header.Get("X-Gitlab-Token") | ||
| if token != o.token { | ||
| return ErrInvalidToken | ||
| } | ||
| } |
There was a problem hiding this comment.
The token comparison uses a direct string equality check (token != o.token), which is vulnerable to timing attacks. An attacker could use timing differences to gradually guess the correct token byte by byte.
Use crypto/subtle.ConstantTimeCompare() for secure token comparison:
import "crypto/subtle"
// check token if provided
if o.token != "" {
token := req.Header.Get("X-Gitlab-Token")
if subtle.ConstantTimeCompare([]byte(token), []byte(o.token)) != 1 {
return ErrInvalidToken
}
}There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
README.md (1)
91-91: Good example, but fix the tab formatting.The example clearly demonstrates the token validation feature. However, the line uses hard tabs instead of spaces, which violates markdown best practices.
Apply this diff to fix the formatting:
- gitlabwebhook.DispatchRequestWithToken("your-secret-token"), // validate token, if needed + gitlabwebhook.DispatchRequestWithToken("your-secret-token"), // validate token, if neededNote: Replace the leading tab with two additional tabs (to match the existing indentation level using tabs consistently with the rest of the file) or convert the entire file to use spaces.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
README.md(2 hunks)dispatcher.go(3 hunks)dispatcher_test.go(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
dispatcher_test.go (2)
dispatcher.go (5)
NewDispatcher(48-54)RegisterListeners(42-46)ErrInvalidToken(15-15)DispatchRequestOption(270-270)DispatchRequestWithToken(278-282)listeners.go (1)
PushListener(61-63)
🪛 markdownlint-cli2 (0.18.1)
README.md
91-91: Hard tabs
Column: 1
(MD010, no-hard-tabs)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Agent
- GitHub Check: CodeQL analysis (go)
- GitHub Check: go test (1.25.x, windows-latest)
🔇 Additional comments (5)
dispatcher.go (2)
13-16: LGTM! Clean error declaration.Converting to a var block for multiple error variables is idiomatic Go, and the new
ErrInvalidTokenfollows the established naming and message format.
278-282: LGTM! Consistent option pattern.The function follows the established functional options pattern used elsewhere in the codebase (e.g.,
DispatchRequestWithContext).README.md (1)
20-20: LGTM! Clear feature documentation.The new feature is well-documented and follows the established format with consistent emoji usage.
dispatcher_test.go (2)
232-309: LGTM! Comprehensive test coverage.The test thoroughly covers all token validation scenarios:
- Valid token dispatch path
- Invalid token rejection
- Missing token header rejection
- Optional validation when no token configured
The table-driven structure is clean, and the assertions correctly verify both error conditions and listener invocation state.
311-320: LGTM! Clean test helper.The
simpleTestListenerprovides a minimal, focused test double for verifying dispatch behavior in token validation tests. The implementation is appropriately simple and separate from the more comprehensivetestListenerused elsewhere.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
dispatcher.go (1)
285-310: Consider rate limiting for failed token attempts.While the token validation implementation is secure, consider adding rate limiting at the application or infrastructure level to prevent brute-force attacks on the webhook endpoint. This is particularly important since failed validation attempts could be used to guess valid tokens over time.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
dispatcher.go(4 hunks)
🔇 Additional comments (5)
dispatcher.go (5)
5-5: LGTM! Correct import for secure token comparison.The
crypto/subtleimport is properly added to support constant-time comparison for token validation.
14-17: LGTM! Clean error declarations.The error grouping follows Go conventions, and the new
ErrInvalidTokenis properly exported for callers to handle token validation failures.
266-269: LGTM! Clean struct extension.The
tokenfield addition follows the existing pattern for dispatch request options.
279-283: LGTM! Follows established patterns.The new option constructor follows the same functional options pattern as
DispatchRequestWithContext, maintaining API consistency.
293-300: LGTM! Timing attack vulnerability addressed.The token validation correctly uses
subtle.ConstantTimeCompareto prevent timing attacks, addressing the concerns raised in previous reviews. The logic properly validates theX-Gitlab-Tokenheader only when a token is configured.
Summary by CodeRabbit
New Features
Documentation
Tests