-
Notifications
You must be signed in to change notification settings - Fork 8.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: Add spam checking for workflow bodies #18822
base: main
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 2 Skipped Deployments
|
import prisma from "@calcom/prisma"; | ||
|
||
export const scanWorkflowBodySchema = z.object({ | ||
userId: z.number(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need the userId to know which user to lock. This comes from the context of the workflow update tRPC endpoint.
const client = new AkismetClient({ key: process.env.AKISMET_API_KEY, blog: WEBAPP_URL }); | ||
|
||
const comment: Comment = { | ||
user_ip: "127.0.0.1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment needs an IP. From Akismet support we can just use this.
IP is used for scanning against know abuse IPs and adding a reputation score.
Graphite Automations"Add consumer team as reviewer" took an action on this PR • (01/23/25)1 reviewer was added to this PR based on Keith Williams's automation. "Add foundation team as reviewer" took an action on this PR • (01/23/25)1 reviewer was added to this PR based on Keith Williams's automation. |
const isSpam = await client.checkSpam(comment); | ||
|
||
if (isSpam) { | ||
// We won't delete the workflow step incase it is flagged as a false positive |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call on not deleting the step in the case of a false positive @Udit-takkar
-- AlterTable | ||
ALTER TABLE "WorkflowStep" ADD COLUMN "safe" BOOLEAN NOT NULL DEFAULT false; | ||
|
||
-- Update existing records to set safe to true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@emrysal does this look correct?
@@ -22,6 +22,7 @@ export const workflowSelect = { | |||
sender: true, | |||
includeCalendarEvent: true, | |||
numberRequired: true, | |||
safe: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add the safe
property when fetching workflow steps
@@ -54,6 +54,8 @@ const processWorkflowStep = async ( | |||
seatReferenceUid, | |||
}: ProcessWorkflowStepParams | |||
) => { | |||
if (!step.safe) return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before processing the step, see if it is marked as safe
|
||
export const scanWorkflowBodySchema = z.object({ | ||
userId: z.number(), | ||
workflowStepIds: z.array(z.number()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since scheduleWorkflowNotifications
expects multiple steps we now accept multiple steps in the task
@@ -269,29 +270,29 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => { | |||
isOrg, | |||
}); | |||
|
|||
await scheduleWorkflowNotifications( | |||
await scheduleWorkflowNotifications({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scheduleWorkflowNotifications
is refactored to accept an object for better readability.
@@ -337,7 +338,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => { | |||
id: oldStep.id, | |||
}, | |||
}); | |||
} else if (isStepEdited(oldStep, newStep)) { | |||
} else if (isStepEdited(oldStep, { ...newStep, safe: false })) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type fix, expects the safe
property
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be safe: oldStep.safe
? 🤔 Because otherwise if the oldStep is safe, isStepEdited
would always be true because of the different value in the safe field
@@ -398,20 +399,24 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => { | |||
}, | |||
}); | |||
|
|||
if (SCANNING_WORKFLOW_STEPS && newStep.reminderBody !== oldStep.reminderBody) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only send to scan the body if it's been updated
data: { | ||
...step, | ||
numberVerificationPending: false, | ||
...(!SCANNING_WORKFLOW_STEPS ? { safe: true } : {}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default to safe = true
if a self-hoster isn't planning on scanning workflows
E2E results are ready! |
@@ -337,7 +338,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => { | |||
id: oldStep.id, | |||
}, | |||
}); | |||
} else if (isStepEdited(oldStep, newStep)) { | |||
} else if (isStepEdited(oldStep, { ...newStep, safe: false })) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be safe: oldStep.safe
? 🤔 Because otherwise if the oldStep is safe, isStepEdited
would always be true because of the different value in the safe field
workflowSteps, | ||
time: workflow?.time || null, | ||
timeUnit: workflow?.timeUnit || null, | ||
trigger: WorkflowTriggerEvents.AFTER_EVENT, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trigger: WorkflowTriggerEvents.AFTER_EVENT, | |
trigger: workflow.trigger, |
Should be like that I think
@@ -395,23 +398,28 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => { | |||
sender: newStep.sender, | |||
numberVerificationPending: false, | |||
includeCalendarEvent: newStep.includeCalendarEvent, | |||
...(SCANNING_WORKFLOW_STEPS && didBodyChange ? { safe: true } : {}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@CarinaWolli thoughts here? Only if the body has changed we should remark the step as unsafe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh wait, why true
here and not false
?
New, updated, and removed dependencies detected. Learn more about Socket for GitHub ↗︎
🚮 Removed packages: npm/[email protected], npm/[email protected] |
🚨 Potential security issues detected. Learn more about Socket for GitHub ↗︎ To accept the risk, merge this PR and you will not be notified again.
Next stepsWhat is a typosquat?Package name is similar to other popular packages and may not be the package you want. Use care when consuming similarly named packages and ensure that you did not intend to consume a different package. Malicious packages often publish using similar names as existing popular packages. Take a deeper look at the dependencyTake a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support [AT] socket [DOT] dev. Remove the packageIf you happen to install a dependency that Socket reports as Known Malware you should immediately remove it and select a different dependency. For other alert types, you may may wish to investigate alternative packages or consider if there are other ways to mitigate the specific risk posed by the dependency. Mark a package as acceptable riskTo ignore an alert, reply with a comment starting with
|
reviewing |
What does this PR do?
Adds a background task to scan workflow bodies for spam and auto locking the user is detected
Mandatory Tasks (DO NOT REMOVE)
How should this be tested?
AKISMET_API_KEY
.env variable