{
  "id": "W3unQdoRSdzDXDyPfCKdj",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "File Hash Reputation Checker",
  "tags": [
    {
      "id": "PQsDv8dbNswnsItE",
      "name": "cybersecurity",
      "createdAt": "2026-02-04T07:53:18.370Z",
      "updatedAt": "2026-02-04T07:53:18.370Z"
    },
    {
      "id": "jI1EvO6QTAu5XPp6",
      "name": "virus total",
      "createdAt": "2026-02-04T07:53:38.155Z",
      "updatedAt": "2026-02-04T07:53:38.155Z"
    },
    {
      "id": "mOOHD7ZEi5V8NM1I",
      "name": "malware",
      "createdAt": "2026-02-04T07:53:56.067Z",
      "updatedAt": "2026-02-04T07:53:56.067Z"
    },
    {
      "id": "qfS2esG6Rh52i4DR",
      "name": "slack",
      "createdAt": "2026-01-29T06:09:26.747Z",
      "updatedAt": "2026-01-29T06:09:26.747Z"
    },
    {
      "id": "ql9O8hOXPjaCNbht",
      "name": "hash",
      "createdAt": "2026-02-04T07:53:09.179Z",
      "updatedAt": "2026-02-04T07:53:09.179Z"
    }
  ],
  "nodes": [
    {
      "id": "34008e71-38bb-4de3-a060-1eb96f1686fa",
      "name": "Receive File Hash",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -48,
        176
      ],
      "parameters": {
        "path": "/hash-check",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "9985ba85-7a31-44d0-beb3-d1a7541c0ef8",
      "name": "Respond - Clean or Unknown",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1520,
        272
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={\n  \"hash\": \"{{ $json.hash }}\",\n  \"verdict\": \"{{$json.verdict}}\",\n  \"malicious\":{{ $json.malicious }},\n  \"suspicious\":{{ $json.suspicious }},\n  \"detections\": \"{{$json.malicious}}/{{$json.total}}\"\n} "
      },
      "typeVersion": 1.5
    },
    {
      "id": "3f542484-250d-416e-aa4e-4aeada8b029d",
      "name": "Slack - Malicious Hash Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        1520,
        80
      ],
      "parameters": {
        "text": "=\ud83d\udea8 MALICIOUS FILE DETECTED\nHash: {{ $json.hash }}\nDetections: {{$json.malicious}}/{{$json.total}}\nFamily: {{$json.malware_family}}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0A252GLT70",
          "cachedResultName": "all-team-sawi"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "9119e5d5-bc35-4e7d-9a2c-5006b7063cea",
      "name": "IF - Malicious Verdict",
      "type": "n8n-nodes-base.if",
      "position": [
        1296,
        160
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "91bdc517-211b-4c07-a9ae-8cad6c6093f0",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.verdict ===\"Malicious\" }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "84b36197-ed3a-4d5a-8017-d237c2daf6fd",
      "name": "Function - Calculate Verdict",
      "type": "n8n-nodes-base.code",
      "position": [
        1088,
        80
      ],
      "parameters": {
        "jsCode": "const stats = $json.data.attributes.last_analysis_stats;\n\nconst malicious = stats.malicious || 0;\nconst suspicious = stats.suspicious || 0;\nconst total = Object.values(stats).reduce((a, b) => a + b, 0);\n\nlet verdict = \"Clean\";\nif (malicious > 0) verdict = \"Malicious\";\nelse if (suspicious > 0) verdict = \"Suspicious\";\n\nreturn [{\n  json: {    \n    hash: $json.data.id,\n    verdict,\n    malicious,\n    suspicious,\n    total,\n    malware_family: $json.data.attributes.popular_threat_classification?.suggested_threat_label || \"N/A\"\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "189900ed-8e3d-4f24-87a2-284769506024",
      "name": "Respond - Invalid Hash",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        656,
        288
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "{\n  \"status\": \"error\",\n  \"message\": \"Invalid hash format. Provide MD5, SHA1, or SHA256.\"\n}\n"
      },
      "typeVersion": 1.5
    },
    {
      "id": "cc43ad57-4842-48dc-959b-8185dcb16501",
      "name": "HTTP - VirusTotal Hash Lookup",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        656,
        96
      ],
      "parameters": {
        "": "",
        "url": "=https://www.virustotal.com/api/v3/files/{{ $json.hash }}",
        "method": "GET",
        "options": {},
        "sendBody": false,
        "sendQuery": false,
        "curlImport": "",
        "infoMessage": "",
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "specifyHeaders": "keypair",
        "headerParameters": {},
        "httpVariantWarning": "",
        "nodeCredentialType": "virusTotalApi",
        "provideSslCertificates": false
      },
      "credentials": {
        "virusTotalApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3,
      "extendsCredential": "virusTotalApi"
    },
    {
      "id": "d31682ad-58d9-49e3-9b49-ee1037cf97b5",
      "name": "IF - Hash Exists in VT",
      "type": "n8n-nodes-base.if",
      "position": [
        864,
        176
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "b7a5c678-f4ef-4a15-b865-07fc9079c7dd",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{$json.error === undefined}}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "78006d40-ec95-4738-8356-1bc84ada73d0",
      "name": "IF - Valid Hash Format",
      "type": "n8n-nodes-base.if",
      "position": [
        416,
        176
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "4bcd63f1-eed7-49f5-bb21-ce0153cec8c2",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.hash.length.toString() }}",
              "rightValue": "=32"
            },
            {
              "id": "7067a87e-6396-4174-b061-ffcf6adb16fb",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.hash.length.toString() }}",
              "rightValue": "40"
            },
            {
              "id": "165d9c7a-35a9-4958-92dc-7ff49e9d88fe",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.hash.length.toString() }}",
              "rightValue": "64"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "35faaee9-f154-47bf-8fc0-9dbfe4a3d324",
      "name": "Respond - Unknown Hash",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1088,
        288
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={\n  \n  \"verdict\": \"Unknown\",\n  \"message\": \"{{ $json.error.message }}\"\n} "
      },
      "typeVersion": 1.5
    },
    {
      "id": "d93e59a7-750a-4e8f-8a5f-e28a4c8f4f32",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        32
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 432,
        "content": "## 1. Webhook Input & Normalization\n"
      },
      "typeVersion": 1
    },
    {
      "id": "9200acad-94ac-4906-bcff-8b6019b29216",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        352,
        32
      ],
      "parameters": {
        "color": 7,
        "height": 432,
        "content": "## 2. Hash Validation\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b5644510-eb31-484c-b1ab-311c62c9c472",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        608,
        32
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 432,
        "content": "## 3. VirusTotal Lookup\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b69d7f7a-c2d3-4000-ac97-97d8ff2f55b3",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1024,
        32
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 432,
        "content": "## 4. Verdict Calculation\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b61abd46-d1c3-40b7-b7a5-19498391e414",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1456,
        32
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 432,
        "content": "## 5. Alerts & Responses\n"
      },
      "typeVersion": 1
    },
    {
      "id": "f074671e-f814-4ba9-a6d7-ea3d5a73f1c3",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -544,
        -96
      ],
      "parameters": {
        "width": 432,
        "height": 752,
        "content": "## File Hash Reputation Checker\nThis is a security automation workflow that validates files hashes (**MD5**, **SHA1**, **SHA256**) and checks their reputation using the **VirusTotal API**. \n\nThe workflow accepts a file hash via an **HTTP webhook**, normalizes and validates the input, then queries VirusTotal to retrieve detection statistics. Based on the analysis results, it determines whether the file is **Malicious**, **Suspicious**, **Clean**, or **Unknown**.\n\n### How it works\n1. Receives a file hash via webhook **(POST)** or Slack using Slash command.\n2. Normalizes and validates hash format.\n3. Queries **VirusTotal** for hash reputation.\n4. Calculates verdict from detection stats.\n5. Sends Slack alert if **malicious**.\n6. Returns a **JSON** response with verdict and detections.\n\n### Setup steps\n1. Add your **VirusTotal API** key to n8n credentials.\n2. Configure **Slack API** credentials and channel.\n3. Activate the workflow.\n4. Send a **POST** request with `{ \"text\": \"<file_hash>\" }` or submit file hash directly from Slack using `/hash-check <file hash>`.\n\n### Customization\n- Adjust verdict thresholds in the verdict function.\n- Add additional notifications (email, SIEM, ticketing).\n- Extend to support file uploads or multiple hashes.          "
      },
      "typeVersion": 1
    },
    {
      "id": "f712dae4-6336-4250-b8af-884ab56f8b25",
      "name": "Normalize Hash from Webhook",
      "type": "n8n-nodes-base.set",
      "position": [
        176,
        176
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "0f7b31e4-7305-4f80-93fb-663246db1063",
              "name": "hash",
              "type": "string",
              "value": "={{ $json.body.text.toLowerCase().trim() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "2f7ebeae-77e0-44b0-a4f2-7ca207474757",
      "name": "Send a message",
      "type": "n8n-nodes-base.slack",
      "position": [
        1728,
        272
      ],
      "parameters": {
        "text": "={{\n $json.verdict === 'Suspicious'\n    ? `\u26a0\ufe0f *SUSPICIOUS FILE*\nHash: ${$json.hash}\nDetections: ${$json.suspicious}/${$json.total}`\n\n  : $json.verdict === 'Clean'\n    ? `\u2705 *CLEAN FILE*\nHash: ${$json.hash}\nDetections: 0/${$json.total}`\n\n  : `\u2139\ufe0f *UNKNOWN FILE*\nHash: ${$json.hash}\nNot found in VirusTotal`\n}}\n",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0A252GLT70",
          "cachedResultName": "all-team-sawi"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    }
  ],
  "active": true,
  "settings": {
    "timezone": "Asia/Manila",
    "callerPolicy": "workflowsFromSameOwner",
    "errorWorkflow": "o4jqXmki9xPDSHf4J09Ld",
    "timeSavedMode": "fixed",
    "availableInMCP": true,
    "executionOrder": "v1",
    "timeSavedPerExecution": 3
  },
  "versionId": "961b130f-a21f-49e2-9cb4-bce11931aee8",
  "connections": {
    "Receive File Hash": {
      "main": [
        [
          {
            "node": "Normalize Hash from Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Hash Exists in VT": {
      "main": [
        [
          {
            "node": "Function - Calculate Verdict",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond - Unknown Hash",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Malicious Verdict": {
      "main": [
        [
          {
            "node": "Slack - Malicious Hash Alert",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond - Clean or Unknown",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Valid Hash Format": {
      "main": [
        [
          {
            "node": "HTTP - VirusTotal Hash Lookup",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond - Invalid Hash",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Respond - Clean or Unknown": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Hash from Webhook": {
      "main": [
        [
          {
            "node": "IF - Valid Hash Format",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Function - Calculate Verdict": {
      "main": [
        [
          {
            "node": "IF - Malicious Verdict",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP - VirusTotal Hash Lookup": {
      "main": [
        [
          {
            "node": "IF - Hash Exists in VT",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}