Skip to content

Enable and test Gotify and Custom Webhook notifications#754

Merged
Wikid82 merged 100 commits intodevelopmentfrom
feature/beta-release
Feb 27, 2026
Merged

Enable and test Gotify and Custom Webhook notifications#754
Wikid82 merged 100 commits intodevelopmentfrom
feature/beta-release

Conversation

@Wikid82
Copy link
Owner

@Wikid82 Wikid82 commented Feb 23, 2026

Primary goals:

  1. Enable a unified wrapper path for outbound provider dispatch.
  2. Make Gotify token handling write-only and non-leaking by contract.
  3. Add explicit SSRF/redirect/rebinding protections.
  4. Add strict error leakage controls for preview/test paths.
  5. Add wrapper transport guardrails and expanded validation tests.

renovate bot and others added 2 commits February 23, 2026 21:17
…n-major-updates

chore(deps): update actions/download-artifact digest to 70fc10c (feature/beta-release)
@Wikid82 Wikid82 self-assigned this Feb 23, 2026
@Wikid82 Wikid82 added frontend UI/UX code feature New functionality monitoring Logging and statistics manual-testing labels Feb 23, 2026
@Wikid82 Wikid82 added this to Charon Feb 23, 2026
@github-project-automation github-project-automation bot moved this to Backlog in Charon Feb 23, 2026
@Wikid82 Wikid82 moved this from Backlog to In Progress in Charon Feb 23, 2026
@github-advanced-security
Copy link

This pull request sets up GitHub code scanning for this repository. Once the scans have completed and the checks have passed, the analysis results for this pull request branch will appear on this overview. Once you merge this pull request, the 'Security' tab will show more code scanning analysis results (for example, for the default branch). Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results. For more information about GitHub code scanning, check out the documentation.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 23, 2026

✅ Supply Chain Verification Results

PASSED

📦 SBOM Summary

  • Components: 1670

🔍 Vulnerability Scan

Severity Count
🔴 Critical 0
🟠 High 0
🟡 Medium 11
🟢 Low 5
Total 16

📎 Artifacts

  • SBOM (CycloneDX JSON) and Grype results available in workflow artifacts

Generated by Supply Chain Verification workflow • View Details

…load validation

- Enhanced Notifications component tests to include support for Discord, Gotify, and Webhook provider types.
- Updated test cases to validate the correct handling of provider type options and ensure proper payload structure during creation, preview, and testing.
- Introduced new tests for Gotify token handling and ensured sensitive information is not exposed in the UI.
- Refactored existing tests for clarity and maintainability, including improved assertions and error handling.
- Added comprehensive coverage for payload validation scenarios, including malformed requests and security checks against SSRF and oversized payloads.
actions-user and others added 14 commits February 26, 2026 14:01
…cumentation

- Updated tools for Doc_Writer, Frontend_Dev, Management, Planning, Playwright_Dev, QA_Security, and Supervisor agents to enhance terminal command execution capabilities and streamline operations.
- Removed redundant tools and ensured uniformity in tool listings across agents.
@Wikid82 Wikid82 marked this pull request as ready for review February 27, 2026 03:24
Copilot AI review requested due to automatic review settings February 27, 2026 03:24
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enables Gotify and Custom Webhook notification providers with comprehensive security hardening. The changes focus on write-only token handling, SSRF protections, error message sanitization, and expanded test coverage.

Changes:

  • Added support for Gotify and Custom Webhook notification providers with HTTP wrapper delivery
  • Implemented write-only token handling and masked API responses for sensitive fields (API keys, invite tokens, Gotify tokens)
  • Enhanced security controls including authenticated admin checks, sensitive setting masking, and secure cookie handling
  • Increased coverage thresholds from 85% to 87% for both backend and frontend
  • Improved Docker socket access documentation and troubleshooting guidance
  • Added comprehensive test coverage for new features and security improvements

Reviewed changes

