APIVoid
APIVoid wraps up a number of services such as ipvoid & urlvoid.
Data Enrichment & Threat Intelligence · APIVoid
Details
| ID | APIVoid |
|---|---|
| Provider | APIVoid |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
APIVoid wraps up a number of services such as ipvoid & urlvoid.
Configure APIVoid in Cortex
| Parameter | Description | Required |
|---|---|---|
| Server URL | True | |
| API Key | False | |
| Suspicious Reputation (Percentage) | If the percentage of detections is above this value, the indicator is scored as SUSPICIOUS. If the percentage of detections is below this value, the indicator is scored as GOOD. | True |
| Bad Reputation (Percentage) | If the percentage of detections is above this value, the indicator is considered bad. | True |
| Malicious | The indicator is considered malicious if the suspicious or bad reputation percentages exceed the thresholds. | True |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False | |
| Source Reliability | Reliability of the source providing the intelligence data. | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
apivoid-ip
Returns the reputation and extended context of the IP.
Base Command
apivoid-ip
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | The IP to query. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| IP.Address | string | IP address |
| IP.DetectionEngines | number | The total number of engines that checked the indicator. |
| IP.Geo | unknown | |
| IP.Geo.Country | string | The country in which the IP address is located. |
| IP.Geo.Description | string | Additional information about the location. |
| IP.Geo.Location | string | The geolocation where the IP address is located, in the format: latitude:longitude. |
| IP.Hostname | string | The hostname that is mapped to this IP address. |
| IP.PositiveDetections | number | The number of engines that positively detected the indicator as malicious. |
| DBotScore | unknown | |
| DBotScore.Indicator | string | The indicator that was tested. |
| DBotScore.Score | number | The actual score. |
| DBotScore.Type | string | The indicator type. |
| DBotScore.Vendor | string | The vendor used to calculate the score. |
| APIVoid.IP.anonymity.is_hosting | boolean | |
| APIVoid.IP.anonymity.is_proxy | boolean | |
| APIVoid.IP.anonymity.is_tor | boolean | |
| APIVoid.IP.anonymity.is_vpn | boolean | |
| APIVoid.IP.anonymity.is_webproxy | boolean | |
| APIVoid.IP.blacklists.detection_rate | string | |
| APIVoid.IP.blacklists.detections | number | |
| APIVoid.IP.blacklists.engines.detected | boolean | |
| APIVoid.IP.blacklists.engines.elapsed | string | |
| APIVoid.IP.blacklists.engines.engine | string | |
| APIVoid.IP.blacklists.engines.reference | string | |
| APIVoid.IP.blacklists.engines_count | number | |
| APIVoid.IP.blacklists.scantime | string | |
| APIVoid.IP.information.isp | string | |
| APIVoid.IP.information.latitude | string | |
| APIVoid.IP.information.reverse_dns | string | |
| APIVoid.IP.information.longitude | string | |
| APIVoid.IP.information.country_calling_code | string | |
| APIVoid.IP.information.country_name | string | |
| APIVoid.IP.information.region_name | string | |
| APIVoid.IP.information.country_code | string | |
| APIVoid.IP.information.continent_name | string | |
| APIVoid.IP.information.continent_code | string | |
| APIVoid.IP.information.country_currency | string | |
| APIVoid.IP.information.city_name | string | |
| APIVoid.IP.ip | string |
apivoid-domain
Returns the reputation of the domain.
Base Command
apivoid-domain
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | The Domain to query. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Domain | unknown | |
| Domain.DNS | string | A list of IP objects resolved by DNS. |
| Domain.DetectionEngines | number | The total number of engines that checked the indicator. |
| Domain.Name | string | The domain name, for example: “google.com”. |
| Domain.PositiveDetections | number | The number of engines that positively detected the indicator as malicious. |
| DBotScore | unknown | |
| DBotScore.Indicator | string | The indicator that was tested. |
| DBotScore.Score | number | The actual score. |
| DBotScore.Type | string | The indicator type. |
| DBotScore.Vendor | string | The vendor used to calculate the score. |
| APIVoid.Domain.alexa_top_100k | boolean | |
| APIVoid.Domain.domain_length | number | |
| APIVoid.Domain.server.isp | string | |
| APIVoid.Domain.server.ip | string | |
| APIVoid.Domain.server.latitude | string | |
| APIVoid.Domain.server.reverse_dns | string | |
| APIVoid.Domain.server.longitude | string | |
| APIVoid.Domain.server.country_name | string | |
| APIVoid.Domain.server.region_name | string | |
| APIVoid.Domain.server.country_code | string | |
| APIVoid.Domain.server.continent_name | string | |
| APIVoid.Domain.server.continent_code | string | |
| APIVoid.Domain.server.city_name | string | |
| APIVoid.Domain.alexa_top_250k | boolean | |
| APIVoid.Domain.alexa_top_10k | boolean | |
| APIVoid.Domain.most_abused_tld | boolean | |
| APIVoid.Domain.host | string | |
| APIVoid.Domain.blacklists.detection_rate | string | |
| APIVoid.Domain.blacklists.detections | number | |
| APIVoid.Domain.blacklists.engines.confidence | string | |
| APIVoid.Domain.blacklists.engines.detected | boolean | |
| APIVoid.Domain.blacklists.engines.elapsed | string | |
| APIVoid.Domain.blacklists.engines.engine | string | |
| APIVoid.Domain.blacklists.engines.reference | string | |
| APIVoid.Domain.blacklists.engines_count | number | |
| APIVoid.Domain.blacklists.scantime | string | |
| APIVoid.Domain.category.is_anonymizer | boolean | |
| APIVoid.Domain.category.is_free_dynamic_dns | boolean | |
| APIVoid.Domain.category.is_free_hosting | boolean | |
| APIVoid.Domain.category.is_url_shortener | boolean |
apivoid-url
Returns the reputation of the URL.
Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.
Base Command
apivoid-url
Input
| Argument Name | Description | Required |
|---|---|---|
| url | The URL to query. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| URL | unknown | |
| URL.Data | string | The URL |
| URL.DetectionEngines | number | The total number of engines that checked the indicator. |
| URL.PositiveDetections | number | The number of engines that positively detected the indicator as malicious. |
| DBotScore | unknown | |
| DBotScore.Indicator | string | The indicator that was tested. |
| DBotScore.Score | number | The actual score. |
| DBotScore.Type | string | The indicator type. |
| DBotScore.Vendor | string | The vendor used to calculate the score. |
| APIVoid.URL.risk_score.result | number | |
| APIVoid.URL.domain_blacklist.detections | number | |
| APIVoid.URL.domain_blacklist.engines.detected | boolean | |
| APIVoid.URL.domain_blacklist.engines.name | string | |
| APIVoid.URL.domain_blacklist.engines.reference | string | |
| APIVoid.URL.geo_location.countries | string | |
| APIVoid.URL.server_details.isp | string | |
| APIVoid.URL.server_details.ip | string | |
| APIVoid.URL.server_details.latitude | string | |
| APIVoid.URL.server_details.longitude | string | |
| APIVoid.URL.server_details.hostname | string | |
| APIVoid.URL.server_details.country_name | string | |
| APIVoid.URL.server_details.region_name | string | |
| APIVoid.URL.server_details.country_code | string | |
| APIVoid.URL.server_details.continent_name | string | |
| APIVoid.URL.server_details.continent_code | string | |
| APIVoid.URL.server_details.city_name | string | |
| APIVoid.URL.response_headers.server | string | |
| APIVoid.URL.response_headers.code | number | |
| APIVoid.URL.response_headers.content-type | string | |
| APIVoid.URL.response_headers.date | date | |
| APIVoid.URL.response_headers.cache-control | string | |
| APIVoid.URL.response_headers.host-header | string | |
| APIVoid.URL.response_headers.status | string | |
| APIVoid.URL.response_headers.x-redirect-by | string | |
| APIVoid.URL.response_headers.expires | date | |
| APIVoid.URL.response_headers.location | string | |
| APIVoid.URL.response_headers.content-length | string | |
| APIVoid.URL.response_headers.upgrade | string | |
| APIVoid.URL.response_headers.connection | string | |
| APIVoid.URL.security_checks.is_windows_exe_file_on_ipv4 | boolean | |
| APIVoid.URL.security_checks.is_credit_card_form | boolean | |
| APIVoid.URL.security_checks.is_windows_exe_file_on_free_hosting | boolean | |
| APIVoid.URL.security_checks.is_linux_elf_file_on_ipv4 | boolean | |
| APIVoid.URL.security_checks.is_linux_elf_file_on_free_hosting | boolean | |
| APIVoid.URL.security_checks.is_masked_windows_exe_file | boolean | |
| APIVoid.URL.security_checks.is_zip_on_directory_listing | boolean | |
| APIVoid.URL.security_checks.is_masked_linux_elf_file | boolean | |
| APIVoid.URL.security_checks.is_sinkholed_domain | boolean | |
| APIVoid.URL.security_checks.is_suspended_page | boolean | |
| APIVoid.URL.security_checks.is_suspicious_file_extension | boolean | |
| APIVoid.URL.security_checks.is_uncommon_clickable_url | boolean | |
| APIVoid.URL.security_checks.is_suspicious_content | boolean | |
| APIVoid.URL.security_checks.is_risky_geo_location | boolean | |
| APIVoid.URL.security_checks.is_php_on_directory_listing | boolean | |
| APIVoid.URL.security_checks.is_doc_on_directory_listing | boolean | |
| APIVoid.URL.security_checks.is_doc_on_directory_listing | boolean | |
| APIVoid.URL.security_checks.is_empty_page_title | boolean | |
| APIVoid.URL.security_checks.is_login_form | boolean | |
| APIVoid.URL.security_checks.is_robots_noindex | boolean | |
| APIVoid.URL.security_checks.is_suspicious_domain | boolean | |
| APIVoid.URL.security_checks.is_windows_exe_file_on_free_dynamic_dns | boolean | |
| APIVoid.URL.security_checks.is_most_abused_tld | boolean | |
| APIVoid.URL.security_checks.is_linux_elf_file_on_free_dynamic_dns | boolean | |
| APIVoid.URL.security_checks.is_suspicious_url_pattern | boolean | |
| APIVoid.URL.security_checks.is_valid_https | boolean | |
| APIVoid.URL.security_checks.is_exe_on_directory_listing | boolean | |
| APIVoid.URL.security_checks.is_pdf_on_directory_listing | boolean | |
| APIVoid.URL.security_checks.is_host_an_ipv4 | boolean | |
| APIVoid.URL.security_checks.is_domain_blacklisted | boolean | |
| APIVoid.URL.security_checks.is_china_country | boolean | |
| APIVoid.URL.security_checks.is_windows_exe_file | boolean | |
| APIVoid.URL.security_checks.is_masked_file | boolean | |
| APIVoid.URL.security_checks.is_email_address_on_url_query | boolean | |
| APIVoid.URL.security_checks.is_phishing_heuristic | boolean | |
| APIVoid.URL.security_checks.is_non_standard_port | boolean | |
| APIVoid.URL.security_checks.is_linux_elf_file | boolean | |
| APIVoid.URL.security_checks.is_defaced_heuristic | boolean | |
| APIVoid.URL.security_checks.is_directory_listing | boolean | |
| APIVoid.URL.dns_records.mx.records.country_code | string | |
| APIVoid.URL.dns_records.ns.records.country_name | string | |
| APIVoid.URL.dns_records.ns.records.ip | string | |
| APIVoid.URL.dns_records.ns.records.isp | string | |
| APIVoid.URL.dns_records.ns.records.target | string | |
| APIVoid.URL.redirection.external | boolean | |
| APIVoid.URL.redirection.found | boolean | |
| APIVoid.URL.redirection.url | string | |
| APIVoid.URL.url | string | |
| APIVoid.URL.url_parts.host | string | |
| APIVoid.URL.url_parts.host_nowww | string | |
| APIVoid.URL.url_parts.path | string | |
| APIVoid.URL.url_parts.port | number | |
| APIVoid.URL.url_parts.query | string | |
| APIVoid.URL.url_parts.scheme | string | |
| APIVoid.URL.site_category.is_anonymizer | boolean | |
| APIVoid.URL.site_category.is_free_dynamic_dns | boolean | |
| APIVoid.URL.site_category.is_free_hosting | boolean | |
| APIVoid.URL.site_category.is_torrent | boolean | |
| APIVoid.URL.site_category.is_url_shortener | boolean | |
| APIVoid.URL.site_category.is_vpn_provider | boolean | |
| APIVoid.URL.web_page.description | string | |
| APIVoid.URL.web_page.keywords | string | |
| APIVoid.URL.web_page.title | string | |
| APIVoid.URL.html_forms.credit_card_field_present | boolean | |
| APIVoid.URL.html_forms.email_field_present | boolean | |
| APIVoid.URL.html_forms.number_of_total_forms | number | |
| APIVoid.URL.html_forms.number_of_total_input_fields | number | |
| APIVoid.URL.html_forms.password_field_present | boolean | |
| APIVoid.URL.html_forms.two_text_inputs_in_a_form | boolean | |
| APIVoid.URL.file_type.extension | string | |
| APIVoid.URL.file_type.headers | string | |
| APIVoid.URL.file_type.signature | string |
ip
Returns the reputation of the IP.
Base Command
ip
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | The IP to query. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| IP | unknown | |
| IP.Address | string | IP address |
| IP.DetectionEngines | number | The total number of engines that checked the indicator. |
| IP.Geo | unknown | |
| IP.Geo.Country | string | The country in which the IP address is located. |
| IP.Geo.Description | string | Additional information about the location. |
| IP.Geo.Location | string | The geolocation where the IP address is located, in the format: latitude:longitude. |
| IP.Hostname | string | The hostname that is mapped to this IP address. |
| IP.PositiveDetections | number | The number of engines that positively detected the indicator as malicious. |
| DBotScore.Indicator | string | The indicator that was tested. |
| DBotScore.Score | number | The actual score. |
| DBotScore.Type | string | The indicator type. |
| DBotScore.Vendor | string | The vendor used to calculate the score. |
domain
Returns the reputation of the domain.
Base Command
domain
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | The Domain to query. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Domain.DNS | string | A list of IP objects resolved by DNS. |
| Domain.DetectionEngines | number | The total number of engines that checked the indicator. |
| Domain.Name | string | The domain name, for example: “google.com”. |
| Domain.PositiveDetections | number | The number of engines that positively detected the indicator as malicious. |
| DBotScore.Indicator | string | The indicator that was tested. |
| DBotScore.Score | number | The actual score. |
| DBotScore.Type | string | The indicator type. |
| DBotScore.Vendor | string | The vendor used to calculate the score. |
url
Returns the reputation of the URL.
Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.
Base Command
url
Input
| Argument Name | Description | Required |
|---|---|---|
| url | The URL to query. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| URL.Data | string | The URL |
| URL.DetectionEngines | number | The total number of engines that checked the indicator. |
| URL.PositiveDetections | number | The number of engines that positively detected the indicator as malicious. |
| URL.RiskScore | number | |
| URL.Score | string | |
| DBotScore | unknown | |
| DBotScore.Indicator | string | The indicator that was tested. |
| DBotScore.Score | number | The actual score. |
| DBotScore.Type | string | The indicator type. |
| DBotScore.Vendor | string | The vendor used to calculate the score. |
apivoid-dns-lookup
Gets DNS records of a host.
Base Command
apivoid-dns-lookup
Input
| Argument Name | Description | Required |
|---|---|---|
| host | Host to lookup. | Required |
| type | The DNS record type to lookup. Possible values are: A, AAAA, MX, NS, DMARK, Reverse, TXT, ANY, CNAME, SOA, SRV, CAA. Default is A. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| APIVoid.DNS | unknown | |
| APIVoid.DNS.items.host | string | |
| APIVoid.DNS.items.class | string | |
| APIVoid.DNS.items.ttl | number | |
| APIVoid.DNS.items.type | string | |
| APIVoid.DNS.items.ip | string | |
| APIVoid.DNS.found | boolean | |
| APIVoid.DNS.count | number | |
| APIVoid.DNS.items.ipv6 | string | |
| APIVoid.DNS.items.pri | number | |
| APIVoid.DNS.items.target | string | |
| APIVoid.DNS.items.txt | string | |
| APIVoid.DNS.items.entries | unknown | |
| APIVoid.DNS.items.mname | string | |
| APIVoid.DNS.items.rname | string | |
| APIVoid.DNS.items.serial | number | |
| APIVoid.DNS.items.refresh | number | |
| APIVoid.DNS.items.retry | number | |
| APIVoid.DNS.items.expire | number | |
| APIVoid.DNS.items.minimum-ttl | number | |
| APIVoid.DNS.items.weight | number | |
| APIVoid.DNS.items.port | number | |
| APIVoid.DNS.items.flags | number | |
| APIVoid.DNS.items.tag | string | |
| APIVoid.DNS.items.value | string |
apivoid-ssl-info
Get useful SSL information from a remote host
Base Command
apivoid-ssl-info
Input
| Argument Name | Description | Required |
|---|---|---|
| host | Host to lookup SSL. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| APIVoid.SSL | unknown | |
| APIVoid.SSL.found | boolean | |
| APIVoid.SSL.fingerprint | string | |
| APIVoid.SSL.deprecated_issuer | boolean | |
| APIVoid.SSL.expired | boolean | |
| APIVoid.SSL.valid_peer | boolean | |
| APIVoid.SSL.host | string | |
| APIVoid.SSL.name_match | boolean | |
| APIVoid.SSL.debug_message | string | |
| APIVoid.SSL.blacklisted | boolean | |
| APIVoid.SSL.valid | boolean | |
| APIVoid.SSL.details | unknown | |
| APIVoid.SSL.details.extensions | unknown | |
| APIVoid.SSL.details.extensions.authority_info_access | string | |
| APIVoid.SSL.details.extensions.authority_key_identifier | string | |
| APIVoid.SSL.details.extensions.basic_constraints | string | |
| APIVoid.SSL.details.extensions.certificate_policies | string | |
| APIVoid.SSL.details.extensions.crl_distribution_points | string | |
| APIVoid.SSL.details.extensions.extended_key_usage | string | |
| APIVoid.SSL.details.extensions.key_usage | string | |
| APIVoid.SSL.details.extensions.subject_key_identifier | string | |
| APIVoid.SSL.details.hash | string | |
| APIVoid.SSL.details.issuer | unknown | |
| APIVoid.SSL.details.issuer.common_name | string | |
| APIVoid.SSL.details.issuer.country | string | |
| APIVoid.SSL.details.issuer.location | string | |
| APIVoid.SSL.details.issuer.organization | string | |
| APIVoid.SSL.details.issuer.organization_unit | string | |
| APIVoid.SSL.details.issuer.state | string | |
| APIVoid.SSL.details.signature | unknown | |
| APIVoid.SSL.details.signature.serial | string | |
| APIVoid.SSL.details.signature.serial_hex | string | |
| APIVoid.SSL.details.signature.type | string | |
| APIVoid.SSL.details.subject | unknown | |
| APIVoid.SSL.details.subject.postal_code | string | |
| APIVoid.SSL.details.subject.street | string | |
| APIVoid.SSL.details.subject.name | string | |
| APIVoid.SSL.details.subject.organization_unit | string | |
| APIVoid.SSL.details.subject.state | string | |
| APIVoid.SSL.details.subject.organization | string | |
| APIVoid.SSL.details.subject.location | string | |
| APIVoid.SSL.details.subject.alternative_names | string | |
| APIVoid.SSL.details.subject.country | string | |
| APIVoid.SSL.details.subject.category | string | |
| APIVoid.SSL.details.subject.common_name | string | |
| APIVoid.SSL.details.validity | unknown | |
| APIVoid.SSL.details.validity.days_left | number | |
| APIVoid.SSL.details.validity.valid_from | date | |
| APIVoid.SSL.details.validity.valid_from_timestamp | date | |
| APIVoid.SSL.details.validity.valid_to | date | |
| APIVoid.SSL.details.validity.valid_to_timestamp | date | |
| APIVoid.SSL.details.version | string |
apivoid-email-verify
Checks if an email address is disposable, if it has MX records, and more.
Base Command
apivoid-email-verify
Input
| Argument Name | Description | Required |
|---|---|---|
| Email address to lookup. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| APIVoid.Email | unknown | |
| APIVoid.Email.email | string | |
| APIVoid.Email.valid_format | boolean | |
| APIVoid.Email.username | string | |
| APIVoid.Email.role_address | boolean | |
| APIVoid.Email.suspicious_username | boolean | |
| APIVoid.Email.dirty_words_username | boolean | |
| APIVoid.Email.domain | string | |
| APIVoid.Email.valid_tld | boolean | |
| APIVoid.Email.disposable | boolean | |
| APIVoid.Email.has_mx_records | boolean | |
| APIVoid.Email.free_email | boolean | |
| APIVoid.Email.russian_free_email | boolean | |
| APIVoid.Email.china_free_email | boolean | |
| APIVoid.Email.suspicious_domain | boolean | |
| APIVoid.Email.did_you_mean | string | |
| APIVoid.Email.dirty_words_domain | boolean | |
| APIVoid.Email.domain_popular | boolean | |
| APIVoid.Email.risky_tld | boolean | |
| APIVoid.Email.police_domain | boolean | |
| APIVoid.Email.government_domain | boolean | |
| APIVoid.Email.educational_domain | boolean | |
| APIVoid.Email.should_block | boolean | |
| APIVoid.Email.score | number |
apivoid-threatlog
Check if a website is present on ThreatLog database
Base Command
apivoid-threatlog
Input
| Argument Name | Description | Required |
|---|---|---|
| host | The host the check. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| APIVoid.ThreatLog.detected | boolean | |
| APIVoid.ThreatLog.host | string | |
| APIVoid.ThreatLog.scantime | string | |
| Domain.Name | string | The domain name, for example: “google.com”. |
apivoid-parked-domain
Detect if a domain (i.e google.com) is actually parked
Base Command
apivoid-parked-domain
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | Domain to check. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| APIVoid.ParkedDomain.host | string | |
| APIVoid.ParkedDomain.parked_domain | boolean | |
| Domain.Name | string | The domain name, for example: “google.com”. |
apivoid-domain-age
Get the registration date of a domain and the domain age in days
Base Command
apivoid-domain-age
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | The domain to check. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| APIVoid.DomainAge.debug_message | string | |
| APIVoid.DomainAge.domain_age_found | boolean | |
| APIVoid.DomainAge.domain_age_in_days | number | |
| APIVoid.DomainAge.domain_age_in_months | number | |
| APIVoid.DomainAge.domain_age_in_years | number | |
| APIVoid.DomainAge.domain_creation_date | string | |
| APIVoid.DomainAge.domain_registered | string | |
| APIVoid.DomainAge.host | string | |
| Domain.CreationDate | date | The date that the domain was created. |
| Domain.Name | string | The domain name, for example: “google.com”. |
apivoid-url-to-image
Capture a high-quality screenshot of any website or URL
Base Command
apivoid-url-to-image
Input
| Argument Name | Description | Required |
|---|---|---|
| url | URL to capture screenshot of. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| File.Size | number | The size of the file. |
| File.SHA1 | string | The SHA1 hash of the file. |
| File.SHA256 | string | The SHA256 hash of the file. |
| File.SHA512 | string | The SHA512 hash of the file. |
| File.Name | string | The name of the file. |
| File.SSDeep | string | The SSDeep hash of the file. |
| File.EntryID | string | The EntryID of the file. |
| File.Info | string | Info regarding the file. |
| File.Type | string | The type of the file. |
| File.MD5 | string | The MD5 hash of the file. |
| File.Extension | string | The extension of the file. |
apivoid-url-to-pdf
Convert an URL info high-quality and printable PDF document
Base Command
apivoid-url-to-pdf
Input
| Argument Name | Description | Required |
|---|---|---|
| url | URL to create PDF of. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| File.Size | number | The size of the file. |
| File.SHA1 | string | The SHA1 hash of the file. |
| File.SHA256 | string | The SHA256 hash of the file. |
| File.SHA512 | string | The SHA512 hash of the file. |
| File.Name | string | The name of the file. |
| File.SSDeep | string | The SSDeep hash of the file. |
| File.EntryID | string | The EntryID of the file. |
| File.Info | string | Info regarding the file. |
| File.Type | string | The type of the file. |
| File.MD5 | string | The MD5 hash of the file. |
| File.Extension | string | The extension of the file. |
apivoid-url-to-html
Get the body of an html page after javascript has been executed
Base Command
apivoid-url-to-html
Input
| Argument Name | Description | Required |
|---|---|---|
| url | URL to create PDF of. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| File.Size | number | The size of the file. |
| File.SHA1 | string | The SHA1 hash of the file. |
| File.SHA256 | string | The SHA256 hash of the file. |
| File.SHA512 | string | The SHA512 hash of the file. |
| File.Name | string | The name of the file. |
| File.SSDeep | string | The SSDeep hash of the file. |
| File.EntryID | string | The EntryID of the file. |
| File.Info | string | Info regarding the file. |
| File.Type | string | The type of the file. |
| File.MD5 | string | The MD5 hash of the file. |
| File.Extension | string | The extension of the file. |
apivoid-site-trustworthiness
A smart API that accurately checks a website’s trustworthiness.
Base Command
apivoid-site-trustworthiness
Input
| Argument Name | Description | Required |
|---|---|---|
| host | The host to check. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| APIVoid.SiteTrust.domain_blacklist.detections | number | |
| APIVoid.SiteTrust.domain_blacklist.engines.detected | boolean | |
| APIVoid.SiteTrust.domain_blacklist.engines.name | string | |
| APIVoid.SiteTrust.domain_blacklist.engines.reference | string | |
| APIVoid.SiteTrust.geo_location.countries | unknown | |
| APIVoid.SiteTrust.domain_age.domain_age_in_days | number | |
| APIVoid.SiteTrust.domain_age.domain_age_in_months | number | |
| APIVoid.SiteTrust.domain_age.domain_age_in_years | number | |
| APIVoid.SiteTrust.domain_age.domain_creation_date | string | |
| APIVoid.SiteTrust.domain_age.found | boolean | |
| APIVoid.SiteTrust.server_details.isp | string | |
| APIVoid.SiteTrust.server_details.ip | string | |
| APIVoid.SiteTrust.server_details.latitude | number | |
| APIVoid.SiteTrust.server_details.longitude | number | |
| APIVoid.SiteTrust.server_details.hostname | string | |
| APIVoid.SiteTrust.server_details.country_name | string | |
| APIVoid.SiteTrust.server_details.region_name | string | |
| APIVoid.SiteTrust.server_details.country_code | string | |
| APIVoid.SiteTrust.server_details.continent_name | string | |
| APIVoid.SiteTrust.server_details.continent_code | string | |
| APIVoid.SiteTrust.server_details.city_name | string | |
| APIVoid.SiteTrust.response_headers.server | string | |
| APIVoid.SiteTrust.response_headers.content-encoding | string | |
| APIVoid.SiteTrust.response_headers.code | number | |
| APIVoid.SiteTrust.response_headers.content-type | string | |
| APIVoid.SiteTrust.response_headers.date | date | |
| APIVoid.SiteTrust.response_headers.vary | string | |
| APIVoid.SiteTrust.response_headers.status | string | |
| APIVoid.SiteTrust.response_headers.x-amz-rid | string | |
| APIVoid.SiteTrust.response_headers.content-length | string | |
| APIVoid.SiteTrust.response_headers.connection | string | |
| APIVoid.SiteTrust.host | string | |
| APIVoid.SiteTrust.security_checks.is_website_popular | boolean | |
| APIVoid.SiteTrust.security_checks.is_suspended_site | boolean | |
| APIVoid.SiteTrust.security_checks.is_domain_recent | string | |
| APIVoid.SiteTrust.security_checks.is_heuristic_pattern | boolean | |
| APIVoid.SiteTrust.security_checks.is_sinkholed_domain | boolean | |
| APIVoid.SiteTrust.security_checks.is_risky_geo_location | boolean | |
| APIVoid.SiteTrust.security_checks.is_empty_page_title | boolean | |
| APIVoid.SiteTrust.security_checks.is_robots_noindex | boolean | |
| APIVoid.SiteTrust.security_checks.is_suspicious_domain | boolean | |
| APIVoid.SiteTrust.security_checks.is_most_abused_tld | boolean | |
| APIVoid.SiteTrust.security_checks.is_valid_https | boolean | |
| APIVoid.SiteTrust.security_checks.is_domain_blacklisted | boolean | |
| APIVoid.SiteTrust.security_checks.is_email_configured | boolean | |
| APIVoid.SiteTrust.security_checks.is_china_country | boolean | |
| APIVoid.SiteTrust.security_checks.is_directory_listing | boolean | |
| APIVoid.SiteTrust.security_checks.is_free_email | boolean | |
| APIVoid.SiteTrust.trust_score.result | number | |
| APIVoid.SiteTrust.dns_records | unknown | |
| APIVoid.SiteTrust.redirection.external | boolean | |
| APIVoid.SiteTrust.redirection.found | boolean | |
| APIVoid.SiteTrust.redirection.url | string | |
| APIVoid.SiteTrust.url_parts.host | string | |
| APIVoid.SiteTrust.url_parts.host_nowww | string | |
| APIVoid.SiteTrust.url_parts.path | string | |
| APIVoid.SiteTrust.url_parts.port | string | |
| APIVoid.SiteTrust.url_parts.query | string | |
| APIVoid.SiteTrust.url_parts.scheme | string | |
| APIVoid.SiteTrust.ecommerce_platform.is_magento | boolean | |
| APIVoid.SiteTrust.ecommerce_platform.is_opencart | boolean | |
| APIVoid.SiteTrust.ecommerce_platform.is_prestashop | boolean | |
| APIVoid.SiteTrust.ecommerce_platform.is_shopify | boolean | |
| APIVoid.SiteTrust.ecommerce_platform.is_woocommerce | boolean | |
| APIVoid.SiteTrust.ecommerce_platform.is_zencart | boolean | |
| APIVoid.SiteTrust.web_page.description | string | |
| APIVoid.SiteTrust.web_page.keywords | string | |
| APIVoid.SiteTrust.web_page.title | string | |
| APIVoid.SiteTrust.targeted_brands.patagonia | boolean | |
| APIVoid.SiteTrust.targeted_brands.rolex | boolean | |
| APIVoid.SiteTrust.targeted_brands.timberland | boolean | |
| APIVoid.SiteTrust.targeted_brands.hugoboss | boolean | |
| APIVoid.SiteTrust.targeted_brands.moncler | boolean | |
| APIVoid.SiteTrust.targeted_brands.longchamp | boolean | |
| APIVoid.SiteTrust.targeted_brands.abercrombie | boolean | |
| APIVoid.SiteTrust.targeted_brands.montblanc | boolean | |
| APIVoid.SiteTrust.targeted_brands.carhartt | boolean | |
| APIVoid.SiteTrust.targeted_brands.rayban | boolean | |
| APIVoid.SiteTrust.targeted_brands.drmartens | boolean | |
| APIVoid.SiteTrust.targeted_brands.hermes | boolean | |
| APIVoid.SiteTrust.targeted_brands.oakley | boolean | |
| APIVoid.SiteTrust.targeted_brands.michaelkors | boolean | |
| APIVoid.SiteTrust.targeted_brands.louisvuitton | boolean | |
| APIVoid.SiteTrust.targeted_brands.birkenstock | boolean | |
| APIVoid.SiteTrust.targeted_brands.adidas | boolean | |
| APIVoid.SiteTrust.targeted_brands.vans | boolean | |
| APIVoid.SiteTrust.targeted_brands.ralphlauren | boolean | |
| APIVoid.SiteTrust.targeted_brands.mulberry | boolean | |
| APIVoid.SiteTrust.targeted_brands.converse | boolean | |
| APIVoid.SiteTrust.targeted_brands.versace | boolean | |
| APIVoid.SiteTrust.targeted_brands.ugg | boolean | |
| APIVoid.SiteTrust.targeted_brands.nike | boolean | |
| APIVoid.SiteTrust.targeted_brands.swarovski | boolean | |
| APIVoid.SiteTrust.targeted_brands.peuterey | boolean | |
| APIVoid.SiteTrust.targeted_brands.cartier | boolean | |
| APIVoid.SiteTrust.targeted_brands.pandora | boolean | |
| APIVoid.SiteTrust.targeted_brands.burberry | boolean | |
| APIVoid.SiteTrust.targeted_brands.gucci | boolean | |
| APIVoid.SiteTrust.targeted_brands.salomon | boolean | |
| APIVoid.SiteTrust.targeted_brands.liujo | boolean | |
| APIVoid.SiteTrust.targeted_brands.truereligion | boolean |
Configuration parameters
url— Server URL (required)credentials—apikey— API KEYsuspicious— Suspicious Reputation (Percentage) (required)bad— Bad Reputation (Percentage) (required)malicious— Malicious (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settingsintegrationReliability— Source ReliabilityfeedExpirationPolicy—feedExpirationInterval—
Commands (16)
-
apivoid-dns-lookupGets DNS records of a host.
-
apivoid-domainReturns the reputation of the domain.
-
apivoid-domain-ageGet the registration date of a domain and the domain age in days
-
apivoid-email-verifyChecks if an email address is disposable, if it has MX records, and more.
-
apivoid-ipReturns the reputation and extended context of the IP.
-
apivoid-parked-domainDetect if a domain (i.e google.com) is actually parked
-
apivoid-site-trustworthinessA smart API that accurately checks a website's trustworthiness.
-
apivoid-ssl-infoGet useful SSL information from a remote host
-
apivoid-threatlogDeprecatedDeprecated. This command is deprecated because it is not supported in API V2. Check if a website is present on ThreatLog database.
-
apivoid-urlReturns the reputation of the URL.
-
apivoid-url-to-htmlDeprecatedDeprecated. This command is deprecated because it is not supported in API V2. Get the body of an html page after javascript has been executed.
-
apivoid-url-to-imageCapture a high-quality screenshot of any website or URL
-
apivoid-url-to-pdfConvert an URL info high-quality and printable PDF document
-
domainReturns the reputation of the domain.
-
ipReturns the reputation of the IP.
-
urlReturns the reputation of the URL.
""" Unit tests for APIVoid integration Tests all commands, helper functions, and error handling scenarios with strict HTTP request validation """ import pytest import json import os from CommonServerPython import * from APIVoid import ( Client, calculate_dbot_score, ip_reputation_command, domain_reputation_command, url_reputation_command, dns_lookup_command, ssl_info_command, email_verify_command, parked_domain_command, domain_age_command, screenshot_command, url_to_pdf_command, site_trustworthiness_command, test_module as module_test, main, ) # ============================================================================ # HELPER FUNCTION TO LOAD MOCK DATA FROM FILES # ============================================================================ def load_mock_response(filename: str) -> dict: """ Load mock response data from JSON file in test_data directory Args: filename: Name of the JSON file (e.g., 'ip-reputation-response.json') Returns: Dictionary containing the mock response data """ test_data_dir = os.path.join(os.path.dirname(__file__), "test_data") file_path = os.path.join(test_data_dir, filename) with open(file_path) as f: return json.load(f) # ============================================================================ # MOCK DATA - V2 API Responses (loaded from files) # ============================================================================ MOCK_IP_RESPONSE = load_mock_response("ip-reputation-response.json") MOCK_DOMAIN_RESPONSE = load_mock_response("domain-reputation-response.json") MOCK_URL_RESPONSE = load_mock_response("url-reputation-response.json") MOCK_DNS_RESPONSE = load_mock_response("dns-lookup-response.json") MOCK_SSL_RESPONSE = load_mock_response("ssl-info-response.json") MOCK_EMAIL_RESPONSE = load_mock_response("email-verify-response.json") MOCK_PARKED_DOMAIN_RESPONSE = load_mock_response("parked-domain-response.json") MOCK_DOMAIN_AGE_RESPONSE = load_mock_response("domain-age-response.json") MOCK_SCREENSHOT_RESPONSE = load_mock_response("screenshot-response.json") MOCK_PDF_RESPONSE = load_mock_response("pdf-response.json") MOCK_SITE_TRUST_RESPONSE = load_mock_response("site-trust-response.json") MOCK_ERROR_RESPONSE = load_mock_response("error-response.json") # ============================================================================ # FIXTURES # ============================================================================ @pytest.fixture def client(): """ Create a test client instance Given: Valid API credentials When: Client is initialized Then: Client should be created with proper headers """ return Client(base_url="https://api.apivoid.com", apikey="test-api-key", verify=False, proxy=False) @pytest.fixture def mock_demisto(mocker): """ Mock demisto functions Given: Demisto environment When: Tests are run Then: Demisto functions should be mocked """ mocker.patch.object( demisto, "params", return_value={ "credentials": {"password": "test-api-key"}, "insecure": False, "proxy": False, "integrationReliability": "C - Fairly reliable", "suspicious": "30", "bad": "60", }, ) mocker.patch.object(demisto, "args", return_value={}) mocker.patch.object(demisto, "command", return_value="test-module") mocker.patch.object(demisto, "results") mocker.patch.object(demisto, "debug") return mocker # ============================================================================ # TEST CLIENT CLASS WITH STRICT REQUEST VALIDATION # ============================================================================ class TestClientWithStrictValidation: """Test Client class with strict HTTP request validation""" def test_client_initialization(self, client): """ Test client initialization Given: Valid API credentials When: Client is initialized Then: Headers should contain API key and Content-Type """ assert client._headers["X-API-Key"] == "test-api-key" assert client._headers["Content-Type"] == "application/json" assert client._base_url == "https://api.apivoid.com" def test_api_request_validates_method(self, client, mocker): """ Test API request uses POST method Given: A client instance When: api_request is called Then: Should use POST method """ mock_http = mocker.patch.object(client, "_http_request", return_value={"result": "success"}) client.api_request("/v2/test", {"param": "value"}) # Validate exact method assert mock_http.call_args[1]["method"] == "POST" def test_api_request_validates_url_suffix(self, client, mocker): """ Test API request uses correct URL suffix Given: A client instance When: api_request is called with endpoint Then: Should use exact URL suffix """ mock_http = mocker.patch.object(client, "_http_request", return_value={"result": "success"}) client.api_request("/v2/ip-reputation", {"ip": "8.8.8.8"}) # Validate exact URL suffix assert mock_http.call_args[1]["url_suffix"] == "/v2/ip-reputation" def test_api_request_validates_json_data(self, client, mocker): """ Test API request sends correct JSON data Given: A client instance When: api_request is called with data Then: Should send exact JSON data """ mock_http = mocker.patch.object(client, "_http_request", return_value={"result": "success"}) test_data = {"ip": "8.8.8.8"} client.api_request("/v2/ip-reputation", test_data) # Validate exact JSON data assert mock_http.call_args[1]["json_data"] == test_data def test_api_request_validates_headers(self, client, mocker): """ Test API request includes correct headers Given: A client instance When: api_request is called Then: Should include X-API-Key and Content-Type headers """ mocker.patch.object(client, "_http_request", return_value={"result": "success"}) client.api_request("/v2/test", {"param": "value"}) # Validate headers are set in client assert client._headers["X-API-Key"] == "test-api-key" assert client._headers["Content-Type"] == "application/json" # ============================================================================ # TEST IP REPUTATION WITH STRICT REQUEST VALIDATION # ============================================================================ class TestIpReputationWithStrictValidation: """Test IP reputation command with strict HTTP request validation""" def test_ip_reputation_request_validation(self, client, mocker): """ Test IP reputation sends exact request format Given: Valid IP address When: ip_reputation_command is called Then: Should send POST to /v2/ip-reputation with exact JSON body {"ip": "value"} """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_IP_RESPONSE) args = {"ip": "8.8.8.8"} thresholds = {"suspicious": 30, "bad": 60} ip_reputation_command(client, args, False, thresholds, "C - Fairly reliable") # Strict validation of request mock_http.assert_called_once() call_kwargs = mock_http.call_args[1] assert call_kwargs["method"] == "POST" assert call_kwargs["url_suffix"] == "/v2/ip-reputation" assert call_kwargs["json_data"] == {"ip": "8.8.8.8"} def test_ip_reputation_different_ip_addresses(self, client, mocker): """ Test IP reputation with different IP addresses Given: Different IP addresses When: ip_reputation_command is called Then: Should send correct IP in request body """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_IP_RESPONSE) thresholds = {"suspicious": 30, "bad": 60} test_ips = ["8.8.8.8", "1.1.1.1", "192.168.1.1", "10.0.0.1"] for test_ip in test_ips: mock_http.reset_mock() args = {"ip": test_ip} ip_reputation_command(client, args, False, thresholds, "C - Fairly reliable") # Validate exact IP in request assert mock_http.call_args[1]["json_data"]["ip"] == test_ip def test_ip_reputation_success(self, client, mocker): """ Test successful IP reputation check Given: Valid IP address When: ip_reputation_command is called Then: Should return CommandResults with IP indicator """ mocker.patch.object(client, "_http_request", return_value=MOCK_IP_RESPONSE) args = {"ip": "8.8.8.8"} thresholds = {"suspicious": 30, "bad": 60} result = ip_reputation_command(client, args, False, thresholds, "C - Fairly reliable") assert isinstance(result, CommandResults) assert result.indicator.ip == "8.8.8.8" assert result.outputs_prefix == "APIVoid.IP" assert result.outputs_key_field == "ip" # ============================================================================ # TEST DOMAIN REPUTATION WITH STRICT REQUEST VALIDATION # ============================================================================ class TestDomainReputationWithStrictValidation: """Test domain reputation command with strict HTTP request validation""" def test_domain_reputation_request_validation(self, client, mocker): """ Test domain reputation sends exact request format Given: Valid domain When: domain_reputation_command is called Then: Should send POST to /v2/domain-reputation with exact JSON body {"host": "value"} """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_DOMAIN_RESPONSE) args = {"domain": "google.com"} thresholds = {"suspicious": 30, "bad": 60} domain_reputation_command(client, args, False, thresholds, "C - Fairly reliable") # Strict validation of request mock_http.assert_called_once() call_kwargs = mock_http.call_args[1] assert call_kwargs["method"] == "POST" assert call_kwargs["url_suffix"] == "/v2/domain-reputation" assert call_kwargs["json_data"] == {"host": "google.com"} def test_domain_reputation_different_domains(self, client, mocker): """ Test domain reputation with different domains Given: Different domains When: domain_reputation_command is called Then: Should send correct domain in request body """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_DOMAIN_RESPONSE) thresholds = {"suspicious": 30, "bad": 60} test_domains = ["example.com", "google.com", "test.org", "subdomain.example.com"] for test_domain in test_domains: mock_http.reset_mock() args = {"domain": test_domain} domain_reputation_command(client, args, False, thresholds, "C - Fairly reliable") # Validate exact domain in request assert mock_http.call_args[1]["json_data"]["host"] == test_domain # ============================================================================ # TEST URL REPUTATION WITH STRICT REQUEST VALIDATION # ============================================================================ class TestUrlReputationWithStrictValidation: """Test URL reputation command with strict HTTP request validation""" def test_url_reputation_request_validation(self, client, mocker): """ Test URL reputation sends exact request format Given: Valid URL When: url_reputation_command is called Then: Should send POST to /v2/url-reputation with exact JSON body {"url": "value"} """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_URL_RESPONSE) args = {"url": "https://example.com"} thresholds = {"suspicious": 30, "bad": 60} url_reputation_command(client, args, False, thresholds, "C - Fairly reliable") # Strict validation of request mock_http.assert_called_once() call_kwargs = mock_http.call_args[1] assert call_kwargs["method"] == "POST" assert call_kwargs["url_suffix"] == "/v2/url-reputation" assert call_kwargs["json_data"] == {"url": "https://example.com"} def test_url_reputation_different_urls(self, client, mocker): """ Test URL reputation with different URLs Given: Different URLs When: url_reputation_command is called Then: Should send correct URL in request body """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_URL_RESPONSE) thresholds = {"suspicious": 30, "bad": 60} test_urls = [ "https://example.com", "http://test.org/path", "https://www.disney.com?param=value", ] for test_url in test_urls: mock_http.reset_mock() args = {"url": test_url} url_reputation_command(client, args, False, thresholds, "C - Fairly reliable") # Validate exact URL in request assert mock_http.call_args[1]["json_data"]["url"] == test_url # ============================================================================ # TEST DNS LOOKUP WITH STRICT REQUEST VALIDATION # ============================================================================ class TestDnsLookupWithStrictValidation: """Test DNS lookup command with strict HTTP request validation""" def test_dns_lookup_request_validation(self, client, mocker): """ Test DNS lookup sends exact request format Given: Valid host and DNS type When: dns_lookup_command is called Then: Should send POST to /v2/dns-lookup with exact JSON body {"host": "value", "dns_types": "type"} """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_DNS_RESPONSE) args = {"host": "example.com", "type": "A"} dns_lookup_command(client, args) # Strict validation of request mock_http.assert_called_once() call_kwargs = mock_http.call_args[1] assert call_kwargs["method"] == "POST" assert call_kwargs["url_suffix"] == "/v2/dns-lookup" assert call_kwargs["json_data"] == {"host": "example.com", "dns_types": "A"} def test_dns_lookup_default_type(self, client, mocker): """ Test DNS lookup with default type Given: Host without type specified When: dns_lookup_command is called Then: Should default to A record in request """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_DNS_RESPONSE) args = {"host": "example.com"} dns_lookup_command(client, args) # Validate default type is A assert mock_http.call_args[1]["json_data"]["dns_types"] == "A" def test_dns_lookup_different_types(self, client, mocker): """ Test DNS lookup with different DNS types Given: Different DNS types When: dns_lookup_command is called Then: Should send correct dns_types in request """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_DNS_RESPONSE) test_types = ["A", "AAAA", "MX", "NS", "TXT", "A,AAAA,MX,NS,TXT,SOA,DMARC,CAA,SRV"] for dns_type in test_types: mock_http.reset_mock() args = {"host": "example.com", "type": dns_type} dns_lookup_command(client, args) # Validate exact dns_types in request assert mock_http.call_args[1]["json_data"]["dns_types"] == dns_type # ============================================================================ # TEST SSL INFO WITH STRICT REQUEST VALIDATION # ============================================================================ class TestSslInfoWithStrictValidation: """Test SSL info command with strict HTTP request validation""" def test_ssl_info_request_validation(self, client, mocker): """ Test SSL info sends exact request format Given: Valid host When: ssl_info_command is called Then: Should send POST to /v2/ssl-info with exact JSON body {"host": "value"} """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_SSL_RESPONSE) args = {"host": "paypal.com"} ssl_info_command(client, args) # Strict validation of request mock_http.assert_called_once() call_kwargs = mock_http.call_args[1] assert call_kwargs["method"] == "POST" assert call_kwargs["url_suffix"] == "/v2/ssl-info" assert call_kwargs["json_data"] == {"host": "paypal.com"} def test_ssl_info_different_hosts(self, client, mocker): """ Test SSL info with different hosts Given: Different hosts When: ssl_info_command is called Then: Should send correct host in request body """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_SSL_RESPONSE) test_hosts = ["example.com", "google.com", "github.com"] for test_host in test_hosts: mock_http.reset_mock() args = {"host": test_host} ssl_info_command(client, args) # Validate exact host in request assert mock_http.call_args[1]["json_data"]["host"] == test_host # ============================================================================ # TEST EMAIL VERIFY WITH STRICT REQUEST VALIDATION # ============================================================================ class TestEmailVerifyWithStrictValidation: """Test email verify command with strict HTTP request validation""" def test_email_verify_request_validation(self, client, mocker): """ Test email verify sends exact request format Given: Valid email address When: email_verify_command is called Then: Should send POST to /v2/email-verify with exact JSON body {"email": "value"} """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_EMAIL_RESPONSE) args = {"email": "test@test.com"} email_verify_command(client, args) # Strict validation of request mock_http.assert_called_once() call_kwargs = mock_http.call_args[1] assert call_kwargs["method"] == "POST" assert call_kwargs["url_suffix"] == "/v2/email-verify" assert call_kwargs["json_data"] == {"email": "test@test.com"} def test_email_verify_different_emails(self, client, mocker): """ Test email verify with different email addresses Given: Different email addresses When: email_verify_command is called Then: Should send correct email in request body """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_EMAIL_RESPONSE) test_emails = ["test@example.com", "user@domain.org", "admin@company.co.uk"] for test_email in test_emails: mock_http.reset_mock() args = {"email": test_email} email_verify_command(client, args) # Validate exact email in request assert mock_http.call_args[1]["json_data"]["email"] == test_email # ============================================================================ # TEST PARKED DOMAIN WITH STRICT REQUEST VALIDATION # ============================================================================ class TestParkedDomainWithStrictValidation: """Test parked domain command with strict HTTP request validation""" def test_parked_domain_request_validation(self, client, mocker): """ Test parked domain sends exact request format Given: Valid domain When: parked_domain_command is called Then: Should send POST to /v2/parked-domain with exact JSON body {"host": "value"} """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_PARKED_DOMAIN_RESPONSE) args = {"domain": "example.com"} parked_domain_command(client, args) # Strict validation of request mock_http.assert_called_once() call_kwargs = mock_http.call_args[1] assert call_kwargs["method"] == "POST" assert call_kwargs["url_suffix"] == "/v2/parked-domain" assert call_kwargs["json_data"] == {"host": "example.com"} def test_parked_domain_different_domains(self, client, mocker): """ Test parked domain with different domains Given: Different domains When: parked_domain_command is called Then: Should send correct domain in request body """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_PARKED_DOMAIN_RESPONSE) test_domains = ["test.com", "example.org", "parked.net"] for test_domain in test_domains: mock_http.reset_mock() args = {"domain": test_domain} parked_domain_command(client, args) # Validate exact domain in request assert mock_http.call_args[1]["json_data"]["host"] == test_domain # ============================================================================ # TEST DOMAIN AGE WITH STRICT REQUEST VALIDATION # ============================================================================ class TestDomainAgeWithStrictValidation: """Test domain age command with strict HTTP request validation""" def test_domain_age_request_validation(self, client, mocker): """ Test domain age sends exact request format Given: Valid domain When: domain_age_command is called Then: Should send POST to /v2/domain-age with exact JSON body {"host": "value"} """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_DOMAIN_AGE_RESPONSE) args = {"domain": "example.com"} domain_age_command(client, args) # Strict validation of request mock_http.assert_called_once() call_kwargs = mock_http.call_args[1] assert call_kwargs["method"] == "POST" assert call_kwargs["url_suffix"] == "/v2/domain-age" assert call_kwargs["json_data"] == {"host": "example.com"} def test_domain_age_different_domains(self, client, mocker): """ Test domain age with different domains Given: Different domains When: domain_age_command is called Then: Should send correct domain in request body """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_DOMAIN_AGE_RESPONSE) test_domains = ["google.com", "amazon.com", "old-domain.org"] for test_domain in test_domains: mock_http.reset_mock() args = {"domain": test_domain} domain_age_command(client, args) # Validate exact domain in request assert mock_http.call_args[1]["json_data"]["host"] == test_domain # ============================================================================ # TEST SCREENSHOT WITH STRICT REQUEST VALIDATION # ============================================================================ class TestScreenshotWithStrictValidation: """Test screenshot command with strict HTTP request validation""" def test_screenshot_request_validation(self, client, mocker): """ Test screenshot sends exact request format Given: Valid URL When: screenshot_command is called Then: Should send POST to /v2/screenshot with exact JSON body {"url": "value"} """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_SCREENSHOT_RESPONSE) mocker.patch("APIVoid.fileResult", return_value={"Type": 3, "File": "test.png"}) args = {"url": "https://example.com"} screenshot_command(client, args) # Strict validation of request mock_http.assert_called_once() call_kwargs = mock_http.call_args[1] assert call_kwargs["method"] == "POST" assert call_kwargs["url_suffix"] == "/v2/screenshot" assert call_kwargs["json_data"] == {"url": "https://example.com"} # ============================================================================ # TEST URL TO PDF WITH STRICT REQUEST VALIDATION # ============================================================================ class TestUrlToPdfWithStrictValidation: """Test URL to PDF command with strict HTTP request validation""" def test_url_to_pdf_request_validation(self, client, mocker): """ Test URL to PDF sends exact request format Given: Valid URL When: url_to_pdf_command is called Then: Should send POST to /v2/url-to-pdf with exact JSON body {"url": "value"} """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_PDF_RESPONSE) mocker.patch("APIVoid.fileResult", return_value={"Type": 3, "File": "test.pdf"}) args = {"url": "https://example.com"} url_to_pdf_command(client, args) # Strict validation of request mock_http.assert_called_once() call_kwargs = mock_http.call_args[1] assert call_kwargs["method"] == "POST" assert call_kwargs["url_suffix"] == "/v2/url-to-pdf" assert call_kwargs["json_data"] == {"url": "https://example.com"} # ============================================================================ # TEST SITE TRUSTWORTHINESS WITH STRICT REQUEST VALIDATION # ============================================================================ class TestSiteTrustworthinessWithStrictValidation: """Test site trustworthiness command with strict HTTP request validation""" def test_site_trust_request_validation(self, client, mocker): """ Test site trustworthiness sends exact request format Given: Valid host When: site_trustworthiness_command is called Then: Should send POST to /v2/site-trust with exact JSON body {"host": "value"} """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_SITE_TRUST_RESPONSE) args = {"host": "amazon.com"} site_trustworthiness_command(client, args) # Strict validation of request mock_http.assert_called_once() call_kwargs = mock_http.call_args[1] assert call_kwargs["method"] == "POST" assert call_kwargs["url_suffix"] == "/v2/site-trust" assert call_kwargs["json_data"] == {"host": "amazon.com"} def test_site_trust_different_hosts(self, client, mocker): """ Test site trustworthiness with different hosts Given: Different hosts When: site_trustworthiness_command is called Then: Should send correct host in request body """ mock_http = mocker.patch.object(client, "_http_request", return_value=MOCK_SITE_TRUST_RESPONSE) test_hosts = ["google.com", "microsoft.com", "apple.com"] for test_host in test_hosts: mock_http.reset_mock() args = {"host": test_host} site_trustworthiness_command(client, args) # Validate exact host in request assert mock_http.call_args[1]["json_data"]["host"] == test_host # ============================================================================ # TEST HELPER FUNCTIONS # ============================================================================ class TestCalculateDbotScore: """Test DBot score calculation logic""" def test_score_good_zero_detections(self): """ Test DBot score calculation with zero detections Given: 0 detections out of 10 engines_count (0%) When: calculate_dbot_score is called Then: Score should be GOOD (1) """ score = calculate_dbot_score(engines_count=10, detections=0, thresholds={"suspicious": 30, "bad": 60}) assert score == Common.DBotScore.GOOD def test_score_good_below_suspicious_threshold(self): """ Test DBot score calculation below suspicious threshold (previously 'gap' area) Given: 20 detections out of 100 engines_count (20%) When: calculate_dbot_score is called with suspicious threshold 30% Then: Score should be GOOD (1) """ score = calculate_dbot_score(engines_count=100, detections=20, thresholds={"suspicious": 30, "bad": 60}) assert score == Common.DBotScore.GOOD def test_score_suspicious(self): """ Test DBot score calculation in suspicious range Given: 40 detections out of 100 engines_count (40%) When: calculate_dbot_score is called with thresholds 30/60 Then: Score should be SUSPICIOUS (2) """ score = calculate_dbot_score(engines_count=100, detections=40, thresholds={"suspicious": 30, "bad": 60}) assert score == Common.DBotScore.SUSPICIOUS def test_score_bad(self): """ Test DBot score calculation in bad range Given: 70 detections out of 100 engines_count (70%) When: calculate_dbot_score is called with bad threshold 60% Then: Score should be BAD (3) """ score = calculate_dbot_score(engines_count=100, detections=70, thresholds={"suspicious": 30, "bad": 60}) assert score == Common.DBotScore.BAD def test_score_none_zero_engines(self): """ Test DBot score calculation with zero engines_count Given: 0 engines_count When: calculate_dbot_score is called Then: Score should be NONE (0) """ score = calculate_dbot_score(engines_count=0, detections=0, thresholds={"suspicious": 30, "bad": 60}) assert score == Common.DBotScore.NONE # ============================================================================ # TEST MALICIOUS DESCRIPTION IN DBOT SCORE # ============================================================================ class TestMaliciousDescription: """Test malicious_description in DBotScore when score is BAD""" def test_ip_reputation_bad_score_has_malicious_description(self, client, mocker): """ Test IP reputation with BAD score includes malicious_description Given: IP with high detection rate (80%) When: ip_reputation_command is called with bad threshold 60% Then: DBotScore should have malicious_description with detection rate """ # Create mock response with high detection rate mock_response = MOCK_IP_RESPONSE.copy() mock_response["blacklists"]["detections"] = 8 mock_response["blacklists"]["engines_count"] = 10 mocker.patch.object(client, "_http_request", return_value=mock_response) args = {"ip": "8.8.8.8"} thresholds = {"suspicious": 30, "bad": 60} result = ip_reputation_command(client, args, False, thresholds, "C - Fairly reliable") # Verify DBotScore has malicious_description assert result.indicator.dbot_score.score == Common.DBotScore.BAD assert result.indicator.dbot_score.malicious_description == "Detection rate of 8/10" def test_domain_reputation_bad_score_has_malicious_description(self, client, mocker): """ Test domain reputation with BAD score includes malicious_description Given: Domain with high detection rate (70%) When: domain_reputation_command is called with bad threshold 60% Then: DBotScore should have malicious_description with detection rate """ # Create mock response with high detection rate mock_response = MOCK_DOMAIN_RESPONSE.copy() mock_response["blacklists"]["detections"] = 7 mock_response["blacklists"]["engines_count"] = 10 mocker.patch.object(client, "_http_request", return_value=mock_response) args = {"domain": "malicious.com"} thresholds = {"suspicious": 30, "bad": 60} result = domain_reputation_command(client, args, False, thresholds, "C - Fairly reliable") # Verify DBotScore has malicious_description assert result.indicator.dbot_score.score == Common.DBotScore.BAD assert result.indicator.dbot_score.malicious_description == "Detection rate of 7/10" def test_url_reputation_bad_score_has_malicious_description(self, client, mocker): """ Test URL reputation with BAD score includes malicious_description Given: URL with high detection rate (75%) When: url_reputation_command is called with bad threshold 60% Then: DBotScore should have malicious_description with detection rate """ # Create mock response with high detection rate mock_response = MOCK_URL_RESPONSE.copy() mock_response["domain_blacklist"]["detections"] = 15 mock_response["domain_blacklist"]["engines_count"] = 20 mocker.patch.object(client, "_http_request", return_value=mock_response) args = {"url": "https://example.com"} thresholds = {"suspicious": 30, "bad": 60} result = url_reputation_command(client, args, False, thresholds, "C - Fairly reliable") # Verify DBotScore has malicious_description assert result.indicator.dbot_score.score == Common.DBotScore.BAD assert result.indicator.dbot_score.malicious_description == "Detection rate of 15/20" def test_ip_reputation_good_score_has_malicious_description(self, client, mocker): """ Test IP reputation with GOOD score still includes malicious_description Given: IP with low detection rate (5%) When: ip_reputation_command is called Then: DBotScore should have malicious_description even when score is GOOD """ # Create mock response with low detection rate mock_response = MOCK_IP_RESPONSE.copy() mock_response["blacklists"]["detections"] = 1 mock_response["blacklists"]["engines_count"] = 20 mocker.patch.object(client, "_http_request", return_value=mock_response) args = {"ip": "8.8.8.8"} thresholds = {"suspicious": 30, "bad": 60} result = ip_reputation_command(client, args, False, thresholds, "C - Fairly reliable") # Verify DBotScore has malicious_description even for GOOD score assert result.indicator.dbot_score.score == Common.DBotScore.GOOD assert result.indicator.dbot_score.malicious_description == "Detection rate of 1/20" # ============================================================================ # TEST ERROR HANDLING # ============================================================================ class TestErrorHandling: """Test error handling scenarios""" def test_ip_reputation_api_error(self, client, mocker): """ Test IP reputation with API error Given: API returns error response When: ip_reputation_command is called Then: Should raise DemistoException """ mocker.patch.object(client, "_http_request", return_value=MOCK_ERROR_RESPONSE) args = {"ip": "8.8.8.8"} thresholds = {"suspicious": 30, "bad": 60} with pytest.raises(DemistoException, match="Error checking IP"): ip_reputation_command(client, args, False, thresholds, "C - Fairly reliable") def test_domain_reputation_api_error(self, client, mocker): """ Test domain reputation with API error Given: API returns error response When: domain_reputation_command is called Then: Should raise DemistoException """ mocker.patch.object(client, "_http_request", return_value=MOCK_ERROR_RESPONSE) args = {"domain": "example.com"} thresholds = {"suspicious": 30, "bad": 60} with pytest.raises(DemistoException, match="Error checking domain"): domain_reputation_command(client, args, False, thresholds, "C - Fairly reliable") def test_url_reputation_api_error(self, client, mocker): """ Test URL reputation with API error Given: API returns error response When: url_reputation_command is called Then: Should raise DemistoException """ mocker.patch.object(client, "_http_request", return_value=MOCK_ERROR_RESPONSE) args = {"url": "https://example.com"} thresholds = {"suspicious": 30, "bad": 60} with pytest.raises(DemistoException, match="Error checking URL"): url_reputation_command(client, args, False, thresholds, "C - Fairly reliable") def test_dns_lookup_api_error(self, client, mocker): """ Test DNS lookup with API error Given: API returns error response When: dns_lookup_command is called Then: Should raise DemistoException """ mocker.patch.object(client, "_http_request", return_value=MOCK_ERROR_RESPONSE) args = {"host": "example.com", "type": "A"} with pytest.raises(DemistoException, match="Error looking up DNS"): dns_lookup_command(client, args) def test_screenshot_no_data(self, client, mocker): """ Test screenshot with no data returned Given: API returns response without base64_file When: screenshot_command is called Then: Should raise DemistoException """ mocker.patch.object(client, "_http_request", return_value={}) args = {"url": "https://example.com"} with pytest.raises(DemistoException, match="No screenshot data returned"): screenshot_command(client, args) def test_url_to_pdf_no_data(self, client, mocker): """ Test URL to PDF with no data returned Given: API returns response without base64_file When: url_to_pdf_command is called Then: Should raise DemistoException """ mocker.patch.object(client, "_http_request", return_value={}) args = {"url": "https://example.com"} with pytest.raises(DemistoException, match="No PDF data returned"): url_to_pdf_command(client, args) # ============================================================================ # TEST MODULE # ============================================================================ class TestTestModule: """Test the test-module command""" def test_module_success(self, client, mocker): """ Test successful test-module Given: Valid API credentials When: test_module is called Then: Should return 'ok' """ mocker.patch.object(client, "_http_request", return_value=MOCK_IP_RESPONSE) result = module_test(client) assert result == "ok" def test_module_api_error(self, client, mocker): """ Test test-module with API error Given: API returns error When: test_module is called Then: Should return error message """ mocker.patch.object(client, "_http_request", return_value=MOCK_ERROR_RESPONSE) result = module_test(client) assert "Test Failed" in result def test_module_exception(self, client, mocker): """ Test test-module with exception Given: API request raises exception When: test_module is called Then: Should return error message """ mocker.patch.object(client, "_http_request", side_effect=Exception("Connection error")) result = module_test(client) assert "Test Failed" in result # ============================================================================ # TEST MAIN FUNCTION # ============================================================================ class TestMain: """Test main function and command routing""" def test_main_test_module(self, mock_demisto, mocker): """ Test main function with test-module command Given: test-module command When: main is called Then: Should call test_module and return results """ mocker.patch.object(demisto, "command", return_value="test-module") mock_return_results = mocker.patch("APIVoid.return_results") mocker.patch("APIVoid.test_module", return_value="ok") main() mock_return_results.assert_called_once_with("ok") def test_main_ip_command(self, mock_demisto, mocker): """ Test main function with ip command Given: ip command When: main is called Then: Should call ip_reputation_command with reputation_only=True """ mocker.patch.object(demisto, "command", return_value="ip") mocker.patch.object(demisto, "args", return_value={"ip": "8.8.8.8"}) mocker.patch("APIVoid.return_results") mock_ip_cmd = mocker.patch("APIVoid.ip_reputation_command", return_value=CommandResults(readable_output="test")) main() # Verify reputation_only was True assert mock_ip_cmd.call_args[0][2] is True def test_main_apivoid_ip_command(self, mock_demisto, mocker): """ Test main function with apivoid-ip command Given: apivoid-ip command When: main is called Then: Should call ip_reputation_command with reputation_only=False """ mocker.patch.object(demisto, "command", return_value="apivoid-ip") mocker.patch.object(demisto, "args", return_value={"ip": "8.8.8.8"}) mocker.patch("APIVoid.return_results") mock_ip_cmd = mocker.patch("APIVoid.ip_reputation_command", return_value=CommandResults(readable_output="test")) main() # Verify reputation_only was False assert mock_ip_cmd.call_args[0][2] is False def test_main_domain_command(self, mock_demisto, mocker): """ Test main function with domain command Given: domain command When: main is called Then: Should call domain_reputation_command with reputation_only=True """ mocker.patch.object(demisto, "command", return_value="domain") mocker.patch.object(demisto, "args", return_value={"domain": "example.com"}) mocker.patch("APIVoid.return_results") mock_domain_cmd = mocker.patch("APIVoid.domain_reputation_command", return_value=CommandResults(readable_output="test")) main() # Verify reputation_only was True assert mock_domain_cmd.call_args[0][2] is True def test_main_apivoid_domain_command(self, mock_demisto, mocker): """ Test main function with apivoid-domain command Given: apivoid-domain command When: main is called Then: Should call domain_reputation_command with reputation_only=False """ mocker.patch.object(demisto, "command", return_value="apivoid-domain") mocker.patch.object(demisto, "args", return_value={"domain": "example.com"}) mocker.patch("APIVoid.return_results") mock_domain_cmd = mocker.patch("APIVoid.domain_reputation_command", return_value=CommandResults(readable_output="test")) main() # Verify reputation_only was False assert mock_domain_cmd.call_args[0][2] is False def test_main_url_command(self, mock_demisto, mocker): """ Test main function with url command Given: url command When: main is called Then: Should call url_reputation_command with reputation_only=True """ mocker.patch.object(demisto, "command", return_value="url") mocker.patch.object(demisto, "args", return_value={"url": "https://example.com"}) mocker.patch("APIVoid.return_results") mock_url_cmd = mocker.patch("APIVoid.url_reputation_command", return_value=CommandResults(readable_output="test")) main() # Verify reputation_only was True assert mock_url_cmd.call_args[0][2] is True def test_main_apivoid_url_command(self, mock_demisto, mocker): """ Test main function with apivoid-url command Given: apivoid-url command When: main is called Then: Should call url_reputation_command with reputation_only=False """ mocker.patch.object(demisto, "command", return_value="apivoid-url") mocker.patch.object(demisto, "args", return_value={"url": "https://example.com"}) mocker.patch("APIVoid.return_results") mock_url_cmd = mocker.patch("APIVoid.url_reputation_command", return_value=CommandResults(readable_output="test")) main() # Verify reputation_only was False assert mock_url_cmd.call_args[0][2] is False def test_main_dns_lookup_command(self, mock_demisto, mocker): """ Test main function with apivoid-dns-lookup command Given: apivoid-dns-lookup command When: main is called Then: Should call dns_lookup_command """ mocker.patch.object(demisto, "command", return_value="apivoid-dns-lookup") mocker.patch.object(demisto, "args", return_value={"host": "example.com"}) mocker.patch("APIVoid.return_results") mock_dns_cmd = mocker.patch("APIVoid.dns_lookup_command", return_value=CommandResults(readable_output="test")) main() mock_dns_cmd.assert_called_once() def test_main_ssl_info_command(self, mock_demisto, mocker): """ Test main function with apivoid-ssl-info command Given: apivoid-ssl-info command When: main is called Then: Should call ssl_info_command """ mocker.patch.object(demisto, "command", return_value="apivoid-ssl-info") mocker.patch.object(demisto, "args", return_value={"host": "example.com"}) mocker.patch("APIVoid.return_results") mock_ssl_cmd = mocker.patch("APIVoid.ssl_info_command", return_value=CommandResults(readable_output="test")) main() mock_ssl_cmd.assert_called_once() def test_main_email_verify_command(self, mock_demisto, mocker): """ Test main function with apivoid-email-verify command Given: apivoid-email-verify command When: main is called Then: Should call email_verify_command """ mocker.patch.object(demisto, "command", return_value="apivoid-email-verify") mocker.patch.object(demisto, "args", return_value={"email": "test@example.com"}) mocker.patch("APIVoid.return_results") mock_email_cmd = mocker.patch("APIVoid.email_verify_command", return_value=CommandResults(readable_output="test")) main() mock_email_cmd.assert_called_once() def test_main_parked_domain_command(self, mock_demisto, mocker): """ Test main function with apivoid-parked-domain command Given: apivoid-parked-domain command When: main is called Then: Should call parked_domain_command """ mocker.patch.object(demisto, "command", return_value="apivoid-parked-domain") mocker.patch.object(demisto, "args", return_value={"domain": "example.com"}) mocker.patch("APIVoid.return_results") mock_parked_cmd = mocker.patch("APIVoid.parked_domain_command", return_value=CommandResults(readable_output="test")) main() mock_parked_cmd.assert_called_once() def test_main_domain_age_command(self, mock_demisto, mocker): """ Test main function with apivoid-domain-age command Given: apivoid-domain-age command When: main is called Then: Should call domain_age_command """ mocker.patch.object(demisto, "command", return_value="apivoid-domain-age") mocker.patch.object(demisto, "args", return_value={"domain": "example.com"}) mocker.patch("APIVoid.return_results") mock_age_cmd = mocker.patch("APIVoid.domain_age_command", return_value=CommandResults(readable_output="test")) main() mock_age_cmd.assert_called_once() def test_main_screenshot_command(self, mock_demisto, mocker): """ Test main function with apivoid-url-to-image command Given: apivoid-url-to-image command When: main is called Then: Should call screenshot_command """ mocker.patch.object(demisto, "command", return_value="apivoid-url-to-image") mocker.patch.object(demisto, "args", return_value={"url": "https://example.com"}) mocker.patch("APIVoid.return_results") mock_screenshot_cmd = mocker.patch("APIVoid.screenshot_command", return_value={"Type": 3, "File": "test.png"}) main() mock_screenshot_cmd.assert_called_once() def test_main_url_to_pdf_command(self, mock_demisto, mocker): """ Test main function with apivoid-url-to-pdf command Given: apivoid-url-to-pdf command When: main is called Then: Should call url_to_pdf_command """ mocker.patch.object(demisto, "command", return_value="apivoid-url-to-pdf") mocker.patch.object(demisto, "args", return_value={"url": "https://example.com"}) mocker.patch("APIVoid.return_results") mock_pdf_cmd = mocker.patch("APIVoid.url_to_pdf_command", return_value={"Type": 3, "File": "test.pdf"}) main() mock_pdf_cmd.assert_called_once() def test_main_site_trustworthiness_command(self, mock_demisto, mocker): """ Test main function with apivoid-site-trustworthiness command Given: apivoid-site-trustworthiness command When: main is called Then: Should call site_trustworthiness_command """ mocker.patch.object(demisto, "command", return_value="apivoid-site-trustworthiness") mocker.patch.object(demisto, "args", return_value={"host": "example.com"}) mocker.patch("APIVoid.return_results") mock_trust_cmd = mocker.patch("APIVoid.site_trustworthiness_command", return_value=CommandResults(readable_output="test")) main() mock_trust_cmd.assert_called_once() def test_main_deprecated_command(self, mock_demisto, mocker): """ Test main function with deprecated command Given: apivoid-threatlog command (deprecated) When: main is called Then: Should raise DemistoException """ mocker.patch.object(demisto, "command", return_value="apivoid-threatlog") mocker.patch.object(demisto, "args", return_value={}) mock_return_error = mocker.patch("APIVoid.return_error") main() mock_return_error.assert_called_once() assert "is not supported in API V2" in mock_return_error.call_args[0][0] def test_main_not_implemented_command(self, mock_demisto, mocker): """ Test main function with not implemented command Given: unknown-command When: main is called Then: Should raise NotImplementedError """ mocker.patch.object(demisto, "command", return_value="unknown-command") mocker.patch.object(demisto, "args", return_value={}) mock_return_error = mocker.patch("APIVoid.return_error") main() mock_return_error.assert_called_once() assert "not implemented" in mock_return_error.call_args[0][0].lower() # ============================================================================ # TEST EXCEPTION HANDLING IN COMMANDS # ============================================================================ class TestExceptionHandling: """Test exception handling in all commands""" def test_ip_reputation_http_exception(self, client, mocker): """ Test IP reputation with HTTP exception Given: HTTP request raises exception When: ip_reputation_command is called Then: Should raise DemistoException with proper message """ mocker.patch.object(client, "_http_request", side_effect=Exception("Connection timeout")) args = {"ip": "8.8.8.8"} thresholds = {"suspicious": 30, "bad": 60} with pytest.raises(DemistoException, match="Failed to get IP reputation"): ip_reputation_command(client, args, False, thresholds, "C - Fairly reliable") def test_domain_reputation_http_exception(self, client, mocker): """ Test domain reputation with HTTP exception Given: HTTP request raises exception When: domain_reputation_command is called Then: Should raise DemistoException with proper message """ mocker.patch.object(client, "_http_request", side_effect=Exception("Network error")) args = {"domain": "example.com"} thresholds = {"suspicious": 30, "bad": 60} with pytest.raises(DemistoException, match="Failed to get domain reputation"): domain_reputation_command(client, args, False, thresholds, "C - Fairly reliable") def test_url_reputation_http_exception(self, client, mocker): """ Test URL reputation with HTTP exception Given: HTTP request raises exception When: url_reputation_command is called Then: Should raise DemistoException with proper message """ mocker.patch.object(client, "_http_request", side_effect=Exception("Timeout")) args = {"url": "https://example.com"} thresholds = {"suspicious": 30, "bad": 60} with pytest.raises(DemistoException, match="Failed to get URL reputation"): url_reputation_command(client, args, False, thresholds, "C - Fairly reliable") def test_dns_lookup_http_exception(self, client, mocker): """ Test DNS lookup with HTTP exception Given: HTTP request raises exception When: dns_lookup_command is called Then: Should raise DemistoException with proper message """ mocker.patch.object(client, "_http_request", side_effect=Exception("DNS error")) args = {"host": "example.com", "type": "A"} with pytest.raises(DemistoException, match="Failed to get DNS records"): dns_lookup_command(client, args) def test_ssl_info_http_exception(self, client, mocker): """ Test SSL info with HTTP exception Given: HTTP request raises exception When: ssl_info_command is called Then: Should raise DemistoException with proper message """ mocker.patch.object(client, "_http_request", side_effect=Exception("SSL error")) args = {"host": "example.com"} with pytest.raises(DemistoException, match="Failed to get SSL info"): ssl_info_command(client, args) def test_email_verify_http_exception(self, client, mocker): """ Test email verify with HTTP exception Given: HTTP request raises exception When: email_verify_command is called Then: Should raise DemistoException with proper message """ mocker.patch.object(client, "_http_request", side_effect=Exception("Email error")) args = {"email": "test@example.com"} with pytest.raises(DemistoException, match="Failed to verify email"): email_verify_command(client, args) def test_parked_domain_http_exception(self, client, mocker): """ Test parked domain with HTTP exception Given: HTTP request raises exception When: parked_domain_command is called Then: Should raise DemistoException with proper message """ mocker.patch.object(client, "_http_request", side_effect=Exception("Parked error")) args = {"domain": "example.com"} with pytest.raises(DemistoException, match="Failed to check parked domain"): parked_domain_command(client, args) def test_domain_age_http_exception(self, client, mocker): """ Test domain age with HTTP exception Given: HTTP request raises exception When: domain_age_command is called Then: Should raise DemistoException with proper message """ mocker.patch.object(client, "_http_request", side_effect=Exception("Age error")) args = {"domain": "example.com"} with pytest.raises(DemistoException, match="Failed to get domain age"): domain_age_command(client, args) def test_screenshot_http_exception(self, client, mocker): """ Test screenshot with HTTP exception Given: HTTP request raises exception When: screenshot_command is called Then: Should raise DemistoException with proper message """ mocker.patch.object(client, "_http_request", side_effect=Exception("Screenshot error")) args = {"url": "https://example.com"} with pytest.raises(DemistoException, match="Failed to capture screenshot"): screenshot_command(client, args) def test_url_to_pdf_http_exception(self, client, mocker): """ Test URL to PDF with HTTP exception Given: HTTP request raises exception When: url_to_pdf_command is called Then: Should raise DemistoException with proper message """ mocker.patch.object(client, "_http_request", side_effect=Exception("PDF error")) args = {"url": "https://example.com"} with pytest.raises(DemistoException, match="Failed to convert URL to PDF"): url_to_pdf_command(client, args) def test_site_trustworthiness_http_exception(self, client, mocker): """ Test site trustworthiness with HTTP exception Given: HTTP request raises exception When: site_trustworthiness_command is called Then: Should raise DemistoException with proper message """ mocker.patch.object(client, "_http_request", side_effect=Exception("Trust error")) args = {"host": "example.com"} with pytest.raises(DemistoException, match="Failed to get site trustworthiness"): site_trustworthiness_command(client, args) # ============================================================================ # TEST EDGE CASES AND EMPTY RESPONSES # ============================================================================ class TestEdgeCases: """Test edge cases and empty response handling""" def test_dns_lookup_no_records(self, client, mocker): """ Test DNS lookup with no records Given: API returns empty records When: dns_lookup_command is called Then: Should return CommandResults with appropriate message """ mocker.patch.object(client, "_http_request", return_value={"host": "example.com", "records": {}}) args = {"host": "example.com", "type": "A"} result = dns_lookup_command(client, args) assert isinstance(result, CommandResults) assert "No DNS records found" in result.readable_output def test_dns_lookup_no_matching_type(self, client, mocker): """ Test DNS lookup with no matching record type Given: API returns records but not the requested type When: dns_lookup_command is called Then: Should return CommandResults with appropriate message """ mocker.patch.object( client, "_http_request", return_value={"host": "example.com", "records": {"mx": [{"target": "mail.example.com"}]}} ) args = {"host": "example.com", "type": "A"} result = dns_lookup_command(client, args) assert isinstance(result, CommandResults) assert "No A records found" in result.readable_output def test_ssl_info_no_certificate(self, client, mocker): """ Test SSL info with no certificate Given: API returns empty certificate When: ssl_info_command is called Then: Should return CommandResults with appropriate message """ mocker.patch.object(client, "_http_request", return_value={"host": "example.com", "certificate": {}}) args = {"host": "example.com"} result = ssl_info_command(client, args) assert isinstance(result, CommandResults) assert "No SSL information" in result.readable_output def test_ssl_info_api_error(self, client, mocker): """ Test SSL info with API error Given: API returns error response When: ssl_info_command is called Then: Should raise DemistoException """ mocker.patch.object(client, "_http_request", return_value=MOCK_ERROR_RESPONSE) args = {"host": "example.com"} with pytest.raises(DemistoException, match="Error getting SSL info"): ssl_info_command(client, args) def test_email_verify_empty_response(self, client, mocker): """ Test email verify with empty response Given: API returns empty response When: email_verify_command is called Then: Should return CommandResults with appropriate message """ mocker.patch.object(client, "_http_request", return_value={}) args = {"email": "test@example.com"} result = email_verify_command(client, args) assert isinstance(result, CommandResults) assert "No information" in result.readable_output def test_email_verify_api_error(self, client, mocker): """ Test email verify with API error Given: API returns error response When: email_verify_command is called Then: Should raise DemistoException """ mocker.patch.object(client, "_http_request", return_value=MOCK_ERROR_RESPONSE) args = {"email": "test@example.com"} with pytest.raises(DemistoException, match="Error verifying email"): email_verify_command(client, args) def test_parked_domain_empty_response(self, client, mocker): """ Test parked domain with empty response Given: API returns empty response When: parked_domain_command is called Then: Should return CommandResults with appropriate message """ mocker.patch.object(client, "_http_request", return_value={}) args = {"domain": "example.com"} result = parked_domain_command(client, args) assert isinstance(result, CommandResults) assert "No information" in result.readable_output def test_parked_domain_api_error(self, client, mocker): """ Test parked domain with API error Given: API returns error response When: parked_domain_command is called Then: Should raise DemistoException """ mocker.patch.object(client, "_http_request", return_value=MOCK_ERROR_RESPONSE) args = {"domain": "example.com"} with pytest.raises(DemistoException, match="Error checking parked domain"): parked_domain_command(client, args) def test_domain_age_empty_response(self, client, mocker): """ Test domain age with empty response Given: API returns empty response When: domain_age_command is called Then: Should return CommandResults with appropriate message """ mocker.patch.object(client, "_http_request", return_value={}) args = {"domain": "example.com"} result = domain_age_command(client, args) assert isinstance(result, CommandResults) assert "No information" in result.readable_output def test_domain_age_api_error(self, client, mocker): """ Test domain age with API error Given: API returns error response When: domain_age_command is called Then: Should raise DemistoException """ mocker.patch.object(client, "_http_request", return_value=MOCK_ERROR_RESPONSE) args = {"domain": "example.com"} with pytest.raises(DemistoException, match="Error getting domain age"): domain_age_command(client, args) def test_screenshot_api_error(self, client, mocker): """ Test screenshot with API error Given: API returns error response When: screenshot_command is called Then: Should raise DemistoException """ mocker.patch.object(client, "_http_request", return_value=MOCK_ERROR_RESPONSE) args = {"url": "https://example.com"} with pytest.raises(DemistoException, match="Error capturing screenshot"): screenshot_command(client, args) def test_url_to_pdf_api_error(self, client, mocker): """ Test URL to PDF with API error Given: API returns error response When: url_to_pdf_command is called Then: Should raise DemistoException """ mocker.patch.object(client, "_http_request", return_value=MOCK_ERROR_RESPONSE) args = {"url": "https://example.com"} with pytest.raises(DemistoException, match="Error converting URL to PDF"): url_to_pdf_command(client, args) def test_site_trustworthiness_empty_response(self, client, mocker): """ Test site trustworthiness with empty response Given: API returns empty response When: site_trustworthiness_command is called Then: Should return CommandResults with appropriate message """ mocker.patch.object(client, "_http_request", return_value={}) args = {"host": "example.com"} result = site_trustworthiness_command(client, args) assert isinstance(result, CommandResults) assert "No information" in result.readable_output def test_site_trustworthiness_api_error(self, client, mocker): """ Test site trustworthiness with API error Given: API returns error response When: site_trustworthiness_command is called Then: Should raise DemistoException """ mocker.patch.object(client, "_http_request", return_value=MOCK_ERROR_RESPONSE) args = {"host": "example.com"} with pytest.raises(DemistoException, match="Error getting site trustworthiness"): site_trustworthiness_command(client, args)