Skip to content

Claude/add claude documentation k8vv j#70

Merged
wrhalpin merged 2 commits intomainfrom
claude/add-claude-documentation-k8vvJ
Apr 6, 2026
Merged

Claude/add claude documentation k8vv j#70
wrhalpin merged 2 commits intomainfrom
claude/add-claude-documentation-k8vvJ

Conversation

@wrhalpin
Copy link
Copy Markdown
Owner

@wrhalpin wrhalpin commented Apr 6, 2026

No description provided.

claude added 2 commits April 6, 2026 12:52
…clients

Adds platform-specific methods to all five connectors, surfaced via
capabilities() / call() with no changes to the standard 7-method interface.

GreyMatter (+18 methods):
  Case management: add_case_comment, list_case_comments, update_case_status,
  assign_case, close_case, add_case_observable, get_case_timeline
  Observables: bulk_create_observables, tag_observable, search_observables_by_value,
  get_observable_enrichments
  Entities: get/list_threat_actors, get_malware_family, list_malware,
  get/list_vulnerabilities, list_attack_patterns
  Analytics: get_metrics
  Playbooks: get_playbook, list_playbooks, run_playbook
  Admin: list_users

XSOAR (+19 methods):
  Incident lifecycle: close_incident, reopen_incident, get_incident_indicators,
  add_incident_comment, assign_incident
  Indicators: get_indicator_reputation, bulk_create_indicators, export_indicators,
  expire_indicator
  Playbooks/automation: run_playbook, get_playbook_tasks, complete_task,
  search_automations, search_integrations
  Admin: list_users, get_server_config, list_incident_types,
  list_indicator_types, get_dashboard, list_reports

ThreatQ (+29 methods):
  Indicator relationships: get_indicator_adversaries/events/malware/vulnerabilities/
  signatures/comments, add_indicator_comment, score_indicator
  Adversary relationships: get_adversary_indicators/malware/vulnerabilities/
  attack_patterns
  Event extensions: get_event_malware/vulnerabilities/attack_patterns,
  add_event_comment
  Signatures: list_signatures, get_signature, get_signature_indicators
  Attachments: list_attachments, upload_attachment
  Tasks: list_tasks, create_task, complete_task
  Sources: list_sources, get_source
  Entity helpers: get_malware_indicators/adversaries,
  get_vulnerability_indicators/adversaries

RecordedFuture (+24 methods, was 0 platform-specific):
  Entity lookups: lookup_ip, lookup_domain, lookup_hash, lookup_url,
  lookup_vulnerability, lookup_malware, lookup_threat_actor
  Search: search_ips, search_domains, search_hashes, search_vulnerabilities
  Risk alerts: list_risk_alerts, get_risk_alert, update_alert_status
  Playbook alerts: list_playbook_alerts, get_playbook_alert, update_playbook_alert
  Analyst notes: search_analyst_notes, get_analyst_note
  Related entities: get_related_entities
  Risk lists: download_risk_list, get_risk_rules
  Fusion files: list_fusion_files, download_fusion_file

Netskope (+23 methods, was 0 platform-specific):
  URL lists: deploy_urllist, add_urls_to_list, replace_urllist_urls
  Alerts: list_alerts, get_alert, acknowledge_alert, get_alert_events
  Events: get_application_events, get_page_events, get_infrastructure_events,
  get_network_events
  Policy: list_policy_rules, get_policy_rule
  Private apps: list_private_apps, get_private_app, create_private_app
  Users: get_user_config, list_users
  Steering: list_web_categories
  Infrastructure: list_client_configs, get_siem_config, update_siem_config
  Tenant: get_tenant_info

3205 unit tests pass.

https://claude.ai/code/session_01BDoue9HxB83ijLzFARAugq
…lients

Add platform-specific API methods to 5 connectors, all surfaced automatically
via capabilities(). No existing code removed or modified.

CrowdStrike (28 new methods):
- Detections: list/get/update
- Incidents: list/get/update/get_behaviors
- Hosts: list/get/contain/lift_containment/login_history/network_addresses
- Intel: actors/malware/reports/indicators
- Custom IOCs: create/update/delete/list
- RTR: init/execute/delete session
- Spotlight: list/get vulnerabilities

VirusTotal (27 new methods):
- Typed lookups: lookup_ip/domain/hash/url
- File analysis: behaviors/sigma/rescan
- Entity relationships (generic + 6 typed helpers)
- Intelligence search, comments, votes
- Hunting rulesets: list/get/create/delete
- Collections and threat actor profiles

Splunk (32 new methods):
- Search jobs: create/get/results/cancel + run_search
- Saved searches: list/get/create/trigger/delete
- Fired alerts: list/get
- Indexes: list/get/create
- KV Store: list/get/upsert/delete records
- HEC: send_hec_event/send_hec_events_batch
- Apps: list/get
- Lookup tables: list/get
- Threat intel framework: add IP/domain entries

