nuxt-webhook-validators
Advanced tools
| import { type H3Event } from 'h3'; | ||
| /** | ||
| * Validates Brevo webhooks on the Edge | ||
| * @see {@link https://help.brevo.com/hc/en-us/articles/27824932835474} | ||
| * @param event H3Event | ||
| * @returns {boolean} `true` if the webhook is valid, `false` otherwise | ||
| */ | ||
| export declare const isValidBrevoWebhook: (event: H3Event) => Promise<boolean>; |
| import { getRequestHeader, getRequestIP } from "h3"; | ||
| import { useRuntimeConfig } from "#imports"; | ||
| const ALLOWED_IP_RANGES = ["1.179.112.0/20", "172.246.240.0/20"]; | ||
| const ipToInt = (ip) => { | ||
| return ip.split(".").reduce((acc, octet) => (acc << 8) + Number(octet), 0); | ||
| }; | ||
| const isIpInRange = (ip, cidr) => { | ||
| const [range, bits] = cidr.split("/"); | ||
| if (!range || !bits) return false; | ||
| const mask = ~(2 ** (32 - Number(bits)) - 1); | ||
| return (ipToInt(ip) & mask) === (ipToInt(range) & mask); | ||
| }; | ||
| export const isValidBrevoWebhook = async (event) => { | ||
| const ip = getRequestIP(event, { xForwardedFor: true }); | ||
| if (!ip || !ALLOWED_IP_RANGES.some((cidr) => isIpInRange(ip, cidr))) return false; | ||
| const config = useRuntimeConfig(event).webhook.brevo; | ||
| if (config.token) { | ||
| const authorization = getRequestHeader(event, "authorization") || ""; | ||
| if (!authorization.toLowerCase().startsWith("bearer ")) return false; | ||
| const token = authorization.slice(7); | ||
| if (token !== config.token) return false; | ||
| } | ||
| return true; | ||
| }; |
+1
-1
@@ -7,3 +7,3 @@ { | ||
| }, | ||
| "version": "0.2.4", | ||
| "version": "0.2.5", | ||
| "builder": { | ||
@@ -10,0 +10,0 @@ "@nuxt/module-builder": "1.0.2", |
+3
-0
@@ -18,2 +18,5 @@ import { defineNuxtModule, createResolver, addServerImportsDir } from '@nuxt/kit'; | ||
| runtimeConfig.webhook = defu(runtimeConfig.webhook, {}); | ||
| runtimeConfig.webhook.brevo = defu(runtimeConfig.webhook.brevo, { | ||
| token: "" | ||
| }); | ||
| runtimeConfig.webhook.discord = defu(runtimeConfig.webhook.discord, { | ||
@@ -20,0 +23,0 @@ publicKey: "" |
+2
-2
| { | ||
| "name": "nuxt-webhook-validators", | ||
| "version": "0.2.4", | ||
| "version": "0.2.5", | ||
| "description": "A simple nuxt module that works on the edge to easily validate incoming webhooks from different services.", | ||
@@ -49,3 +49,3 @@ "keywords": [ | ||
| "vitest": "^3.2.4", | ||
| "vue-tsc": "^3.0.7" | ||
| "vue-tsc": "^3.0.8" | ||
| }, | ||
@@ -52,0 +52,0 @@ "scripts": { |
+2
-1
@@ -17,3 +17,3 @@  | ||
| - 19 [Webhook validators](#supported-webhook-validators) | ||
| - 20 [Webhook validators](#supported-webhook-validators) | ||
| - Works on the edge | ||
@@ -82,2 +82,3 @@ - Exposed [Server utils](#server-utils) | ||
| - Brevo | ||
| - Discord | ||
@@ -84,0 +85,0 @@ - Dropbox |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
42259
3.58%49
4.26%782
4.69%168
0.6%