AutomationFlowsAI & RAG › Orchestrate Security Vulnerability Remediation with Port, Openai, Jira and Slack

Orchestrate Security Vulnerability Remediation with Port, Openai, Jira and Slack

ByPort IO @portio on n8n.io

Complete security workflow from vulnerability detection to automated remediation, with severity-based routing and full organizational context from Port's catalog. This template provides end-to-end lifecycle management including automatic Jira ticket creation with appropriate…

Webhook trigger★★★★☆ complexityAI-powered16 nodesCustomOpenAIJiraHTTP RequestSlack
AI & RAG Trigger: Webhook Nodes: 16 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #11726 — we link there as the canonical source.

This workflow follows the HTTP Request → OpenAI recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "f2ZfY7xKhYArVH4V",
  "name": "Remediate security vulnerabilities with n8n and Port",
  "tags": [],
  "nodes": [
    {
      "id": "6ec161d3-a66e-4229-ae19-e705eeb248b6",
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -1744,
        320
      ],
      "parameters": {
        "path": "security/vulnerability",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 1,
      "webhookDescription": "Triggered when a new vulnerability is detected"
    },
    {
      "id": "59fad1ae-bc92-4d4d-8977-176e8b5313be",
      "name": "Get Context From Port",
      "type": "CUSTOM.portApiAi",
      "position": [
        -1504,
        320
      ],
      "parameters": {
        "prompt": "=You are an assistant that provides contextual enrichment for vulnerabilities using the Port catalog as a knowledge base. A new security vulnerability has been detected.\nVulnerability Details:\n- Identifier: {{ $('Webhook Trigger').item.json.body.vulnerability_id }}\n- Description: {{ $('Webhook Trigger').item.json.body.description }}\n- Severity: {{ $('Webhook Trigger').item.json.body.severity }}\n- CVE: {{ $('Webhook Trigger').item.json.body.cve || 'N/A' }}\n- Package: {{ $('Webhook Trigger').item.json.body.package || 'N/A' }}\n\nUsing the Port catalog, return relevant contextual information. Specifically, retrieve:\n1. The affected service or repository\n2. Service owners and responsible team\n3. Environment (production/staging/dev)\n4. Service tier and SLA requirements\n5. Team's Slack channel\n6. Related dependencies\n7. Jira project key for security tickets\n\nYour response must be a single valid JSON object only, without any code block formatting, markdown, explanations, or extra text.\nDo not include ```json or ``` or any surrounding characters \u2014 just raw JSON.\n\nRequired output schema:\n{\n  \"service_name\": \"\",\n  \"repository\": \"\",\n  \"service_tier\": \"production|staging|development\",\n  \"sla_hours\": 0,\n  \"owners\": [],\n  \"slack_channel\": \"\",\n  \"environment\": \"\",\n  \"dependencies\": [],\n  \"jira_project_key\": \"\"\n}",
        "operation": "invokeAgent",
        "agentIdentifier": "context_retriever_agent"
      },
      "typeVersion": 1
    },
    {
      "id": "894a418a-0821-41af-b361-67d242e4e90b",
      "name": "OpenAI Remediation Plan",
      "type": "n8n-nodes-base.openAi",
      "position": [
        -1088,
        320
      ],
      "parameters": {
        "model": "gpt-4o-mini",
        "prompt": {
          "messages": [
            {
              "content": "=You are a security engineer. Analyze this vulnerability and create a remediation plan.\n\nVulnerability:\n- ID: {{ $('Webhook Trigger').item.json.body.vulnerability_id }}\n- Description: {{ $('Webhook Trigger').item.json.body.description }}\n- Severity: {{ $('Webhook Trigger').item.json.body.severity }}\n- CVE: {{ $('Webhook Trigger').item.json.body.cve || 'N/A' }}\n- Package: {{ $('Webhook Trigger').item.json.body.package || 'N/A' }}\n\nService Context from Port:\n{{ $('Get Context From Port').item.json.executionMessage }}\n\nYour response must be a single valid JSON object only, without any code block formatting, markdown, explanations, or extra text.\nDo not include ```json or ``` or any surrounding characters \u2014 just raw JSON.\n\nRequired output schema:\n{\n  \"summary\": \"Brief description of the vulnerability\",\n  \"impact\": \"Business impact assessment\",\n  \"remediation_steps\": [\"Step 1\", \"Step 2\"],\n  \"is_auto_fixable\": true or false,\n  \"fix_prompt\": \"Detailed prompt for a coding agent to fix this vulnerability\",\n  \"estimated_effort\": \"low|medium|high\"\n}"
            }
          ]
        },
        "options": {},
        "resource": "chat",
        "requestOptions": {}
      },
      "typeVersion": 1
    },
    {
      "id": "6c3608c6-5534-45a4-bb9e-df8887abf06a",
      "name": "Check Severity Level",
      "type": "n8n-nodes-base.switch",
      "position": [
        -784,
        320
      ],
      "parameters": {
        "rules": {
          "rules": [
            {
              "value2": "critical"
            },
            {
              "value2": "high"
            },
            {
              "value2": ".*",
              "operation": "regex"
            }
          ]
        },
        "value1": "={{ $('Webhook Trigger').item.json.body.severity.toLowerCase() }}",
        "dataType": "string",
        "fallbackOutput": 2
      },
      "typeVersion": 2
    },
    {
      "id": "a8a13823-f8d6-422e-ba0e-2fa220cbf6d6",
      "name": "Create Critical Jira Ticket",
      "type": "n8n-nodes-base.jira",
      "position": [
        -512,
        272
      ],
      "parameters": {
        "project": {
          "__rl": true,
          "mode": "list",
          "value": "10000",
          "cachedResultName": "Port"
        },
        "summary": "=[CRITICAL] {{ $('Webhook Trigger').item.json.body.vulnerability_id }}: {{ $('Webhook Trigger').item.json.body.description.substring(0, 100) }}",
        "issueType": {
          "__rl": true,
          "mode": "list",
          "value": "10002",
          "cachedResultName": "Task"
        },
        "additionalFields": {
          "labels": [
            "security"
          ],
          "priority": {
            "__rl": true,
            "mode": "list",
            "value": "10001",
            "cachedResultName": "Now (Urgent)"
          },
          "description": "=*Security Vulnerability - CRITICAL*\n\n*Vulnerability Details*\n- ID: {{ $('Webhook Trigger').item.json.body.vulnerability_id }}\n- CVE: {{ $('Webhook Trigger').item.json.body.cve || 'N/A' }}\n- Severity: CRITICAL\n- Package: {{ $('Webhook Trigger').item.json.body.package || 'N/A' }}\n\n*Description*\n{{ $('Webhook Trigger').item.json.body.description }}\n\n*Affected Service*\n{{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return '- Service: ' + (parsed?.service_name || 'Unknown') + '\\n- Repository: ' + (parsed?.repository || 'Unknown') + '\\n- Environment: ' + (parsed?.environment || 'Unknown') + '\\n- Owners: ' + (parsed?.owners?.join(', ') || 'Unknown'); } catch(e) { return 'Context unavailable'; } })() }}\n\n*AI Remediation Plan*\n{{ (() => { try { let content = $('OpenAI Remediation Plan').item.json.message?.content || '{}'; if (content.includes('```json')) { content = content.replace(/```json\\n?/g, '').replace(/```\\n?/g, ''); } const ai = JSON.parse(content); return ai.summary || 'See remediation steps'; } catch(e) { return 'Analysis pending'; } })() }}\n\n*Impact*\n{{ (() => { try { let content = $('OpenAI Remediation Plan').item.json.message?.content || '{}'; if (content.includes('```json')) { content = content.replace(/```json\\n?/g, '').replace(/```\\n?/g, ''); } const ai = JSON.parse(content); return ai.impact || 'Impact assessment pending'; } catch(e) { return 'Impact assessment pending'; } })() }}\n\n*Remediation Steps*\n{{ (() => { try { let content = $('OpenAI Remediation Plan').item.json.message?.content || '{}'; if (content.includes('```json')) { content = content.replace(/```json\\n?/g, '').replace(/```\\n?/g, ''); } const ai = JSON.parse(content); return ai.remediation_steps?.map((s, i) => (i+1) + '. ' + s).join('\\n') || 'Steps pending'; } catch(e) { return 'Steps pending'; } })() }}\n\n*SLA*\nThis vulnerability must be resolved within {{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return parsed?.sla_hours || 24; } catch(e) { return 24; } })() }} hours.\n\n---\n_Auto-generated by n8n + Port security workflow_"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7a9e901c-1312-4a85-b3df-b0412f9722bc",
      "name": "Create High Jira Ticket",
      "type": "n8n-nodes-base.jira",
      "position": [
        -512,
        416
      ],
      "parameters": {
        "project": {
          "__rl": true,
          "mode": "list",
          "value": "10000",
          "cachedResultName": "Port"
        },
        "summary": "=[HIGH] {{ $('Webhook Trigger').item.json.body.vulnerability_id }}: {{ $('Webhook Trigger').item.json.body.description.substring(0, 100) }}",
        "issueType": {
          "__rl": true,
          "mode": "list",
          "value": "10002",
          "cachedResultName": "Task"
        },
        "additionalFields": {
          "labels": [
            "security"
          ],
          "priority": {
            "__rl": true,
            "mode": "list",
            "value": "2",
            "cachedResultName": "High"
          },
          "description": "=*Security Vulnerability - HIGH*\n\n*Vulnerability Details*\n- ID: {{ $('Webhook Trigger').item.json.body.vulnerability_id }}\n- CVE: {{ $('Webhook Trigger').item.json.body.cve || 'N/A' }}\n- Severity: HIGH\n- Package: {{ $('Webhook Trigger').item.json.body.package || 'N/A' }}\n\n*Description*\n{{ $('Webhook Trigger').item.json.body.description }}\n\n*Affected Service*\n{{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return '- Service: ' + (parsed?.service_name || 'Unknown') + '\\n- Repository: ' + (parsed?.repository || 'Unknown') + '\\n- Environment: ' + (parsed?.environment || 'Unknown') + '\\n- Owners: ' + (parsed?.owners?.join(', ') || 'Unknown'); } catch(e) { return 'Context unavailable'; } })() }}\n\n*AI Remediation Plan*\n{{ (() => { try { let content = $('OpenAI Remediation Plan').item.json.message?.content || '{}'; if (content.includes('```json')) { content = content.replace(/```json\\n?/g, '').replace(/```\\n?/g, ''); } const ai = JSON.parse(content); return ai.summary || 'See remediation steps'; } catch(e) { return 'Analysis pending'; } })() }}\n\n*Remediation Steps*\n{{ (() => { try { let content = $('OpenAI Remediation Plan').item.json.message?.content || '{}'; if (content.includes('```json')) { content = content.replace(/```json\\n?/g, '').replace(/```\\n?/g, ''); } const ai = JSON.parse(content); return ai.remediation_steps?.map((s, i) => (i+1) + '. ' + s).join('\\n') || 'Steps pending'; } catch(e) { return 'Steps pending'; } })() }}\n\n---\n_Auto-generated by n8n + Port security workflow_"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "6f4fe862-3748-49fd-b197-98874801c330",
      "name": "Create Medium/Low Jira Ticket",
      "type": "n8n-nodes-base.jira",
      "position": [
        -512,
        560
      ],
      "parameters": {
        "project": {
          "__rl": true,
          "mode": "list",
          "value": "10000",
          "cachedResultName": "Port"
        },
        "summary": "=[{{ $('Webhook Trigger').item.json.body.severity.toUpperCase() }}] {{ $('Webhook Trigger').item.json.body.vulnerability_id }}: {{ $('Webhook Trigger').item.json.body.description.substring(0, 100) }}",
        "issueType": {
          "__rl": true,
          "mode": "list",
          "value": "10002",
          "cachedResultName": "Task"
        },
        "additionalFields": {
          "labels": [
            "security"
          ],
          "priority": {
            "__rl": true,
            "mode": "list",
            "value": "4",
            "cachedResultName": "Low"
          },
          "description": "=*Security Vulnerability*\n\n*Vulnerability Details*\n- ID: {{ $('Webhook Trigger').item.json.body.vulnerability_id }}\n- CVE: {{ $('Webhook Trigger').item.json.body.cve || 'N/A' }}\n- Severity: {{ $('Webhook Trigger').item.json.body.severity }}\n- Package: {{ $('Webhook Trigger').item.json.body.package || 'N/A' }}\n\n*Description*\n{{ $('Webhook Trigger').item.json.body.description }}\n\n*Affected Service*\n{{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return '- Service: ' + (parsed?.service_name || 'Unknown') + '\\n- Repository: ' + (parsed?.repository || 'Unknown'); } catch(e) { return 'Context unavailable'; } })() }}\n\n*Remediation Steps*\n{{ (() => { try { let content = $('OpenAI Remediation Plan').item.json.message?.content || '{}'; if (content.includes('```json')) { content = content.replace(/```json\\n?/g, '').replace(/```\\n?/g, ''); } const ai = JSON.parse(content); return ai.remediation_steps?.map((s, i) => (i+1) + '. ' + s).join('\\n') || 'Steps pending'; } catch(e) { return 'Steps pending'; } })() }}\n\n---\n_Auto-generated by n8n + Port security workflow_"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c14c83a9-e20b-44dc-bb5f-122b860d34e0",
      "name": "Is Auto-Fixable?",
      "type": "n8n-nodes-base.if",
      "position": [
        -208,
        256
      ],
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ (() => { try { let content = $('OpenAI Remediation Plan').item.json.message?.content || '{}'; if (content.includes('```json')) { content = content.replace(/```json\\n?/g, '').replace(/```\\n?/g, ''); } const ai = JSON.parse(content); return ai.is_auto_fixable === true || (ai.fix_prompt && ai.fix_prompt.length > 10); } catch(e) { return false; } })() }}",
              "value2": "={{ true }}"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7e272afb-5682-44b0-a5a6-e5f9bab00321",
      "name": "Trigger Fix via Port AI Agent",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        112,
        128
      ],
      "parameters": {
        "url": "https://api.getport.io/v1/actions/run_claude_code/runs",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ properties: { service: (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return parsed?.repository || 'default-organization/repository'; } catch(e) { return 'default-organization/repository'; } })(), prompt: (() => { try { let content = $('OpenAI Remediation Plan').item.json.message?.content || '{}'; if (content.includes('```json')) { content = content.replace(/```json\\n?/g, '').replace(/```\\n?/g, ''); } const ai = JSON.parse(content); const vulnId = $('Webhook Trigger').item.json.body.vulnerability_id; const jiraKey = $('Create Critical Jira Ticket').item.json?.key || 'N/A'; return 'Fix vulnerability ' + vulnId + ': ' + (ai.fix_prompt || ai.summary || 'security vulnerability') + '. Reference Jira ticket: ' + jiraKey + '. Create a PR with the fix.'; } catch(e) { return 'Fix the security vulnerability and create a PR.'; } })() } }) }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "typeVersion": 4.3
    },
    {
      "id": "cee7f862-9878-419a-82e6-307fb017b833",
      "name": "Alert Critical to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        352,
        160
      ],
      "parameters": {
        "text": "=\ud83d\udea8 *CRITICAL SECURITY VULNERABILITY DETECTED*\n\n*Vulnerability:* {{ $('Webhook Trigger').item.json.body.vulnerability_id }}\n*CVE:* {{ $('Webhook Trigger').item.json.body.cve || 'N/A' }}\n*Severity:* CRITICAL \ud83d\udd34\n\n*Affected Service:* {{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return parsed?.service_name || 'Unknown'; } catch(e) { return 'Unknown'; } })() }}\n*Environment:* {{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return parsed?.environment || 'Unknown'; } catch(e) { return 'Unknown'; } })() }}\n*Owners:* {{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return parsed?.owners?.join(', ') || 'Not specified'; } catch(e) { return 'Not specified'; } })() }}\n\n*Summary:*\n{{ (() => { try { let content = $('OpenAI Remediation Plan').item.json.message?.content || '{}'; if (content.includes('```json')) { content = content.replace(/```json\\n?/g, '').replace(/```\\n?/g, ''); } const ai = JSON.parse(content); return ai.summary || 'See Jira ticket'; } catch(e) { return 'See Jira ticket'; } })() }}\n\n*Impact:*\n{{ (() => { try { let content = $('OpenAI Remediation Plan').item.json.message?.content || '{}'; if (content.includes('```json')) { content = content.replace(/```json\\n?/g, '').replace(/```\\n?/g, ''); } const ai = JSON.parse(content); return ai.impact || 'See Jira ticket'; } catch(e) { return 'See Jira ticket'; } })() }}\n\n*Jira Ticket:* {{ $('Create Critical Jira Ticket').item.json?.key || 'Creating...' }}\n\n\ud83e\udd16 *Auto-Fix Status:* Triggered\n\n_SLA: Resolve within {{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return parsed?.sla_hours || 24; } catch(e) { return 24; } })() }} hours_",
        "channel": "={{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return parsed?.slack_channel || '#security-alerts'; } catch(e) { return '#security-alerts'; } })() }}",
        "attachments": [],
        "otherOptions": {}
      },
      "typeVersion": 1
    },
    {
      "id": "7b6609b8-ccc5-46d6-a1ed-ef61b655393c",
      "name": "Alert Critical (Manual Fix)",
      "type": "n8n-nodes-base.slack",
      "position": [
        128,
        336
      ],
      "parameters": {
        "text": "=\ud83d\udea8 *CRITICAL SECURITY VULNERABILITY - MANUAL FIX REQUIRED*\n\n*Vulnerability:* {{ $('Webhook Trigger').item.json.body.vulnerability_id }}\n*CVE:* {{ $('Webhook Trigger').item.json.body.cve || 'N/A' }}\n*Severity:* CRITICAL \ud83d\udd34\n\n*Affected Service:* {{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return parsed?.service_name || 'Unknown'; } catch(e) { return 'Unknown'; } })() }}\n*Owners:* {{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return parsed?.owners?.join(', ') || 'Not specified'; } catch(e) { return 'Not specified'; } })() }}\n\n*Summary:*\n{{ (() => { try { let content = $('OpenAI Remediation Plan').item.json.message?.content || '{}'; if (content.includes('```json')) { content = content.replace(/```json\\n?/g, '').replace(/```\\n?/g, ''); } const ai = JSON.parse(content); return ai.summary || 'See Jira ticket'; } catch(e) { return 'See Jira ticket'; } })() }}\n\n*Remediation Steps:*\n{{ (() => { try { let content = $('OpenAI Remediation Plan').item.json.message?.content || '{}'; if (content.includes('```json')) { content = content.replace(/```json\\n?/g, '').replace(/```\\n?/g, ''); } const ai = JSON.parse(content); return ai.remediation_steps?.map((s, i) => (i+1) + '. ' + s).join('\\n') || 'See Jira ticket'; } catch(e) { return 'See Jira ticket'; } })() }}\n\n*Jira Ticket:* {{ $('Create Critical Jira Ticket').item.json?.key || 'Creating...' }}\n\n\u26a0\ufe0f *This vulnerability requires manual remediation*\n\n_SLA: Resolve within {{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return parsed?.sla_hours || 24; } catch(e) { return 24; } })() }} hours_",
        "channel": "={{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return parsed?.slack_channel || '#security-alerts'; } catch(e) { return '#security-alerts'; } })() }}",
        "attachments": [],
        "otherOptions": {}
      },
      "typeVersion": 1
    },
    {
      "id": "367c49c6-9c43-4dbf-98dd-23b8d2c325aa",
      "name": "Alert High to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        -208,
        448
      ],
      "parameters": {
        "text": "=\u26a0\ufe0f *HIGH SEVERITY VULNERABILITY DETECTED*\n\n*Vulnerability:* {{ $('Webhook Trigger').item.json.body.vulnerability_id }}\n*CVE:* {{ $('Webhook Trigger').item.json.body.cve || 'N/A' }}\n*Severity:* HIGH \ud83d\udfe0\n\n*Affected Service:* {{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return parsed?.service_name || 'Unknown'; } catch(e) { return 'Unknown'; } })() }}\n*Owners:* {{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return parsed?.owners?.join(', ') || 'Not specified'; } catch(e) { return 'Not specified'; } })() }}\n\n*Summary:*\n{{ (() => { try { let content = $('OpenAI Remediation Plan').item.json.message?.content || '{}'; if (content.includes('```json')) { content = content.replace(/```json\\n?/g, '').replace(/```\\n?/g, ''); } const ai = JSON.parse(content); return ai.summary || 'See Jira ticket'; } catch(e) { return 'See Jira ticket'; } })() }}\n\n*Jira Ticket:* {{ $('Create High Jira Ticket').item.json?.key || 'Creating...' }}",
        "channel": "={{ (() => { try { const ctx = $('Get Context From Port').item.json.executionMessage; const parsed = typeof ctx === 'string' ? JSON.parse(ctx) : ctx; return parsed?.slack_channel || '#security-alerts'; } catch(e) { return '#security-alerts'; } })() }}",
        "attachments": [],
        "otherOptions": {}
      },
      "typeVersion": 1
    },
    {
      "id": "6fc1bd29-00b5-40a3-88ae-092a975efa57",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2320,
        -16
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 680,
        "content": "## Remediate security vulnerabilities with n8n and Port\n\nThis workflow automates security vulnerability management from detection to remediation.\n\n**How it works**\n\n1. Webhook receives vulnerability alerts from your scanner\n2. Port enriches with service context, ownership, and SLA info\n3. OpenAI generates a remediation plan\n4. Jira ticket is created based on severity\n5. For critical issues, Claude Code can create a fix PR\n6. Team is notified via Slack\n\n### Prerequisites\n\n- Port account with services and ownership configured\n- Port AI agent (`context_retriever_agent`)\n- Claude Code action in Port\n- Jira project for security tickets\n- Slack workspace connected\n- OpenAI API key"
      },
      "typeVersion": 1
    },
    {
      "id": "a4279dd4-c9fe-4518-b2b9-26a285e62b3b",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1792,
        -32
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 380,
        "content": "### 1. Trigger & enrichment\n\n**Webhook Trigger**\nReceives POST requests from security scanners (Snyk, Wiz, SonarQube, etc.)\n\n**Get Context From Port**\nQueries Port's catalog to enrich the vulnerability with:\n- Service name & repository\n- Team ownership\n- Environment (prod/staging/dev)\n- SLA requirements\n- Slack channel for notifications\n- Jira project key"
      },
      "typeVersion": 1
    },
    {
      "id": "9dd27328-1ffb-4242-b52b-1496ed97059c",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1232,
        80
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 280,
        "content": "### 2. AI analysis\n\n**OpenAI Remediation Plan**\nAnalyzes the vulnerability and generates:\n- Summary of the issue\n- Business impact assessment\n- Step-by-step remediation guide\n- Auto-fix determination\n- Fix prompt for Claude Code"
      },
      "typeVersion": 1
    },
    {
      "id": "929c7b74-5795-43e8-a35a-79af8f8fa391",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -912,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 420,
        "content": "### Severity routing & Jira tickets\n\n**Check Severity Level**\nRoutes to the appropriate path based on severity.\n\n**Jira Ticket Creation**\nCreates tickets with full context:\n\n- Critical: \"Now (Urgent)\" priority\n- High: \"High\" priority\n- Medium/Low: \"Low\" priority\n\nTickets include vulnerability details, affected service info from Port, and AI-generated remediation steps."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "e9e96fe4-0790-417c-a0a9-7020984930a0",
  "connections": {
    "Webhook Trigger": {
      "main": [
        [
          {
            "node": "Get Context From Port",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Auto-Fixable?": {
      "main": [
        [
          {
            "node": "Trigger Fix via Port AI Agent",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Alert Critical (Manual Fix)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Severity Level": {
      "main": [
        [
          {
            "node": "Create Critical Jira Ticket",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create High Jira Ticket",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create Medium/Low Jira Ticket",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Context From Port": {
      "main": [
        [
          {
            "node": "OpenAI Remediation Plan",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create High Jira Ticket": {
      "main": [
        [
          {
            "node": "Alert High to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Remediation Plan": {
      "main": [
        [
          {
            "node": "Check Severity Level",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Critical Jira Ticket": {
      "main": [
        [
          {
            "node": "Is Auto-Fixable?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger Fix via Port AI Agent": {
      "main": [
        [
          {
            "node": "Alert Critical to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Complete security workflow from vulnerability detection to automated remediation, with severity-based routing and full organizational context from Port's catalog. This template provides end-to-end lifecycle management including automatic Jira ticket creation with appropriate…

Source: https://n8n.io/workflows/11726/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Complete incident workflow from detection through resolution to post-mortem, with full organizational context from Port's catalog. This template handles both incident triggered and resolved events fro

Custom, OpenAI, Slack +1
AI & RAG

Venafi Presentation - Watch Video

Venafi Tls Protect Cloud, HTTP Request, OpenAI +1
AI & RAG

Automatically detects missed Zoom demos booked via Calendly and triggers AI-powered follow-up sequences.

HTTP Request, OpenAI, Email Send +3
AI & RAG

AI-Powered Fake Review Detection Workflow Using n8n & Airtable. Uses httpRequest, airtable, openAi, slack. Webhook trigger; 27 nodes.

HTTP Request, Airtable, OpenAI +1
AI & RAG

This workflow automates the end-to-end process of scheduling technical or behavioral interviews. It captures interview data via Webhook, creates a Google Calendar event with an integrated Google Meet

Google Calendar, OpenAI, Gmail +2