Mandiant (26 new methods):
- Actor relationships: indicators/malware/attack-patterns/vulns/campaigns
- Malware relationships: indicators/actors/attack-patterns/campaigns
- Vulnerability: detail/actors/malware/EPSS
- Reports: list/get/get_stix
- Campaigns: list/get + actors/malware/indicators
- Indicators: lookup/get_actors/get_malware
- ATT&CK patterns: list/get

Sentinel (32 new methods, delegating to sub-clients):
- Incident lifecycle: create/update/close/comment/entities/count/iter
- TI extended: update/bulk_create/query/iter indicators
- Alerts: list + incident alerts
- Analytic rules: list/get/enable/disable/delete/templates/iter
- Hunting queries: list/get/create/delete
- Watchlists: list/get/create/delete/items/add_item/bulk_add

https://claude.ai/code/session_01BDoue9HxB83ijLzFARAugq
Copilot AI review requested due to automatic review settings April 6, 2026 19:29
@wrhalpin wrhalpin merged commit 5494a86 into main Apr 6, 2026
12 of 24 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request substantially expands the capabilities of multiple GNAT connector clients by adding higher-level helper methods for common platform operations (incident/case lifecycle, indicator enrichment, searches, relationships, and administrative endpoints).

Changes:

  • Added many new convenience API methods across connectors (XSOAR, VirusTotal, ThreatQ, Splunk, Sentinel, Recorded Future, Netskope, Mandiant, GreyMatter, CrowdStrike).
  • Expanded Sentinel connector facade to expose additional command domains (alerts, analytic rules, hunting, watchlists).
  • Introduced new download/export and lifecycle utilities (e.g., Splunk search jobs/HEC, Recorded Future risk lists/fusion downloads).

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
gnat/connectors/xsoar/client.py Adds incident lifecycle, indicator operations, playbook/automation, and admin helper methods.
gnat/connectors/virustotal/client.py Adds typed entity lookup helpers, relationships, intelligence search, comments/votes, and hunting/collection/actor APIs.
gnat/connectors/threatq/client.py Adds extensive relationship APIs plus signatures, attachments, tasks, sources, and entity helper endpoints.
gnat/connectors/splunk/client.py Adds search job utilities, saved searches, alerts, KV store helpers, HEC senders, apps/lookups, and threat intel helpers.
gnat/connectors/sentinel/connector.py Exposes additional Sentinel command modules through the Connector facade and adds wrapper methods for new capabilities.
gnat/connectors/recordedfuture/client.py Adds many entity lookups/searches plus alerts/notes/links and bulk download helpers.
gnat/connectors/netskope/client.py Adds URL list operations plus alerts, event exports, policy and tenant/admin helpers.
gnat/connectors/mandiant/client.py Adds relationship endpoints for actors/malware/vulns/reports/campaigns plus enriched indicator helpers.
gnat/connectors/greymatter/client.py Adds case management, bulk observable operations, entity browsing, and playbook/metrics helpers.
gnat/connectors/crowdstrike/client.py Adds detection/incident/host/intel/custom IOC/RTR/vulnerability helper methods.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +855 to +860
tq_id = self._extract_numeric_id(entity_id)
resp = self.post(
f"/api/{entity_type}/{tq_id}/attachments",
files={"file": (filename, content, content_type)},
)
return resp.get("data", resp) if isinstance(resp, dict) else {}
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

upload_attachment() calls self.post(..., files=...), but BaseClient.post() does not accept a files kwarg and the underlying BaseClient._request() always JSON/form-encodes bodies (no multipart support). This will raise TypeError at runtime and cannot actually upload attachments. Implement multipart encoding in ThreatQClient (e.g., build Content-Type: multipart/form-data body via urllib3.filepost.encode_multipart_formdata) and send it via a custom request method, or extend BaseClient to support multipart uploads.

Copilot uses AI. Check for mistakes.
Comment on lines +170 to +185
"""
Retrieve Recorded Future intelligence for a URL.

Calls ``GET /v2/url/{url}`` (URL-encoded by the HTTP layer).

Parameters
----------
url : str
Full URL to look up.
fields : str
Comma-separated list of RF fields to include.
"""
import urllib.parse
encoded = urllib.parse.quote(url, safe="")
resp = self.get(f"/v2/url/{encoded}", params={"fields": fields})
return resp.get("data", {}) if isinstance(resp, dict) else {}
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lookup_url() docstring says the URL is "URL-encoded by the HTTP layer", but BaseClient does not encode path segments and this method explicitly percent-encodes url before calling get(). Please update the docstring to reflect that the method performs URL encoding itself (or, if you want the HTTP layer to handle it, remove the manual encoding and ensure the client safely encodes path segments).

Copilot uses AI. Check for mistakes.
Comment on lines +618 to +626
resp = self.get(
f"/v2/{entity_type}/risklist",
params={"format": output_format, "threshold": risk_threshold},
)
if isinstance(resp, bytes):
return resp
if isinstance(resp, str):
return resp.encode()
return b""
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

download_risk_list() is documented/typed to return raw bytes, but BaseClient.get() never returns bytes (it returns parsed JSON or a decoded str). That makes the isinstance(resp, bytes) branch dead code, and the str -> .encode() fallback can corrupt non-UTF8/binary content. If this endpoint is meant to be downloaded losslessly, add a raw-bytes request path (e.g., call self._http.request(...) directly and return response.data) or add a raw=True option to BaseClient.get().

Copilot uses AI. Check for mistakes.
Comment on lines +665 to +672
import urllib.parse
encoded_path = urllib.parse.quote(path, safe="")
resp = self.get(f"/v2/fusion/files/{encoded_path}")
if isinstance(resp, bytes):
return resp
if isinstance(resp, str):
return resp.encode()
return b""
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as download_risk_list(): download_fusion_file() claims to return raw bytes, but BaseClient.get() cannot return bytes, so the isinstance(resp, bytes) branch is unreachable and the str re-encoding can corrupt binary content. Consider implementing a raw download path that returns response.data directly for Fusion files.

Copilot uses AI. Check for mistakes.
Comment on lines +748 to +759
resp = self.post(
"search/jobs/oneshot",
data={
"search": search if search.startswith("search ") else f"search {search}",
"earliest_time": earliest_time,
"latest_time": latest_time,
"count": count,
"output_mode": "json",
},
namespaced=False,
)
return (resp or {}).get("results", [])
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

run_search() re-implements one-shot search request construction (including the search prefix logic) instead of reusing the existing _run_oneshot_search() helper. This duplicates behavior in two places and increases the chance of drift (e.g., output_mode, escaping, or future parameters). Consider extending _run_oneshot_search() to accept time bounds/count (or have run_search() delegate to it) so there is a single implementation for one-shot searches.

Suggested change
resp = self.post(
"search/jobs/oneshot",
data={
"search": search if search.startswith("search ") else f"search {search}",
"earliest_time": earliest_time,
"latest_time": latest_time,
"count": count,
"output_mode": "json",
},
namespaced=False,
)
return (resp or {}).get("results", [])
resp = self._run_oneshot_search(
search,
earliest_time=earliest_time,
latest_time=latest_time,
count=count,
)
return (resp or {}).get("results", []) if isinstance(resp, dict) else (resp or [])

Copilot uses AI. Check for mistakes.
Comment on lines +952 to +962
body = _json.dumps(payload).encode("utf-8")
url = f"{hec_base}/services/collector/event"
headers = {
"Authorization": f"Splunk {token}",
"Content-Type": "application/json",
}
response = self._splunk_http.request("POST", url, body=body, headers=headers)
try:
return _json.loads(response.data.decode("utf-8")) if response.data else {}
except Exception:
return {}
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

send_hec_event() does not check response.status and swallows JSON parsing errors by returning {}. This can silently hide HEC failures (401/403 for bad token, 4xx/5xx, etc.) and make it hard to diagnose delivery issues. Consider validating the HTTP status and raising a connector-specific error (or at least returning a structured error including status/body) when the request fails.

Copilot uses AI. Check for mistakes.
Comment on lines +999 to +1003
try:
return _json.loads(response.data.decode("utf-8")) if response.data else {}
except Exception:
return {}

Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

send_hec_events_batch() also ignores response.status and returns {} on JSON parsing errors, which can silently drop entire batches without surfacing the underlying failure. Consider checking the status code and surfacing the response body/status to callers (or raising an exception) so batch delivery failures are observable.

Suggested change
try:
return _json.loads(response.data.decode("utf-8")) if response.data else {}
except Exception:
return {}
response_text = response.data.decode("utf-8", errors="replace") if response.data else ""
if not (200 <= response.status < 300):
raise SplunkAPIError(
f"HEC batch request failed with status {response.status}: {response_text or '<empty response>'}"
)
if not response_text:
return {}
try:
return _json.loads(response_text)
except Exception as exc:
raise SplunkAPIError(
f"HEC batch request returned invalid JSON with status {response.status}: {response_text}"
) from exc

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +32
from .alerts import SentinelAlertCommands
from .analytic_rules import SentinelAnalyticRuleCommands
from .client import SentinelClient
from .config import SentinelConfig
from .hunting import SentinelHuntingCommands
from .incidents import SentinelIncidentCommands
from .stix_mapper import SentinelSTIXMapper
from .threat_intel import SentinelThreatIntelCommands
from .watchlists import SentinelWatchlistCommands
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR title suggests this change is about adding Claude documentation, but the diff primarily adds many new API helper methods across multiple connector clients (XSOAR, VirusTotal, ThreatQ, Splunk, Sentinel, etc.). Consider updating the PR title/description to match the actual scope so reviewers understand the intent and can assess impact appropriately.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants