Orchestrate Security Vulnerability Remediation with n8n, Port, OpenAI, Jira, and Slack
Security scanner alert → Port catalog context enrichment → OpenAI remediation plan → severity-based routing → Jira ticket + Claude Code auto-fix → Slack notification
- Who
- Security or platform engineers with a self-hosted n8n instance using Port as their software catalog
- You get
- Automatically create severity-tiered Jira tickets on vulnerability alerts, trigger Claude Code PRs for critical issues, and notify responsible teams via Slack
Constraints
Prerequisites: Port account with onboarding completed; services and repositories cataloged in Port with ownership; security scanner (Snyk/Wiz/SonarQube) capable of webhooks; working n8n self-hosted instance with Port custom node installed; Jira Cloud account with project permissions; Slack workspace with bot message permissions; OpenAI API key. Limitations: Template intended for self-hosted n8n only; Jira project IDs and Port organization/repository are placeholders; Claude Code fix depends on Port-side action configuration.
What they did
Port IO published this workflow template on the n8n marketplace to automate security vulnerability management: security scanner alerts (Snyk, Wiz, SonarQube, etc.) enter via webhook, Port enriches service context from the software catalog, OpenAI generates a remediation plan, and severity-based routing creates tiered Jira tickets—critical issues attempt Claude Code auto-fix PRs while high issues trigger Slack notifications, and medium/low issues are tracked only via tickets.
How it went
The author states the template provides end-to-end lifecycle management including automatic Jira ticket creation with appropriate priority, AI-powered remediation planning, and Claude Code-triggered fixes for critical vulnerabilities (author_report). The template shows as published on n8n.io with 181 views.
Worth knowing
Template explicitly marked for self-hosted n8n only; Claude Code fix depends on Port platform-side run_claude_code action and Bearer authentication; Jira project/issueType/priority values in workflow.json are template placeholders (e.g., 10000/10002/10001) and must be replaced with actual project IDs; gpt-4o-mini is explicitly configured in the OpenAI node, while gpt-4o is claimed by source but not visible in node parameters; no ROI or runtime metrics provided by source; not tested by UKnowHow (reproduction=not_tested).
n8n workflow template
Structure checked · Not run-testedUse “Import from File” in n8n, or copy the JSON and paste it into the editor. Connect your own accounts, then try test data. The template is inactive by default.
Setup and test checklist
Credentials to connect
- After import, connect your own credentials on auth-required nodes; author secrets are not included.
Configuration to replace
- Source template is n8n public workflow #11726 (~16 nodes). Keep inactive after import; verify triggers, expressions and external API endpoints.
- Sticky-note guidance is informational; replace placeholders with your own accounts, sheet schemas or channel IDs.
Test input and expected output
- Manually run the main path once in a test workspace and confirm credentialed nodes authenticate without errors.
- Drive one synthetic/redacted sample through and check output fields and downstream writes before enabling in production.
Template changes
- Author credential bindings, webhookId and execution data are removed; the workflow is inactive. Nodes, connections and original prompts are preserved. Not run-tested in n8n.
- No business-logic edits; verify keys, quotas and privacy compliance before use.
Template retrieved: 2026-10-24
Steps
Configure trigger and Port context enrichment
After importing the template into n8n, configure the Webhook Trigger node to receive POST requests from your security scanner (path: security/vulnerability). Then configure the Get Context From Port node: set operation to invokeAgent, agentIdentifier to context_retriever_agent, and paste the prompt below into the prompt field. This node queries the Port software catalog for affected service, owners, environment, SLA, Slack channel, and Jira project key.
Execution prompt · Source text。Get Context From Port node prompt field
=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. Vulnerability Details: - Identifier: {{ $('Webhook Trigger').item.json.body.vulnerability_id }} - Description: {{ $('Webhook Trigger').item.json.body.description }} - Severity: {{ $('Webhook Trigger').item.json.body.severity }} - CVE: {{ $('Webhook Trigger').item.json.body.cve || 'N/A' }} - Package: {{ $('Webhook Trigger').item.json.body.package || 'N/A' }} Using the Port catalog, return relevant contextual information. Specifically, retrieve: 1. The affected service or repository 2. Service owners and responsible team 3. Environment (production/staging/dev) 4. Service tier and SLA requirements 5. Team's Slack channel 6. Related dependencies 7. Jira project key for security tickets Your response must be a single valid JSON object only, without any code block formatting, markdown, explanations, or extra text. Do not include ```json or ``` or any surrounding characters — just raw JSON. Required output schema: { "service_name": "", "repository": "", "service_tier": "production|staging|development", "sla_hours": 0, "owners": [], "slack_channel": "", "environment": "", "dependencies": [], "jira_project_key": "" }Configure OpenAI remediation plan generation
Configure the OpenAI Remediation Plan node: resource set to chat, model set to gpt-4o-mini (or gpt-4o), paste the prompt below into messages[0].content. This node combines vulnerability details with Port context to output a JSON containing summary, impact assessment, remediation steps, auto-fixability, Claude Code fix prompt, and estimated effort.
Execution prompt · Source text。OpenAI Remediation Plan node messages[0].content field
=You are a security engineer. Analyze this vulnerability and create a remediation plan. Vulnerability: - ID: {{ $('Webhook Trigger').item.json.body.vulnerability_id }} - Description: {{ $('Webhook Trigger').item.json.body.description }} - Severity: {{ $('Webhook Trigger').item.json.body.severity }} - CVE: {{ $('Webhook Trigger').item.json.body.cve || 'N/A' }} - Package: {{ $('Webhook Trigger').item.json.body.package || 'N/A' }} Service Context from Port: {{ $('Get Context From Port').item.json.executionMessage }} Your response must be a single valid JSON object only, without any code block formatting, markdown, explanations, or extra text. Do not include ```json or ``` or any surrounding characters — just raw JSON. Required output schema: { "summary": "Brief description of the vulnerability", "impact": "Business impact assessment", "remediation_steps": ["Step 1", "Step 2"], "is_auto_fixable": true or false, "fix_prompt": "Detailed prompt for a coding agent to fix this vulnerability", "estimated_effort": "low|medium|high" }Configure severity routing and Jira tickets
Configure the Check Severity Level node (Switch type): value1 maps to webhook body.severity.toLowerCase(), with three branches matching critical, high, and default (regex .*). Then configure the three Jira nodes: Critical priority set to 'Now (Urgent)', High to 'High', Medium/Low to 'Low'; each node's project, issueType, summary, and description must be pointed to your actual Jira project. The description fields already embed Port context and AI remediation plan expressions.
Configure critical auto-fix and Slack alerts
After the Critical branch, configure the Is Auto-Fixable? node (If type): condition checks if OpenAI output is_auto_fixable is true or fix_prompt length exceeds 10. If true, route to Trigger Fix via Port AI Agent: method POST, URL https://api.getport.io/v1/actions/run_claude_code/runs, authentication genericCredentialType + httpBearerAuth, jsonBody using the template expression (with service and prompt properties). Then connect to Alert Critical to Slack for fix-triggered notification. If false, route to Alert Critical (Manual Fix) for manual remediation notification. Both Slack channels read from Port context with fallback #security-alerts.
Execution prompt · Source text。Alert Critical to Slack node text field
=🚨 *CRITICAL SECURITY VULNERABILITY DETECTED* *Vulnerability:* {{ $('Webhook Trigger').item.json.body.vulnerability_id }} *CVE:* {{ $('Webhook Trigger').item.json.body.cve || 'N/A' }} *Severity:* CRITICAL 🔴 *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'; } })() }} *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'; } })() }} *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'; } })() }} *Summary:* {{ (() => { 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'; } })() }} *Impact:* {{ (() => { 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'; } })() }} *Jira Ticket:* {{ $('Create Critical Jira Ticket').item.json?.key || 'Creating...' }} 🤖 *Auto-Fix Status:* Triggered _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_Execution prompt · Source text。Alert Critical (Manual Fix) node text field
=🚨 *CRITICAL SECURITY VULNERABILITY - MANUAL FIX REQUIRED* *Vulnerability:* {{ $('Webhook Trigger').item.json.body.vulnerability_id }} *CVE:* {{ $('Webhook Trigger').item.json.body.cve || 'N/A' }} *Severity:* CRITICAL 🔴 *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'; } })() }} *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'; } })() }} *Summary:* {{ (() => { 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'; } })() }} *Remediation Steps:* {{ (() => { 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'; } })() }} *Jira Ticket:* {{ $('Create Critical Jira Ticket').item.json?.key || 'Creating...' }} ⚠️ *This vulnerability requires manual remediation* _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_Configure high severity Slack notification
After the Create High Jira Ticket node on the High branch, configure the Alert High to Slack node: channel reads from Port context with fallback #security-alerts. Use the template below for the text field, containing vulnerability summary and Jira ticket reference.
Execution prompt · Source text。Alert High to Slack node text field
=⚠️ *HIGH SEVERITY VULNERABILITY DETECTED* *Vulnerability:* {{ $('Webhook Trigger').item.json.body.vulnerability_id }} *CVE:* {{ $('Webhook Trigger').item.json.body.cve || 'N/A' }} *Severity:* HIGH 🟠 *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'; } })() }} *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'; } })() }} *Summary:* {{ (() => { 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'; } })() }} *Jira Ticket:* {{ $('Create High Jira Ticket').item.json?.key || 'Creating...' }}
Prompt you can copy
Setup guidance · Editorial suggestion。Give to setup assistant to confirm inputs and permissions first
This block is the prompt. Ads are never placed here.
You are setting up the n8n security vulnerability auto-remediation workflow. First confirm you have: Port account with catalog data, self-hosted n8n instance, Jira/Slack/OpenAI credentials. After importing the template, replace Jira projects, organization/repository names, and webhook URL, then test with a sample payload.
Create the context_retriever_agent in Port before setup; Claude Code action requires pre-configuration on the Port platform side
Source
Orchestrate security vulnerability remediation with Port, OpenAI, Jira and Slack · portio · n8n.io · 2025-12-12
Comments & feedback
Tried this method? Share results, problems or improvements. Comments appear after moderation. Please avoid sensitive information.
Loading…
Agent feedback
Reports are submitted by Agents and shared after user confirmation and moderation. They are not platform-verified.