How Cal.com Rebuilt AppSec After Going Closed Source
How Cal.com consolidated noisy security tooling into one continuous, context-aware pull request security program with Gecko.
Gecko Security
An authentication bypass in the StripeTrigger node allows any party who knows the webhook URL to forge arbitrary Stripe webhooks without knowing the Stripe webhook signing secret.
The node stores the Stripe webhook secret when creating the webhook endpoint, but the webhook() handler never verifies the Stripe-Signature header or the request body. It only checks that the type field of the incoming JSON matches one of the configured event types, then passes the entire unverified body directly into the workflow.
In contrast, other n8n webhook triggers like Slack, WooCommerce, and HelpScout verify provider signatures/HMAC over the raw request body and reject on mismatch. StripeTrigger stores the secret but performs no verification.
This design means that any unauthenticated HTTP client (not just Stripe) can send POST requests to the publicly exposed webhook URL and cause workflows to execute as if a legitimate Stripe event occurred, enabling payment forgery, subscription manipulation and other downstream attacks depending on how workflows are built.
The StripeTrigger webhook handler never checks that incoming requests really come from Stripe.
In StripeTrigger.node.ts, the webhook() function:
bodyData.type matches one of the configured event typesreq.body into the workflowWhat it does NOT do:
Stripe-Signature headerThe create method stores the Stripe webhook secret when the endpoint is created, but that value is never used in webhook().
Comparison with secure implementations: Other trigger nodes (like WooCommerce and HelpScout) correctly compute an HMAC of req.rawBody with their secret and compare it to the provider’s signature header, rejecting invalid or missing signatures. Because StripeTrigger skips this step entirely, any attacker who knows the webhook URL can send a plain HTTP POST with a JSON body that has a matching type (e.g. payment_intent.succeeded), and n8n will treat it as a genuine Stripe event.
On a deployed n8n cloud tenant (e.g. https://<tenant>.app.n8n.cloud):
1. Create new workflow in n8n cloud workspace
2. Add a Stripe Trigger node:
payment_intent.succeeded (or *)3. Activate the workflow
4. Run the following with the Production Webhook URL:
<code class="hljs language-bash">WEBHOOK_URL=<span class="hljs-string">"https://<tenant>.app.n8n.cloud/webhook/<uuid>/webhook"</span>
<span class="hljs-comment"># Forged Stripe webhook with a fake signature</span>
curl -v -X POST <span class="hljs-string">"<span class="hljs-variable">$WEBHOOK_URL</span>"</span> \
-H <span class="hljs-string">"Content-Type: application/json"</span> \
-H <span class="hljs-string">"Stripe-Signature: FORGED"</span> \
-d <span class="hljs-string">'{
"type": "payment_intent.succeeded",
"data": {
"object": {
"id": "pi_FORGED",
"amount": 999999,
"currency": "usd",
"status": "succeeded"
}
}
}'</span>
</code>5. Observe the result:
200 OKStripe-Signature is invalid and the IDs are fabricatedThis is an authentication bypass on the Stripe webhook endpoint: any attacker who learns the StripeTrigger webhook URL for a given n8n workflow (including on *.app.n8n.cloud tenants) can trigger that workflow by sending arbitrary JSON that has a matching type field, without knowing the Stripe webhook signing secret.
All n8n users who use the StripeTrigger node in active workflows are impacted, because those workflows will trust and act on forged payment or subscription events as if they came from Stripe.
In practice this can be abused to:

Artemiy Malyshau
Co-founder & CTO
Artemiy served in an elite unit of the Austrian Cyber Forces, defending national infrastructure He was then the first employee at a government-backed cybersecurity research group, where he led security projects for Interpol and national governments. At Gecko he builds the platform trusted to sit inside Fortune 500 codebases, and holds it to the standard those governments taught him.
The latest news, technologies, and resources from our team.
How Cal.com consolidated noisy security tooling into one continuous, context-aware pull request security program with Gecko.
Gecko Security
Authorization bypass in n8n’s dynamic-credentials OAuth endpoints allows any authenticated user to operate on another user’s OAuth credential by supplying its ID, enabling unauthorized OAuth rebinding and revocation.
Artemiy Malyshau
An IDOR vulnerability in n8n’s public variables API allows authenticated users to read project variables outside their authorized scope, exposing secrets across project boundaries.
Artemiy Malyshau
Learn API scanning for automated security testing. Find vulnerabilities from broken authentication to business logic flaws in your endpoints.
Artemiy Malyshau
A complete guide to automated pentest tools and best practices. Learn what works, what doesn’t, and how to implement continuous security testing.
Artemiy Malyshau
Compare the best AI-powered application security testing tools. Find which tools detect business logic flaws and broken access control.
Artemiy Malyshau
Occasional updates, new content, and insights. No spam; unsubscribe anytime.