From 056a1979d2adee2bf3e27cad7dd49138cf4f32c0 Mon Sep 17 00:00:00 2001 From: TheRealToxicDev Date: Sat, 9 May 2026 13:20:04 -0600 Subject: [PATCH 1/2] fixed stuff --- .github/workflows/docker-publish.yml | 38 ++++------ .../service/notification-provider-service.ts | 70 ++++++++++++++----- 2 files changed, 65 insertions(+), 43 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index fb0a9e9..c28fb51 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -56,9 +56,6 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 - - name: Login to GitHub Container Registry uses: docker/login-action@v4 with: @@ -141,6 +138,9 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GH_TOKEN }} + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + - name: Create and push DockerHub manifest run: | GIT_SHA="$(git rev-parse HEAD)" @@ -163,17 +163,11 @@ jobs: for APP_NAME in bytesend smtp-proxy; do for TAG in $TAGS; do - # Remove remote tags/manifests first so reruns are idempotent. - docker buildx imagetools rm bytesend/$APP_NAME:$TAG 2>/dev/null || true - docker buildx imagetools rm bytesend/$APP_NAME-amd64:$TAG 2>/dev/null || true - docker buildx imagetools rm bytesend/$APP_NAME-arm64:$TAG 2>/dev/null || true - - docker manifest create \ - bytesend/$APP_NAME:$TAG \ - --amend bytesend/$APP_NAME-amd64:$TAG \ - --amend bytesend/$APP_NAME-arm64:$TAG - - docker manifest push bytesend/$APP_NAME:$TAG + # buildx imagetools create is idempotent and updates the target tag in-place. + docker buildx imagetools create \ + --tag bytesend/$APP_NAME:$TAG \ + bytesend/$APP_NAME-amd64:$TAG \ + bytesend/$APP_NAME-arm64:$TAG done done @@ -199,16 +193,10 @@ jobs: for APP_NAME in bytesend smtp-proxy; do for TAG in $TAGS; do - # Remove remote tags/manifests first so reruns are idempotent. - docker buildx imagetools rm ghcr.io/bytesend/$APP_NAME:$TAG 2>/dev/null || true - docker buildx imagetools rm ghcr.io/bytesend/$APP_NAME-amd64:$TAG 2>/dev/null || true - docker buildx imagetools rm ghcr.io/bytesend/$APP_NAME-arm64:$TAG 2>/dev/null || true - - docker manifest create \ - ghcr.io/bytesend/$APP_NAME:$TAG \ - --amend ghcr.io/bytesend/$APP_NAME-amd64:$TAG \ - --amend ghcr.io/bytesend/$APP_NAME-arm64:$TAG - - docker manifest push ghcr.io/bytesend/$APP_NAME:$TAG + # buildx imagetools create is idempotent and updates the target tag in-place. + docker buildx imagetools create \ + --tag ghcr.io/bytesend/$APP_NAME:$TAG \ + ghcr.io/bytesend/$APP_NAME-amd64:$TAG \ + ghcr.io/bytesend/$APP_NAME-arm64:$TAG done done diff --git a/apps/web/src/server/service/notification-provider-service.ts b/apps/web/src/server/service/notification-provider-service.ts index 25358e4..3360c7c 100644 --- a/apps/web/src/server/service/notification-provider-service.ts +++ b/apps/web/src/server/service/notification-provider-service.ts @@ -621,12 +621,10 @@ export class NotificationProviderService { "Discord webhook URL is required" ); } - if (!config.webhookUrl.includes("discord.com")) { - throw new ByteSendApiError( - "BAD_REQUEST", - "Invalid Discord webhook URL" - ); - } + this.assertAllowedWebhookUrl(config.webhookUrl, "Discord", [ + "discord.com", + "discordapp.com", + ]); break; case "SLACK": @@ -636,12 +634,9 @@ export class NotificationProviderService { "Slack webhook URL is required" ); } - if (!config.webhookUrl.includes("hooks.slack.com")) { - throw new ByteSendApiError( - "BAD_REQUEST", - "Invalid Slack webhook URL" - ); - } + this.assertAllowedWebhookUrl(config.webhookUrl, "Slack", [ + "hooks.slack.com", + ]); break; case "MICROSOFT_TEAMS": @@ -651,12 +646,11 @@ export class NotificationProviderService { "Microsoft Teams webhook URL is required" ); } - if (!config.webhookUrl.includes("outlook.webhook.office.com")) { - throw new ByteSendApiError( - "BAD_REQUEST", - "Invalid Microsoft Teams webhook URL" - ); - } + this.assertAllowedWebhookUrl(config.webhookUrl, "Microsoft Teams", [ + "outlook.webhook.office.com", + "webhook.office.com", + "outlook.office.com", + ]); break; case "TELEGRAM": @@ -684,4 +678,44 @@ export class NotificationProviderService { break; } } + + private static assertAllowedWebhookUrl( + rawUrl: string, + providerName: string, + allowedHostnames: string[] + ) { + let parsedUrl: URL; + + try { + parsedUrl = new URL(rawUrl); + } catch { + throw new ByteSendApiError( + "BAD_REQUEST", + `${providerName} webhook URL is invalid` + ); + } + + if (parsedUrl.protocol !== "https:") { + throw new ByteSendApiError( + "BAD_REQUEST", + `${providerName} webhook URL must use HTTPS` + ); + } + + const hostname = parsedUrl.hostname.toLowerCase(); + const isAllowed = allowedHostnames.some((allowedHostname) => { + const normalizedAllowed = allowedHostname.toLowerCase(); + return ( + hostname === normalizedAllowed || + hostname.endsWith(`.${normalizedAllowed}`) + ); + }); + + if (!isAllowed) { + throw new ByteSendApiError( + "BAD_REQUEST", + `Invalid ${providerName} webhook URL` + ); + } + } } From 8dc19540f911035444398b6e75da24d9d0bdd98e Mon Sep 17 00:00:00 2001 From: TheRealToxicDev Date: Sat, 9 May 2026 13:40:42 -0600 Subject: [PATCH 2/2] fix docs styling --- apps/docs/docs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/docs/docs.json b/apps/docs/docs.json index daad292..9345988 100644 --- a/apps/docs/docs.json +++ b/apps/docs/docs.json @@ -10,7 +10,7 @@ "background": { "color": { "light": "#F8F9FB", - "dark": "#0A0E1A" + "dark": "#0A0A0A" } }, "fonts": {