feat(paloalto-wildfire): add WildFire enrichment connector (#6730)#6731
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #6731 +/- ##
===========================================
+ Coverage 35.64% 86.70% +51.05%
===========================================
Files 2048 7 -2041
Lines 125310 677 -124633
===========================================
- Hits 44672 587 -44085
+ Misses 80638 90 -80548
📢 Thoughts on this report? Let us know! 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR introduces a new internal-enrichment connector (internal-enrichment/paloalto-wildfire) that enriches StixFile and Artifact observables by querying the Palo Alto Networks WildFire public API for hash verdicts/reports, then emitting an enriched STIX bundle (playbook compatible).
Changes:
- Adds the WildFire enrichment connector implementation (hash selection, verdict/score/label mapping, Malware Analysis object creation, TLP gating, bundle send flow).
- Adds a thin HTTP client for the WildFire API (
/get/verdict,/get/report) with retry/backoff and XML parsing. - Adds unit tests + connector packaging assets (Dockerfile, compose/config samples, metadata/schema/docs).
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| internal-enrichment/paloalto-wildfire/src/connector/connector.py | Core enrichment flow (hash lookup, verdict mapping, STIX bundle creation/sending). |
| internal-enrichment/paloalto-wildfire/src/connector/settings.py | Pydantic settings models for connector + WildFire config. |
| internal-enrichment/paloalto-wildfire/src/connector/init.py | Exposes connector/settings package entrypoints. |
| internal-enrichment/paloalto-wildfire/src/paloalto_wildfire_client/api_client.py | WildFire HTTP client with retries and XML parsing. |
| internal-enrichment/paloalto-wildfire/src/paloalto_wildfire_client/init.py | Exposes client + exception symbols. |
| internal-enrichment/paloalto-wildfire/src/main.py | Connector entrypoint (helper init, run, error handling). |
| internal-enrichment/paloalto-wildfire/src/requirements.txt | Runtime dependencies for the connector. |
| internal-enrichment/paloalto-wildfire/tests/conftest.py | Test fixtures + pycti helper mocking. |
| internal-enrichment/paloalto-wildfire/tests/test_main.py | Smoke tests for settings/helper/connector instantiation. |
| internal-enrichment/paloalto-wildfire/tests/test-requirements.txt | Test dependency pin for pytest. |
| internal-enrichment/paloalto-wildfire/tests/tests_connector/test_connector.py | Unit tests for the connector behavior and enrichment logic. |
| internal-enrichment/paloalto-wildfire/tests/tests_connector/test_settings.py | Unit tests for config validation. |
| internal-enrichment/paloalto-wildfire/tests/tests_connector/data/file_message.json | File enrichment message fixture. |
| internal-enrichment/paloalto-wildfire/tests/tests_connector/data/artifact_message.json | Artifact enrichment message fixture. |
| internal-enrichment/paloalto-wildfire/tests/tests_paloalto_wildfire_client/test_api_client.py | Unit tests for the WildFire API client. |
| internal-enrichment/paloalto-wildfire/README.md | Connector documentation (setup, behavior, env vars). |
| internal-enrichment/paloalto-wildfire/Dockerfile | Container build for the connector. |
| internal-enrichment/paloalto-wildfire/entrypoint.sh | Container entrypoint script. |
| internal-enrichment/paloalto-wildfire/docker-compose.yml | Example deployment configuration. |
| internal-enrichment/paloalto-wildfire/config.yml.sample | Example config.yml for manual deployment. |
| internal-enrichment/paloalto-wildfire/metadata/connector_manifest.json | Connector manifest metadata for the catalog. |
| internal-enrichment/paloalto-wildfire/metadata/connector_config_schema.json | Generated config JSON schema. |
| internal-enrichment/paloalto-wildfire/metadata/CONNECTOR_CONFIG_DOC.md | Generated config documentation. |
Review and fix pass completeIndependent senior review of the full connector plus all 16 automated review threads addressed, fixes pushed in 55f0562. WildFire client (
Enrichment (
Docs and tests
CI: all checks green (the earlier Blocker: self-approval is not possible (I am the PR author), so one maintainer approving review is still required before merge. |
Review-and-fix pass summaryIndependent senior re-review of the full Code/test fixes (commit 1598ca9):
Independent-review note: the WildFire client uses a urllib3 CI fix (de-stale):
Verification:
Remaining (non-CI) blocker: |
…rdicts (#6730) Add an internal-enrichment connector for Palo Alto Networks WildFire. It enriches StixFile and Artifact observables by querying the WildFire public API by hash, maps the verdict (benign/grayware/phishing/malware/C2) to an OpenCTI score and label, completes the file hashes from the report, and attaches a STIX Malware Analysis object. Modeled on the hybrid-analysis-sandbox connector (connectors-sdk settings, playbook compatible). Includes client + connector unit tests, generated config schema/doc, README, manifest and docker-compose.
…ling (#6730) Bring WildFire to parity with the other sandbox connectors (FortiSandbox, PolySwarm, intezer, hybrid-analysis): - Submit unknown files to WildFire (POST /submit/file) and poll the verdict (POST /get/verdict) until it is final; enabled by default via submit_unknown so Artifacts uploaded to OpenCTI are detonated. - Add a robust file-download step that enforces max_file_size, rejects empty files, and logs a clear skip reason instead of failing silently. - Add max_file_size and submission_timeout settings; bound the verdict poll by submission_timeout and handle the pending (-100) verdict code. Updates client (submit_file, get_verdict_code, poll_verdict), tests, generated config schema/doc, README, config sample and docker-compose.
…le type Address the Copilot review threads plus an independent senior review. - api_client.py: set Retry(raise_on_status=False) so exhausted retries surface a consistent HTTPError via raise_for_status, and wrap every requests.RequestException (retry exhaustion, timeouts, connection errors), not just HTTPError, as WildfireAPIError in _post and submit_file. - connector.py: the enriched StixFile now carries the WildFire report file type in mime_type; the Malware Analysis object inherits the source observable's object_marking_refs (falling back to the connector default) so enrichment never emits an unmarked or TLP-downgraded object; the default marking is the OpenCTI TLP:CLEAR statement marking instead of the legacy stix2.TLP_WHITE. - Logging: structured context is passed via the meta= keyword across the client and connector. - README.md: fix the TOC anchor, align the OpenCTI minimum version with the manifest (6.8.12), and fix the Debugging typo and logger example. - tests: assert the mime_type completion and the Malware Analysis markings, cover the non-HTTP error wrapping, and fix an "== True" comparison.
…opt-in Address the remaining Copilot review and keep the connector installable against current master: - connector.py: the Malware Analysis object now derives its markings from the source observable's OpenCTI markings (enrichment messages carry them in enrichment_entity["objectMarking"], not as STIX object_marking_refs), and the resolved marking objects are included in the bundle so the SDO is correctly marked and self-contained instead of being silently downgraded to the default TLP (or stripped by cleanup_inconsistent_bundle). - settings.py: submit_unknown now defaults to false (opt-in). File submission/detonation uploads the sample to a third party, and issue #6730 scopes the first version to verdict-by-hash only; the feature stays available via explicit opt-in. Updated the generated schema/doc, config.yml.sample, docker-compose.yml and the test accordingly. - README.md: corrected the base-connector table (CONNECTOR_TYPE INTERNAL_ENRICHMENT, auto key/default, optional flags) and rewrote the Usage section for an enrichment connector. - src/requirements.txt: bump the pinned pycti to 7.260615.0 to match the current connectors-sdk (support_version stays >=6.8.12, the connector's minimum).
1167e4a to
5fae6a1
Compare
Review and fix pass - summary
Remaining (not automatable): GitHub does not allow approving one's own pull request, so |
#6730) - manifest: verified=false / last_verified_date=null (community-contributed, not Filigran-verified), manager_supported=true, XTM Hub use-case taxonomy (Malware Analysis and Sandbox), support_version >=7.260701.0 - Dockerfile: direct python ENTRYPOINT, remove entrypoint.sh (VC402) - docker-compose.yml: exact ChangeMe placeholders, defaulted variables commented out (VC101/VC104) - connector: out-of-scope entities return the original bundle for playbook triggers and raise for direct events (VC319); file download URL built from the configured OpenCTI URL instead of helper.api.api_url (VC505) - README: align minimum OpenCTI version with the manifest - tests: cover the out-of-scope paths and the storage download URL
Proposed changes
New internal-enrichment connector for Palo Alto Networks WildFire.
When a
StixFileorArtifactobservable is enriched, the connector:POST /get/verdict);POST /submit/file) and polls for the verdict (opt-in viasubmit_unknown, disabled by default, bounded bysubmission_timeout, withmax_file_sizeenforced on download);wildfire:<verdict>label;POST /get/report) to complete the file hashes and the file type (mime_type) when available;product = WildFire) referencing the observable, carrying the source observable's markings, with the result mapped to the STIXmalware-resultvocabulary.The connector is playbook compatible and always returns the (enriched) bundle. It is modeled on the existing
hybrid-analysis-sandboxconnector (connectors-sdk Pydantic settings, retry/backoff client,_process_messageflow).Related issues
Closes #6730
Types of changes
Checklist
black,isort) and linting (flake8, STIX id pylint) pass__metadata__config schema and documentationREADME.md,config.yml.sample,docker-compose.ymlandconnector_manifest.jsonFurther comments
The API base URL is configurable to support the different WildFire cloud regions and on-premise WildFire appliances. File submission/detonation of unknown samples is disabled by default (
submit_unknown); set it totrueto allow the connector to upload unknown samples to WildFire for analysis, otherwise it is restricted to hash-based verdict/report lookups only (the issue scopes the first version to verdict-by-hash).Maintainer review and fix pass
A follow-up review hardened the connector and addressed the automated review threads:
Retry(raise_on_status=False)so exhausted retries raise a consistentHTTPError, and everyrequests.RequestException(retry exhaustion, timeouts, connection errors) is wrapped asWildfireAPIErrorin_postandsubmit_file.enrichment_entity["objectMarking"], resolving each TLP to its stix2 MarkingDefinition) and includes the marking objects in the bundle, so enrichment never downgrades the TLP to the default or emits a marking reference thatcleanup_inconsistent_bundlewould strip; it falls back to the OpenCTI TLP:CLEAR statement marking only when the observable carries none.mime_type; the connector default marking is the OpenCTI TLP:CLEAR statement marking instead ofstix2.TLP_WHITE.submit_unknowndefaults tofalse(opt-in). Submission uploads the sample to a third-party service and issue feat(paloalto-wildfire): create enrichment connector for file hash verdicts #6730 scopes the first version to verdict-by-hash only, so it is an explicit opt-in (the feature stays available viasubmit_unknown=true).meta=keyword for structured context throughout the client and connector.CONNECTOR_TYPE=INTERNAL_ENRICHMENT, theautoconfig key,CONNECTOR_AUTOdefaultfalse, and the optional flags to match the generated schema); rewrote the Usage section for an internal-enrichment connector; and fixed the Debugging typo and logger example.mime_typecompletion and the source-derived Malware Analysis markings, the non-HTTP error wrapping, and thesubmit_unknownopt-in default.pyctiis pinned to the latest release7.260701.0(matching theconnectors-sdkpin onmaster) andconnectors-sdkis installed frommaster.Community status and manager compatibility pass
A second follow-up pass aligned the connector with the catalog/manager conventions:
connector_manifest.json:"verified": falseand"last_verified_date": nullare INTENTIONAL - this is a community-contributed connector, not officially verified by Filigran (same status as other recently merged community connectors). The Connector Verified Linter job reports the VC201 verified-status findings as expected; that job is advisory (continue-on-error: true) and does not block the PR. Do not flipverifiedtotrueto silence it.connector_manifest.json:"manager_supported": true(the connector follows the connectors-sdk settings contract and ships the generated config schema), use cases aligned with the official XTM Hub taxonomy (Malware Analysis and Sandbox), andsupport_versionaligned with the pinned pycti (>=7.260701.0).ENTRYPOINT ["python", "main.py"],entrypoint.shremoved (linter rule VC402).docker-compose.yml: exactChangeMeplaceholders and all defaulted variables commented out (linter rules VC101/VC104).helper.api.api_url(linter rule VC505).__metadata__/connector_config_schema.jsonandCONNECTOR_CONFIG_DOC.mdregenerated with the connectors-sdk tooling (no drift from the settings model).connector-linter: score 94.9, only the two intentional VC201 verified-status findings remain; 46 unit tests pass,black/isort/flake8clean.Status
The branch is based on the latest
master(clean linear history, all commits signed). All required CI checks are green and there are 0 unresolved review threads.mergeStateStatusis BLOCKED only becausereviewDecisionrequires an approving review from a maintainer other than the author.