arazzo: 1.0.1 info: title: GreyNoise CVE Exposure Scan summary: Look up a CVE, then aggregate and sample the IPs exploiting it. description: >- Connects a vulnerability to the real-world activity around it. The workflow first retrieves details for a CVE, then runs a GNQL query for IPs associated with that CVE, branches on whether any IPs were found, aggregates statistics over the exploiting population, and finally pulls the full IP context for the first observed IP. Every step spells out its request inline so the flow can be read and executed without opening the underlying OpenAPI description. version: 1.0.0 sourceDescriptions: - name: greynoiseApi url: ../openapi/greynoise-openapi.yml type: openapi workflows: - workflowId: cve-exposure-scan summary: CVE lookup, then GNQL hunt, stats, and context of the first IP. description: >- Looks up a CVE, queries GNQL for IPs associated with it, and when results exist aggregates exploitation statistics and contexts the first IP. inputs: type: object required: - apiKey - cveId properties: apiKey: type: string description: GreyNoise API key passed via the 'key' HTTP header. cveId: type: string description: The CVE ID to investigate (e.g. CVE-2021-44228). size: type: integer description: Number of results per page in the GNQL hunt step. default: 10 steps: - stepId: cveLookup description: >- Retrieve details about the specified CVE based on the caller's entitlements. operationId: getCVE parameters: - name: key in: header value: $inputs.apiKey - name: cve_id in: path value: $inputs.cveId successCriteria: - condition: $statusCode == 200 outputs: cve: $response.body - stepId: huntCve description: >- Run a GNQL query for IP addresses associated with the CVE. operationId: gnqlV3Query parameters: - name: key in: header value: $inputs.apiKey - name: query in: query value: "cve:$inputs.cveId" - name: size in: query value: $inputs.size successCriteria: - condition: $statusCode == 200 outputs: count: $response.body#/request_metadata/count firstIp: $response.body#/data/0/ip onSuccess: - name: exploited type: goto stepId: cveStats criteria: - context: $response.body condition: $.data.length > 0 type: jsonpath - name: noActivity type: end criteria: - context: $response.body condition: $.data.length == 0 type: jsonpath - stepId: cveStats description: >- Aggregate statistics over the population of IPs associated with the CVE, including top classifications, tags, actors, and organizations. operationId: gnqlV3Stats parameters: - name: key in: header value: $inputs.apiKey - name: query in: query value: "cve:$inputs.cveId" successCriteria: - condition: $statusCode == 200 outputs: total: $response.body#/count classifications: $response.body#/stats/classifications organizations: $response.body#/stats/organizations - stepId: contextFirst description: >- Retrieve the full IP context for the first IP associated with the CVE, including metadata, classification, associated actor, and raw scan data. operationId: V3IP parameters: - name: key in: header value: $inputs.apiKey - name: ip in: path value: $steps.huntCve.outputs.firstIp - name: quick in: query value: false successCriteria: - condition: $statusCode == 200 outputs: ip: $response.body#/ip classification: $response.body#/internet_scanner_intelligence/classification actor: $response.body#/internet_scanner_intelligence/actor outputs: cveExploitCount: $steps.huntCve.outputs.count total: $steps.cveStats.outputs.total firstIp: $steps.huntCve.outputs.firstIp classification: $steps.contextFirst.outputs.classification