Copilot reviewed 164 out of 167 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
frontend/src/api/notifications.test.ts Updated to support gotify/webhook types with token payload contract enforcement
frontend/src/api/user.ts Changed API key response to masked format with metadata
frontend/src/pages/Account.tsx Removed copy button for API keys, now displays masked value only
backend/internal/api/handlers/settings_handler.go Added sensitive setting masking logic and admin-only SMTP config access
backend/internal/api/handlers/permission_helpers.go Added requireAuthenticatedAdmin helper for stricter auth checks
backend/internal/api/handlers/auth_handler.go Improved cookie security with Secure=true by default, exception only for local loopback
backend/internal/api/handlers/docker_handler.go Enhanced error messages with supplemental group guidance
backend/internal/notifications/router.go Added webhook service flag support
backend/internal/models/notification_provider.go Added HasToken computed field for safe token presence indication
scripts/*-test-coverage.sh Increased coverage threshold to 87%
docs/getting-started.md Added Docker socket access guidance
.github/workflows/quality-checks.yml Added auth route protection contract test job
Files not reviewed (1)
  • frontend/package-lock.json: Language not supported

Comment on lines 132 to 145
func setSecureCookie(c *gin.Context, name, value string, maxAge int) {
scheme := requestScheme(c)
secure := scheme == "https"
secure := true
sameSite := http.SameSiteStrictMode
if scheme != "https" {
sameSite = http.SameSiteLaxMode
if isLocalRequest(c) {
secure = false
}
}

if isLocalRequest(c) {
secure = false
sameSite = http.SameSiteLaxMode
}
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cookie security logic has been updated to set Secure=true by default, with an exception only for local loopback HTTP requests. This is a security improvement. However, verify that the loopback detection logic (isLocalRequest) correctly identifies all legitimate local development scenarios to prevent breaking local development workflows.

Copilot uses AI. Check for mistakes.
Comment on lines +94 to +113
func isSensitiveSettingKey(key string) bool {
normalizedKey := strings.ToLower(strings.TrimSpace(key))

sensitiveFragments := []string{
"password",
"secret",
"token",
"api_key",
"apikey",
"webhook",
}

for _, fragment := range sensitiveFragments {
if strings.Contains(normalizedKey, fragment) {
return true
}
}

return false
}
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The settings handler now masks sensitive values using fragment-based detection. The isSensitiveSettingKey function checks for keywords like "password", "secret", "token", etc. This is a good security improvement, but consider using a whitelist approach instead of blacklist for more robust security. Also, the function should be case-insensitive for the comparison, which it already does, but ensure all variations are covered (e.g., "api-key" with hyphens).

Copilot uses AI. Check for mistakes.
Comment on lines +27 to +36
func requireAuthenticatedAdmin(c *gin.Context) bool {
if _, exists := c.Get("userID"); !exists {
c.JSON(http.StatusUnauthorized, gin.H{
"error": "Authorization header required",
})
return false
}

return requireAdmin(c)
}
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The requireAuthenticatedAdmin helper has been added and is now used in import handler endpoints. This is a security improvement that ensures unauthenticated requests are rejected with 401 before checking admin role. Verify that all sensitive endpoints use this helper instead of just requireAdmin to prevent information disclosure to unauthenticated users.

Copilot uses AI. Check for mistakes.
Comment on lines +74 to 82
details := unavailableErr.Details()
if details == "" {
details = "Cannot connect to Docker. Please ensure Docker is running and the socket is accessible (e.g., /var/run/docker.sock is mounted)."
}
log.WithFields(map[string]any{"server_id": util.SanitizeForLog(serverID), "host": util.SanitizeForLog(host), "error": util.SanitizeForLog(err.Error())}).Warn("docker unavailable")
c.JSON(http.StatusServiceUnavailable, gin.H{
"error": "Docker daemon unavailable",
"details": "Cannot connect to Docker. Please ensure Docker is running and the socket is accessible (e.g., /var/run/docker.sock is mounted).",
"details": details,
})
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Docker handler now uses the Details() method from DockerUnavailableError to provide more informative error messages, including supplemental group guidance. Ensure that the Details() method never leaks sensitive information like file paths, environment variables, or internal system details that could aid attackers.

Copilot uses AI. Check for mistakes.
Type string `json:"type" gorm:"index"` // discord (only supported type in current rollout)
URL string `json:"url"` // Discord webhook URL (HTTPS format required)
Token string `json:"-"` // Auth token for providers (e.g., Gotify) - never exposed in API
HasToken bool `json:"has_token" gorm:"-"` // Computed: indicates whether a token is set (never exposes raw value)
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The notification provider model now includes a HasToken field with gorm:"-" tag, indicating it's not persisted to the database. This is good for preventing token exposure in API responses. However, ensure that this field is properly populated in the service layer before returning to the API, and that the actual Token field remains write-only with json:"-" tag as intended.

Copilot uses AI. Check for mistakes.
@Wikid82 Wikid82 merged commit 117fd51 into development Feb 27, 2026
42 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Done in Charon Feb 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New functionality frontend UI/UX code manual-testing monitoring Logging and statistics

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants