feat: Prevent webhook url takeover (#14783)

This commit is contained in:
Michael Kret
2025-04-28 14:29:32 +03:00
committed by GitHub
parent bc6f98928e
commit be53453def
13 changed files with 407 additions and 7 deletions

View File

@@ -7,11 +7,19 @@ import type { VNode } from 'vue';
import { computed, h, watch } from 'vue';
import { useI18n } from '@/composables/useI18n';
import type { PermissionsRecord } from '@/permissions';
import { EXECUTE_WORKFLOW_TRIGGER_NODE_TYPE, PLACEHOLDER_EMPTY_WORKFLOW_ID } from '@/constants';
import {
WORKFLOW_ACTIVATION_CONFLICTING_WEBHOOK_MODAL_KEY,
EXECUTE_WORKFLOW_TRIGGER_NODE_TYPE,
PLACEHOLDER_EMPTY_WORKFLOW_ID,
} from '@/constants';
import WorkflowActivationErrorMessage from './WorkflowActivationErrorMessage.vue';
import { useCredentialsStore } from '@/stores/credentials.store';
import type { INodeUi, IUsedCredential } from '@/Interface';
import { OPEN_AI_API_CREDENTIAL_TYPE } from 'n8n-workflow';
import { useUIStore } from '@/stores/ui.store';
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
import { useRouter } from 'vue-router';
const props = defineProps<{
workflowActive: boolean;
@@ -26,6 +34,11 @@ const emit = defineEmits<{
const { showMessage } = useToast();
const workflowActivate = useWorkflowActivate();
const uiStore = useUIStore();
const router = useRouter();
const workflowHelpers = useWorkflowHelpers({ router });
const i18n = useI18n();
const workflowsStore = useWorkflowsStore();
const credentialsStore = useCredentialsStore();
@@ -47,9 +60,12 @@ const isCurrentWorkflow = computed((): boolean => {
return workflowsStore.workflowId === props.workflowId;
});
const foundTriggers = computed(() =>
getActivatableTriggerNodes(workflowsStore.workflowTriggerNodes),
);
const containsTrigger = computed((): boolean => {
const foundTriggers = getActivatableTriggerNodes(workflowsStore.workflowTriggerNodes);
return foundTriggers.length > 0;
return foundTriggers.value.length > 0;
});
const containsOnlyExecuteWorkflowTrigger = computed((): boolean => {
@@ -114,10 +130,31 @@ const shouldShowFreeAiCreditsWarning = computed((): boolean => {
});
async function activeChanged(newActiveState: boolean) {
if (!isWorkflowActive.value) {
const conflictData = await workflowHelpers.checkConflictingWebhooks(props.workflowId);
if (conflictData) {
const { trigger, conflict } = conflictData;
const conflictingWorkflow = await workflowsStore.fetchWorkflow(conflict.workflowId);
uiStore.openModalWithData({
name: WORKFLOW_ACTIVATION_CONFLICTING_WEBHOOK_MODAL_KEY,
data: {
triggerName: trigger.name,
workflowName: conflictingWorkflow.name,
...conflict,
},
});
return;
}
}
const newState = await workflowActivate.updateWorkflowActivation(
props.workflowId,
newActiveState,
);
emit('update:workflowActive', { id: props.workflowId, active: newState });
}