{
  "id": "PieiJJOvbuPki3Mj",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "COPY Malicious URL",
  "tags": [],
  "nodes": [
    {
      "id": "b0c038b7-7362-45a3-a0ad-b1f1b5efc738",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        -64
      ],
      "parameters": {
        "color": 3,
        "width": 2348,
        "height": 448,
        "content": "Malicious URL Scanner Through Telegram"
      },
      "typeVersion": 1
    },
    {
      "id": "4fe74461-614b-4fe1-a0ca-a06d003c056b",
      "name": "VirusTotal HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        848,
        208
      ],
      "parameters": {
        "": "",
        "url": "https://www.virustotal.com/api/v3/urls",
        "method": "POST",
        "options": {},
        "sendBody": false,
        "sendQuery": true,
        "curlImport": "",
        "infoMessage": "",
        "sendHeaders": false,
        "specifyQuery": "keypair",
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "url",
              "value": "={{ $json.message.text }}"
            }
          ]
        },
        "httpVariantWarning": "",
        "nodeCredentialType": "virusTotalApi",
        "provideSslCertificates": false
      },
      "credentials": {
        "virusTotalApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2,
      "extendsCredential": "virusTotalApi"
    },
    {
      "id": "7438f4d5-4837-4dae-b92f-2075ca498cf9",
      "name": "Send a text message",
      "type": "n8n-nodes-base.telegram",
      "position": [
        2464,
        -48
      ],
      "parameters": {
        "text": "={{ $json.output }}",
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "8dfce473-9dc5-476e-99d2-c52c197f2f5d",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        368,
        64
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "be71fedb-6aa7-4b77-ab99-3267ac8ec861",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        -768
      ],
      "parameters": {
        "width": 464,
        "height": 704,
        "content": "Goal:\nThis workflow allows users to quickly analyze potentially malicious URLs received via text or email, directly from their mobile device using Telegram.\nWhen users don't have time to manually investigate links on a computer or search engine, they can simply paste the URL into the Telegram chat and receive a concise summary of the scan results\u2014powered by two open-source URL scanning services.\n\nDisclaimer:\nWhile this tool helps identify threats, it does not guarantee full protection. Use caution\u2014Telegram itself could be a potential point of compromise. Always follow safe browsing practices.\n\nWorkflow Nodes:\nTelegram Trigger \u2013 Listens for incoming messages with URLs.\n\nurlscan.io \u2013 Performs the first malicious URL scan.\n\nVirusTotal (HTTP Request) \u2013 Executes a second URL scan using VirusTotal.\n\nMerge Node \u2013 Combines the results from both scanners.\n\nAI Agent (ChatGPT with simple memory) \u2013 Analyzes the scan results and generates a readable summary.\n\nLimit Node \u2013 Ensures only one summary is sent per URL.\n\nTelegram Send Message Node \u2013 Sends the summary back to the user.\n\nGoogle Sheets (Logging) \u2013 Records scan results for auditing or historical reference.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "36f49fe2-ac55-4dde-8786-9c9611947173",
      "name": "URL Logging",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2464,
        176
      ],
      "parameters": {
        "columns": {
          "value": {
            "URL": "={{ $('Telegram Trigger').item.json.message.text }}",
            "Report": "={{ $json.output }}",
            "Date/Time": "={{ $now }}"
          },
          "schema": [
            {
              "id": "URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Report",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Report",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Date/Time",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Date/Time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "URL"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1diuSW6dAgNu5XFH_sv1GF6TMlbm0jsokJmiuJzmSnUQ/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1diuSW6dAgNu5XFH_sv1GF6TMlbm0jsokJmiuJzmSnUQ",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1diuSW6dAgNu5XFH_sv1GF6TMlbm0jsokJmiuJzmSnUQ/edit?usp=drivesdk",
          "cachedResultName": "URL Scanner"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "aefd6784-f72d-4a12-b2f9-5dca81481b8f",
      "name": "Malicious URL Summary Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1712,
        48
      ],
      "parameters": {
        "text": "=Role:\nYou are a cybersecurity assistant specializing in analyzing and summarizing URL scan reports. Use results from VirusTotal (always available) and urlscan.io (only if successful) to provide a professional, clear, and easy-to-understand summary.\n\nInstructions \u2013 Follow These Steps (Do Not Include in Final Summary):\n\n1.\tIdentify the scanned URL:\n{{ $('Telegram Trigger').item.json.message.text }}\n\n2. Check urlscan.io status (already provided by Code node):\n\u2981\tIf urlscan_status is \"success\" \u2192 include findings from urlscan_data alongside VirusTotal.\n\u2981\tIf urlscan_status is \"failed\" \u2192 rely only on VirusTotal and clearly state: \u201curlscan.io scan failed or was blocked.\u201d\n\n3. Assess threat level (based on VirusTotal):\nClassify as Harmless, Suspicious, or Malicious\n\u2981\tBase this on:\n\u2981\tThe number of engines that flagged the URL\n\u2981\tSeverity of detections from notable vendors (Kaspersky, Bitdefender, Sophos, etc.)\n\n4. Quantify detections:\n\u2981\tNumber of VirusTotal engines flagging the URL\n\u2981\tNotable antivirus vendors and what they reported\n\nProvide recommendation:\n\u2981\tUse plain, clear language for a general audience\n\u2981\tExamples: \u201cAppears safe,\u201d \u201cProceed with caution,\u201d \u201cAvoid this URL.\u201d\n\n\nOutput Format:\nTitle:\nSummary for {{ $('Telegram Trigger').item.json.message.text }} {{ $now }}\n\nBullet Points:\n\u2981\tThreat Level: [Harmless / Suspicious / Malicious]\n\u2981\tNumber of engines flagging the URL: [X engines]\n\u2981\tVirusTotal score: [Number or descriptive result]\n\nurlscan.io indicators:\n\u2981\tIf urlscan_status is \"success\" \u2192 summarize results from urlscan_data\n\u2981\tIf urlscan_status is \"failed\" \u2192 output exactly: \u201cScan failed or was blocked\u201d\n\n\u2981\tNotable detections: [List key AV engines if any]\n\u2981\tRecommendation: [Plain-language recommendation]\n\nFinal Summary (4\u20138 sentences):\n\u2981\tAlways provide a complete summary.\n\u2981\tIf urlscan.io succeeded \u2192 combine VirusTotal + urlscan.io results.\n\u2981\tIf urlscan.io failed \u2192 summarize VirusTotal results normally, then add one sentence noting the urlscan.io scan was blocked or failed.\n\u2981\tInclude: the URL, detection counts, notable antivirus vendors, and a clear recommendation.\n\nClose with this reminder:\nEven if a link appears safe, always exercise caution when clicking unknown URLs\u2014threats can evolve quickly.",
        "options": {
          "systemMessage": "You are a cybersecurity assistant designed to analyze and summarize URL scan results using data from VirusTotal and urlscan.io.\n\nYour role is to:\n\nProvide a concise, professional, and easy-to-understand summary of each scan.\n\nExtract key insights from the JSON responses of both services.\n\nNormalize and interpret data to assess whether the scanned URL is harmless, suspicious, or malicious.\n\nWrite in a tone that is accessible to users with basic technical literacy.\n\nAvoid raw JSON fields, API parameter names, or unnecessary technical jargon.\n\nFor each scan, your output should include:\n\nA bullet-point summary of the key findings.\n\nA short written summary (4\u20138 sentences) combining insights from both sources.\n\nA clear recommendation to help the user decide whether to avoid, review, or safely access the URL.\n\nAlways integrate results from both services into a unified, user-friendly report."
        },
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "4fae7e6b-8213-4aba-8dd2-9d3759a1e69a",
      "name": "OpenAI Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1648,
        224
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4",
          "cachedResultName": "gpt-4"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "d2802345-d0e1-44b9-96b3-a8a84409dc51",
      "name": "Malicious URL Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        1888,
        224
      ],
      "parameters": {
        "sessionKey": "summary",
        "sessionIdType": "customKey"
      },
      "typeVersion": 1.3
    },
    {
      "id": "66ea8113-1052-4b08-8ee4-af822a3d42c4",
      "name": "Limit 1 Summary",
      "type": "n8n-nodes-base.limit",
      "position": [
        2080,
        48
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "df416f80-cc4d-4031-9e84-b929a262da0b",
      "name": "urlscan Perform Scan",
      "type": "n8n-nodes-base.urlScanIo",
      "onError": "continueRegularOutput",
      "position": [
        848,
        -32
      ],
      "parameters": {
        "url": "={{ $json.message.text }}",
        "additionalFields": {}
      },
      "credentials": {
        "urlScanIoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "de9d28e5-6f58-48cd-af76-36c0c2160a4d",
      "name": "Prepare Summary Data",
      "type": "n8n-nodes-base.code",
      "position": [
        1472,
        48
      ],
      "parameters": {
        "jsCode": "// Example Code node\n// Input: results from urlscan.io + VirusTotal + Telegram trigger\n\nconst items = $input.all();\n\n// Loop through items so we don\u2019t drop anything\nreturn items.map(item => {\n  const urlscan = item.json.urlscan || {};\n  const virustotal = item.json.virustotal || {};\n  \n  let summary = \"\";\n\n  if (urlscan.message) {\n    summary = `\u2705 urlscan.io result:\\n${JSON.stringify(urlscan)}\\n\\n\u2705 VirusTotal result:\\n${JSON.stringify(virustotal)}`;\n  } else {\n    summary = `\u26a0\ufe0f urlscan.io scan failed. Falling back to VirusTotal only:\\n${JSON.stringify(virustotal)}`;\n  }\n\n  // Preserve original fields (chatId, etc.)\n  return {\n    json: {\n      ...item.json,\n      summary, // add your summary field\n    },\n    binary: item.binary ?? undefined, // keep binary if exists\n  };\n});\n\n"
      },
      "typeVersion": 2
    },
    {
      "id": "056830ce-9c9e-4e4f-8d7c-51364596c6d7",
      "name": "Merge Scans",
      "type": "n8n-nodes-base.merge",
      "position": [
        1216,
        48
      ],
      "parameters": {},
      "typeVersion": 3.2
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "49fe0c17-5447-4ec2-805a-8508d4463e5d",
  "connections": {
    "Merge Scans": {
      "main": [
        [
          {
            "node": "Prepare Summary Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Model": {
      "ai_languageModel": [
        [
          {
            "node": "Malicious URL Summary Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Limit 1 Summary": {
      "main": [
        [
          {
            "node": "Send a text message",
            "type": "main",
            "index": 0
          },
          {
            "node": "URL Logging",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "VirusTotal HTTP Request",
            "type": "main",
            "index": 0
          },
          {
            "node": "urlscan Perform Scan",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send a text message": {
      "main": [
        []
      ]
    },
    "Malicious URL Memory": {
      "ai_memory": [
        [
          {
            "node": "Malicious URL Summary Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Summary Data": {
      "main": [
        [
          {
            "node": "Malicious URL Summary Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "urlscan Perform Scan": {
      "main": [
        [
          {
            "node": "Merge Scans",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "VirusTotal HTTP Request": {
      "main": [
        [
          {
            "node": "Merge Scans",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Malicious URL Summary Agent": {
      "main": [
        [
          {
            "node": "Limit 1 Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}