Storage: Consider not storing the plain-text secret after initial display. Show it once on creation, then only store the hash. The user can regenerate if lost.
UI: Add a "show/hide" toggle rather than displaying the full URL by default.
## Severity: MEDIUM
## Files
- `internal/handlers/app.go` line 130: `webhookURL := "https://" + request.Host + "/webhook/" + application.WebhookSecret`
- `templates/app_detail.html`: displays full webhook URL with secret
- `internal/middleware/middleware.go` (Logging middleware): logs full URL including webhook secret on every request
## Description
The webhook secret is embedded directly in the URL path (`/webhook/{secret}`) and:
1. **Displayed in plain text** in the app detail page UI, copyable to clipboard
2. **Logged in full** by the request logging middleware on every webhook invocation
3. **Stored in plain text** in the database (the `webhook_secret` column), alongside the hash
While the hash-based lookup is good (avoids timing attacks), the plain-text secret is still stored and logged.
## Suggested Fix
1. **Logging**: Redact the secret from logged URLs. The logging middleware should mask `/webhook/*` paths:
```go
url := request.URL.String()
if strings.HasPrefix(url, "/webhook/") {
url = "/webhook/[REDACTED]"
}
```
2. **Storage**: Consider not storing the plain-text secret after initial display. Show it once on creation, then only store the hash. The user can regenerate if lost.
3. **UI**: Add a "show/hide" toggle rather than displaying the full URL by default.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Severity: MEDIUM
Files
internal/handlers/app.goline 130:webhookURL := "https://" + request.Host + "/webhook/" + application.WebhookSecrettemplates/app_detail.html: displays full webhook URL with secretinternal/middleware/middleware.go(Logging middleware): logs full URL including webhook secret on every requestDescription
The webhook secret is embedded directly in the URL path (
/webhook/{secret}) and:webhook_secretcolumn), alongside the hashWhile the hash-based lookup is good (avoids timing attacks), the plain-text secret is still stored and logged.
Suggested Fix
/webhook/*paths: