diff --git a/README.md b/README.md index 2881398..a338113 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ commands: - id: get_ip_report name: Get IP report description: Reputation for an IP address. + risk: read # read | safe_write | destructive — see below inputs_schema: properties: ip: @@ -93,6 +94,7 @@ commands: - id: enrich_custom name: Custom enrichment description: Runs scripts/enrich_custom.py in a sandbox. + risk: read inputs_schema: properties: indicator: @@ -107,6 +109,27 @@ A command is **request-based** when it has a `request:` block, or **script-based** when a matching `scripts/.py` exists. Prefer request-based commands: they need no sandbox and are easier to audit. +### `risk:` — the agent approval gate + +Every command declares a tier. It is what Riposte's agent approval gate reads: +`read` runs unattended, `safe_write` and `destructive` sit behind the operator's +configured threshold. An omitted `risk` is treated as **destructive** — safe, but +it makes a lookup as noisy as an isolation, so declare it rather than default it. + +| Tier | What belongs there | +|------|--------------------| +| `read` | Only queries. Changes nothing outside Riposte: lookups, searches, telemetry, fetching a job's result. | +| `safe_write` | Additive or reversible, inside the tool's own case/enrichment plane: comments, notes, tags, tickets, alert statuses, threat-intel records, sandbox submissions, collection jobs, outbound messages. | +| `destructive` | Changes the estate or weakens a control: containment **and its removal**, blocklists and allowlists, exclusions and detection rules, every delete, identity and credential operations, running code on a host, generic API escape hatches. | + +Two rules the catalog applies consistently, because they are not obvious: + +- **Undoing a containment is tiered like the containment it lifts.** Un-isolating + a host or un-banning an IP mid-incident is its own decision, not a return to a + neutral state. +- **Retrieving a live secret is `destructive`.** It is a `GET`, but the tier + describes the stake, not the HTTP verb. + --- ## Adding this catalog to Riposte diff --git a/integrations/abuseipdb/manifest.yaml b/integrations/abuseipdb/manifest.yaml index 5fb6a13..95d2665 100644 --- a/integrations/abuseipdb/manifest.yaml +++ b/integrations/abuseipdb/manifest.yaml @@ -1,8 +1,8 @@ id: abuseipdb name: AbuseIPDB -version: 1.0.0 +version: 1.1.0 description: "AbuseIPDB (API v2) — check the abuse reputation of an IP, report abusive IPs, pull the blacklist and check a CIDR block. API-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: IP reputation check, report, blacklist retrieval and CIDR-block check." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: IP reputation check, report, blacklist retrieval and CIDR-block check." category: enrichment config_schema: @@ -29,6 +29,7 @@ commands: - id: report_ip name: abuseipdb-report-ip description: "Report an abusive IP address to AbuseIPDB." + risk: destructive inputs_schema: properties: ip: { type: string, description: "IP address to report" } diff --git a/integrations/active-directory/manifest.yaml b/integrations/active-directory/manifest.yaml index 839d0ff..bda2bd4 100644 --- a/integrations/active-directory/manifest.yaml +++ b/integrations/active-directory/manifest.yaml @@ -1,8 +1,8 @@ id: active_directory name: Active Directory -version: 1.0.0 +version: 1.1.0 description: "Active Directory over LDAP/LDAPS — query and manage users, computers, groups and contacts (search, enable/disable/unlock, set/expire password, group membership, OU moves, create/update/delete). Runs on a remote engine inside the AD network. Requires the Python 'ldap3' library on the engine host (pip install ldap3)." -changelog: "1.0.0 — Initial release: full directory administration over LDAP (search, get user/computer/group-members, create/update/delete user/contact/group, enable/disable/unlock, set/expire password, password-never-expire, add/remove group membership, move user/computer OU, test credentials)." +changelog: "1.1.0 — Declare the risk tier on the 18 commands that carried none: 3 safe_write, 15 destructive. An unset risk is read as destructive by the agent approval gate, so the 3 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: full directory administration over LDAP (search, get user/computer/group-members, create/update/delete user/contact/group, enable/disable/unlock, set/expire password, password-never-expire, add/remove group membership, move user/computer OU, test credentials)." category: identity # Per-instance configuration. The integration binds to a Domain Controller over @@ -139,6 +139,7 @@ commands: - id: ad_enable_account name: ad-enable-account description: "Enable a previously disabled user account." + risk: destructive inputs_schema: properties: username: { type: string, description: "sAMAccountName of the account to enable" } @@ -149,6 +150,7 @@ commands: - id: ad_disable_account name: ad-disable-account description: "Disable a user account." + risk: destructive inputs_schema: properties: username: { type: string, description: "sAMAccountName of the account to disable" } @@ -158,6 +160,7 @@ commands: - id: ad_unlock_account name: ad-unlock-account description: "Unlock a locked-out user account." + risk: destructive inputs_schema: properties: username: { type: string, description: "sAMAccountName of the account to unlock" } @@ -167,6 +170,7 @@ commands: - id: ad_set_new_password name: ad-set-new-password description: "Set a new password for a user. Requires a secure connection (SSL or TLS)." + risk: destructive inputs_schema: properties: username: { type: string, description: "sAMAccountName whose password will be set" } @@ -177,6 +181,7 @@ commands: - id: ad_expire_password name: ad-expire-password description: "Force a user to change their password at next login." + risk: destructive inputs_schema: properties: username: { type: string, description: "sAMAccountName of the user" } @@ -186,6 +191,7 @@ commands: - id: ad_modify_password_never_expire name: ad-modify-password-never-expire description: "Set or clear the 'Password Never Expire' flag on a user account." + risk: destructive inputs_schema: properties: username: { type: string, description: "sAMAccountName of the user" } @@ -197,6 +203,7 @@ commands: - id: ad_add_to_group name: ad-add-to-group description: "Add a user, computer or nested group to a group." + risk: destructive inputs_schema: properties: username: { type: string, description: "Username(s) to add (single or CSV). Mutually exclusive with computer-name." } @@ -209,6 +216,7 @@ commands: - id: ad_remove_from_group name: ad-remove-from-group description: "Remove a user or computer from a group." + risk: destructive inputs_schema: properties: username: { type: string, description: "Username to remove. Mutually exclusive with computer-name." } @@ -222,6 +230,7 @@ commands: - id: ad_modify_user_ou name: ad-modify-user-ou description: "Move a user to a different organizational unit within the domain." + risk: destructive inputs_schema: properties: user-name: { type: string, description: "Name of the user to move" } @@ -232,6 +241,7 @@ commands: - id: ad_modify_computer_ou name: ad-modify-computer-ou description: "Move a computer to a different organizational unit within the domain." + risk: destructive inputs_schema: properties: computer-name: { type: string, description: "Name of the computer to move" } @@ -244,6 +254,7 @@ commands: - id: ad_create_user name: ad-create-user description: "Create a user account, set its initial password and enable it. Requires a secure connection (SSL or TLS)." + risk: destructive inputs_schema: properties: username: { type: string, description: "sAMAccountName for the new user" } @@ -260,6 +271,7 @@ commands: - id: ad_update_user name: ad-update-user description: "Replace a single attribute on an existing user." + risk: destructive inputs_schema: properties: username: { type: string, description: "sAMAccountName of the user" } @@ -271,6 +283,7 @@ commands: - id: ad_delete_user name: ad-delete-user description: "Delete a user (or any object) by its DN." + risk: destructive inputs_schema: properties: user-dn: { type: string, description: "DN of the object to delete" } @@ -281,6 +294,7 @@ commands: - id: ad_create_contact name: ad-create-contact description: "Create a contact object." + risk: safe_write inputs_schema: properties: contact-dn: { type: string, description: "Full DN of the new contact" } @@ -295,6 +309,7 @@ commands: - id: ad_update_contact name: ad-update-contact description: "Replace a single attribute on an existing contact." + risk: safe_write inputs_schema: properties: contact-dn: { type: string, description: "DN of the contact" } @@ -307,6 +322,7 @@ commands: - id: ad_create_group name: ad-create-group description: "Create a security or distribution group." + risk: safe_write inputs_schema: properties: name: { type: string, description: "Group name (sAMAccountName)" } @@ -318,6 +334,7 @@ commands: - id: ad_update_group name: ad-update-group description: "Replace a single attribute on an existing group." + risk: destructive inputs_schema: properties: groupname: { type: string, description: "Group name (cn) to update" } @@ -329,6 +346,7 @@ commands: - id: ad_delete_group name: ad-delete-group description: "Delete a security or distribution group by its DN." + risk: destructive inputs_schema: properties: dn: { type: string, description: "DN of the group" } diff --git a/integrations/anomali-threatstream/manifest.yaml b/integrations/anomali-threatstream/manifest.yaml index 3a97b40..71c9091 100644 --- a/integrations/anomali-threatstream/manifest.yaml +++ b/integrations/anomali-threatstream/manifest.yaml @@ -1,8 +1,8 @@ id: anomali_threatstream name: Anomali ThreatStream -version: 1.0.0 +version: 1.1.0 description: "Anomali ThreatStream (API v2/v1) — threat intelligence: reputation lookups for IPs, domains, file hashes and URLs, indicator search, passive DNS, threat-model listing, and indicator import (with or without approval). API-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: ip/domain/file/url reputation, indicator search, passive DNS, threat models, import indicator." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: ip/domain/file/url reputation, indicator search, passive DNS, threat models, import indicator." category: threat_intel # Per-instance configuration. Auth header 'Authorization: apikey :'. @@ -93,6 +93,7 @@ commands: - id: import_indicator name: anomali-import-indicator description: "Import an observable as an indicator (optionally requiring approval)." + risk: safe_write inputs_schema: properties: value: { type: string, description: "Observable value (IP, domain, hash, URL)" } diff --git a/integrations/anyrun/manifest.yaml b/integrations/anyrun/manifest.yaml index 3419c0c..af12c9e 100644 --- a/integrations/anyrun/manifest.yaml +++ b/integrations/anyrun/manifest.yaml @@ -1,8 +1,8 @@ id: anyrun name: ANY.RUN -version: 1.0.0 +version: 1.1.0 description: "ANY.RUN (API v1) — interactive malware sandbox: detonate files and URLs on Windows/Linux, poll the analysis report and verdict, list analysis history, read user limits and delete tasks. API-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: file/URL detonation, report and verdict retrieval, analysis history, user limits and task deletion." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none: 2 safe_write, 1 destructive. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: file/URL detonation, report and verdict retrieval, analysis history, user limits and task deletion." category: enrichment # The API key is sent as 'Authorization: API-Key ' on every request. @@ -19,6 +19,7 @@ commands: - id: detonate_file name: anyrun-detonate-file description: "Detonate a file (base64) in the ANY.RUN sandbox. Returns a task_id; poll with anyrun-get-report." + risk: safe_write inputs_schema: properties: file_name: { type: string, description: "File name" } @@ -30,6 +31,7 @@ commands: - id: detonate_url name: anyrun-detonate-url description: "Detonate a URL in the ANY.RUN sandbox. Returns a task_id." + risk: safe_write inputs_schema: properties: url: { type: string, description: "URL to detonate" } @@ -67,6 +69,7 @@ commands: - id: delete_task name: anyrun-delete-task description: "Delete an analysis task by ID." + risk: destructive inputs_schema: properties: task_id: { type: string, description: "Task ID" } diff --git a/integrations/armis/manifest.yaml b/integrations/armis/manifest.yaml index b123884..9ef27e5 100644 --- a/integrations/armis/manifest.yaml +++ b/integrations/armis/manifest.yaml @@ -1,8 +1,8 @@ id: armis name: Armis -version: 1.0.0 +version: 1.1.0 description: "Armis (API v1) — device and asset visibility: search devices and alerts with AQL, read a device, and update an alert's status. Secret-key (token exchange) authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: search devices/alerts, get device, update alert status." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: search devices/alerts, get device, update alert status." category: asset_management # Per-instance configuration. The secret key is exchanged for a short-lived @@ -53,6 +53,7 @@ commands: - id: update_alert name: armis-update-alert description: "Update an alert's status." + risk: safe_write inputs_schema: properties: alert_id: { type: string, description: "Alert ID" } diff --git a/integrations/automox/manifest.yaml b/integrations/automox/manifest.yaml index 175010d..1bd3201 100644 --- a/integrations/automox/manifest.yaml +++ b/integrations/automox/manifest.yaml @@ -1,8 +1,8 @@ id: automox name: Automox -version: 1.0.0 +version: 1.1.0 description: "Automox (API) — endpoint patch and configuration management: list and read devices, list policies, and queue a command (e.g. install updates or run a policy) on a device. API-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get devices, list policies, run device command." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list/get devices, list policies, run device command." category: endpoint # Per-instance configuration. Auth header 'Authorization: Bearer '. @@ -49,6 +49,7 @@ commands: - id: run_command name: automox-run-command description: "Queue a command on a device (e.g. InstallUpdate, Reboot)." + risk: destructive inputs_schema: properties: device_id: { type: string, description: "Device (server) ID" } diff --git a/integrations/aws/manifest.yaml b/integrations/aws/manifest.yaml index c152fdd..9580f21 100644 --- a/integrations/aws/manifest.yaml +++ b/integrations/aws/manifest.yaml @@ -1,8 +1,8 @@ id: aws name: AWS -version: 1.0.0 +version: 1.1.0 description: "Amazon Web Services (EC2, IAM, STS) — cloud containment: describe instances and security groups, authorize/revoke security-group ingress rules, change an instance's security groups (isolate), stop instances, and deactivate a compromised IAM access key. AWS Signature V4 authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: EC2 describe instances/security-groups, authorize/revoke ingress, modify instance security groups, stop instances; IAM list/update access keys; STS caller identity." +changelog: "1.1.0 — Declare the risk tier on the 5 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: EC2 describe instances/security-groups, authorize/revoke ingress, modify instance security groups, stop instances; IAM list/update access keys; STS caller identity." category: cloud # Per-instance configuration. Requests are signed with AWS Signature V4. @@ -53,6 +53,7 @@ commands: - id: authorize_security_group_ingress name: aws-authorize-security-group-ingress description: "Add an inbound rule to a security group." + risk: destructive inputs_schema: properties: group_id: { type: string, description: "Security group ID" } @@ -66,6 +67,7 @@ commands: - id: revoke_security_group_ingress name: aws-revoke-security-group-ingress description: "Remove an inbound rule from a security group (containment)." + risk: destructive inputs_schema: properties: group_id: { type: string, description: "Security group ID" } @@ -79,6 +81,7 @@ commands: - id: modify_instance_security_groups name: aws-modify-instance-security-groups description: "Replace the security groups attached to an instance (e.g. move it to an isolation group)." + risk: destructive inputs_schema: properties: instance_id: { type: string, description: "Instance ID" } @@ -89,6 +92,7 @@ commands: - id: stop_instances name: aws-stop-instances description: "Stop one or more EC2 instances." + risk: destructive inputs_schema: properties: instance_ids: { type: string, description: "Comma-separated instance IDs" } @@ -108,6 +112,7 @@ commands: - id: update_access_key name: aws-update-access-key description: "Activate or deactivate an IAM access key (deactivate to contain a compromised key)." + risk: destructive inputs_schema: properties: access_key_id: { type: string, description: "The access key ID to update" } diff --git a/integrations/azure-security/manifest.yaml b/integrations/azure-security/manifest.yaml index c49d023..dba7016 100644 --- a/integrations/azure-security/manifest.yaml +++ b/integrations/azure-security/manifest.yaml @@ -1,8 +1,8 @@ id: azure_security name: Microsoft Azure -version: 1.0.0 +version: 1.1.0 description: "Microsoft Azure (Resource Manager: Defender for Cloud + Network) — cloud containment: list and read Defender for Cloud security alerts and update their state, read the secure score, list/read network security groups (NSGs), and add or delete NSG security rules (deny inbound to isolate). Azure AD OAuth2 client-credentials authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get security alerts, update alert state, secure score, list/get NSGs, create/delete NSG security rules." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none: 1 safe_write, 2 destructive. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list/get security alerts, update alert state, secure score, list/get NSGs, create/delete NSG security rules." category: cloud # Per-instance configuration. Uses application (client-credentials) OAuth2 with @@ -50,6 +50,7 @@ commands: - id: update_alert_state name: azure-update-alert-state description: "Change a security alert's state (dismiss, resolve, activate, or inProgress)." + risk: safe_write inputs_schema: properties: alert_id: { type: string, description: "Full ARM resource ID of the alert" } @@ -85,6 +86,7 @@ commands: - id: create_nsg_rule name: azure-create-nsg-rule description: "Create or update an NSG security rule (e.g. a Deny inbound rule to isolate a resource)." + risk: destructive inputs_schema: properties: resource_group: { type: string, description: "Resource group name" } @@ -102,6 +104,7 @@ commands: - id: delete_nsg_rule name: azure-delete-nsg-rule description: "Delete an NSG security rule." + risk: destructive inputs_schema: properties: resource_group: { type: string, description: "Resource group name" } diff --git a/integrations/beyondtrust-password-safe/manifest.yaml b/integrations/beyondtrust-password-safe/manifest.yaml index 22606b2..20e6d7e 100644 --- a/integrations/beyondtrust-password-safe/manifest.yaml +++ b/integrations/beyondtrust-password-safe/manifest.yaml @@ -1,8 +1,8 @@ id: beyondtrust_password_safe name: BeyondTrust Password Safe -version: 1.0.0 +version: 1.1.0 description: "BeyondTrust Password Safe (Secrets Safe REST API v3) — privileged access and credential retrieval: list managed accounts and systems, request a credential release, and retrieve the credential. API-key (PS-Auth) session authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list managed accounts/systems, create release request, get credential." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 1 safe_write, 1 destructive. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list managed accounts/systems, create release request, get credential." category: identity # Per-instance configuration. Auth signs in with an API key + runas user @@ -50,6 +50,7 @@ commands: - id: create_release_request name: beyondtrust-create-release-request description: "Request a credential release for a managed account." + risk: safe_write inputs_schema: properties: system_id: { type: string, description: "Managed system ID" } @@ -61,6 +62,7 @@ commands: - id: get_credential name: beyondtrust-get-credential description: "Retrieve the credential for an approved request." + risk: destructive inputs_schema: properties: request_id: { type: string, description: "Request ID (from create-release-request)" } diff --git a/integrations/box/manifest.yaml b/integrations/box/manifest.yaml index 8b05756..52c0c03 100644 --- a/integrations/box/manifest.yaml +++ b/integrations/box/manifest.yaml @@ -1,8 +1,8 @@ id: box name: Box -version: 1.0.0 +version: 1.1.0 description: "Box (Content API v2) — evidence and file handling: search files, read file/folder metadata, list a folder's items, and create a shared link. Bearer-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: search, get file/folder info, list folder items, create shared link." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: search, get file/folder info, list folder items, create shared link." category: productivity # Per-instance configuration. Auth header 'Authorization: Bearer '. @@ -57,6 +57,7 @@ commands: - id: create_shared_link name: box-create-shared-link description: "Create a shared link for a file." + risk: destructive inputs_schema: properties: file_id: { type: string, description: "File ID" } diff --git a/integrations/cape/manifest.yaml b/integrations/cape/manifest.yaml index 4e00f36..cd71721 100644 --- a/integrations/cape/manifest.yaml +++ b/integrations/cape/manifest.yaml @@ -1,8 +1,8 @@ id: cape name: CAPE Sandbox -version: 1.0.0 +version: 1.1.0 description: "CAPE Sandbox (APIv2) — dynamic malware analysis and config extraction: submit files and URLs, read task status and reports, and list tasks. Token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: submit file/URL, get task, get report, list tasks." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 2 safe_write. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: submit file/URL, get task, get report, list tasks." category: enrichment # Per-instance configuration. The token is sent as 'Authorization: Token '. @@ -27,6 +27,7 @@ commands: - id: submit_file name: cape-submit-file description: "Submit a file (base64) for analysis." + risk: safe_write inputs_schema: properties: file_name: { type: string, description: "File name" } @@ -36,6 +37,7 @@ commands: - id: submit_url name: cape-submit-url description: "Submit a URL for analysis." + risk: safe_write inputs_schema: properties: url: { type: string, description: "URL to detonate" } diff --git a/integrations/carbon-black-cloud/manifest.yaml b/integrations/carbon-black-cloud/manifest.yaml index fe11415..df998cf 100644 --- a/integrations/carbon-black-cloud/manifest.yaml +++ b/integrations/carbon-black-cloud/manifest.yaml @@ -1,8 +1,8 @@ id: carbon_black_cloud name: VMware Carbon Black Cloud -version: 1.0.0 +version: 1.1.0 description: "VMware Carbon Black Cloud (Platform API) — endpoint containment: search and read devices, quarantine/unquarantine an endpoint, trigger a background scan, update a device's policy, search alerts, and ban/unban a file hash (reputation override). API-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: device search/get, quarantine/unquarantine, background scan, update policy, alert search, ban hash, delete reputation override." +changelog: "1.1.0 — Declare the risk tier on the 6 commands that carried none: 1 safe_write, 5 destructive. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: device search/get, quarantine/unquarantine, background scan, update policy, alert search, ban hash, delete reputation override." category: endpoint # Per-instance configuration. The API token is sent as @@ -51,6 +51,7 @@ commands: - id: quarantine_device name: cbc-quarantine-device description: "Quarantine (network-isolate) a device." + risk: destructive inputs_schema: properties: device_id: { type: string, description: "Device ID" } @@ -59,6 +60,7 @@ commands: - id: unquarantine_device name: cbc-unquarantine-device description: "Remove a device from quarantine." + risk: destructive inputs_schema: properties: device_id: { type: string, description: "Device ID" } @@ -67,6 +69,7 @@ commands: - id: background_scan name: cbc-background-scan description: "Start or stop a background scan on a device." + risk: safe_write inputs_schema: properties: device_id: { type: string, description: "Device ID" } @@ -76,6 +79,7 @@ commands: - id: update_device_policy name: cbc-update-device-policy description: "Assign a device to a different policy." + risk: destructive inputs_schema: properties: device_id: { type: string, description: "Device ID" } @@ -98,6 +102,7 @@ commands: - id: ban_hash name: cbc-ban-hash description: "Ban a file by SHA-256 hash (reputation deny-list override)." + risk: destructive inputs_schema: properties: sha256: { type: string, description: "SHA-256 hash to ban" } @@ -108,6 +113,7 @@ commands: - id: delete_reputation_override name: cbc-delete-reputation-override description: "Delete a reputation override (unban) by its ID." + risk: destructive inputs_schema: properties: override_id: { type: string, description: "Reputation override ID" } diff --git a/integrations/checkpoint/manifest.yaml b/integrations/checkpoint/manifest.yaml index d07a6f8..85c5fab 100644 --- a/integrations/checkpoint/manifest.yaml +++ b/integrations/checkpoint/manifest.yaml @@ -1,8 +1,8 @@ id: checkpoint name: Check Point -version: 1.0.0 +version: 1.1.0 description: "Check Point Management (Web API) — firewall containment: list and add host objects, view the access rulebase, add a drop rule (block), publish changes, and install policy. Session (login) authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: show/add hosts, show access rulebase, add access rule (drop), publish, install policy." +changelog: "1.1.0 — Declare the risk tier on the 4 commands that carried none: 1 safe_write, 3 destructive. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: show/add hosts, show access rulebase, add access rule (drop), publish, install policy." category: network # Per-instance configuration. Each command logs in to the Management API @@ -45,6 +45,7 @@ commands: - id: add_host name: checkpoint-add-host description: "Create a host object." + risk: safe_write inputs_schema: properties: name: { type: string, description: "Host object name" } @@ -64,6 +65,7 @@ commands: - id: add_access_rule name: checkpoint-add-access-rule description: "Add an access rule to a layer (e.g. a Drop rule to block a source)." + risk: destructive inputs_schema: properties: layer: { type: string, description: "Access layer name" } @@ -77,6 +79,7 @@ commands: - id: publish name: checkpoint-publish description: "Publish the current session's changes." + risk: destructive inputs_schema: properties: {} required: [] @@ -84,6 +87,7 @@ commands: - id: install_policy name: checkpoint-install-policy description: "Install a policy package on gateway targets." + risk: destructive inputs_schema: properties: policy_package: { type: string, description: "Policy package name" } diff --git a/integrations/cisco-fmc/manifest.yaml b/integrations/cisco-fmc/manifest.yaml index fdced62..5d4c012 100644 --- a/integrations/cisco-fmc/manifest.yaml +++ b/integrations/cisco-fmc/manifest.yaml @@ -1,8 +1,8 @@ id: cisco_fmc name: Cisco Firepower Management Center -version: 1.0.0 +version: 1.1.0 description: "Cisco Secure Firewall Management Center (FMC REST API) — firewall containment: list and create/delete network host objects, list access policies and rules, and add a block access rule. Token authentication (generatetoken); stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/create/delete host objects, list access policies/rules, create block access rule." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none: 1 safe_write, 2 destructive. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list/create/delete host objects, list access policies/rules, create block access rule." category: network # Per-instance configuration. Auth calls generatetoken with HTTP Basic and reuses @@ -41,6 +41,7 @@ commands: - id: create_host_object name: fmc-create-host-object description: "Create a network host object." + risk: safe_write inputs_schema: properties: name: { type: string, description: "Object name" } @@ -51,6 +52,7 @@ commands: - id: delete_host_object name: fmc-delete-host-object description: "Delete a network host object by ID." + risk: destructive inputs_schema: properties: object_id: { type: string, description: "Host object ID" } @@ -78,6 +80,7 @@ commands: - id: create_access_rule name: fmc-create-access-rule description: "Add an access rule to a policy (e.g. a BLOCK rule for source/destination network objects)." + risk: destructive inputs_schema: properties: policy_id: { type: string, description: "Access control policy ID" } diff --git a/integrations/cisco-ise/manifest.yaml b/integrations/cisco-ise/manifest.yaml index 395dec9..98c6569 100644 --- a/integrations/cisco-ise/manifest.yaml +++ b/integrations/cisco-ise/manifest.yaml @@ -1,8 +1,8 @@ id: cisco_ise name: Cisco ISE -version: 1.0.0 +version: 1.1.0 description: "Cisco Identity Services Engine (ERS + ANC API) — network access containment: list and read endpoints, apply an Adaptive Network Control (ANC) quarantine policy to an endpoint, and clear it. HTTP Basic authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get endpoints, apply/clear ANC policy, list ANC policies." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list/get endpoints, apply/clear ANC policy, list ANC policies." category: network # Per-instance configuration. HTTP Basic auth against the ERS API (port 9060). @@ -49,6 +49,7 @@ commands: - id: apply_anc_policy name: ise-apply-anc-policy description: "Apply an ANC policy to an endpoint by MAC (quarantine — containment)." + risk: destructive inputs_schema: properties: mac: { type: string, description: "Endpoint MAC address" } @@ -58,6 +59,7 @@ commands: - id: clear_anc_policy name: ise-clear-anc-policy description: "Clear the ANC policy from an endpoint by MAC." + risk: destructive inputs_schema: properties: mac: { type: string, description: "Endpoint MAC address" } diff --git a/integrations/cisco-secure-endpoint/manifest.yaml b/integrations/cisco-secure-endpoint/manifest.yaml index c0605ce..56b217d 100644 --- a/integrations/cisco-secure-endpoint/manifest.yaml +++ b/integrations/cisco-secure-endpoint/manifest.yaml @@ -1,8 +1,8 @@ id: cisco_secure_endpoint name: Cisco Secure Endpoint -version: 1.0.0 +version: 1.1.0 description: "Cisco Secure Endpoint (AMP for Endpoints API v1) — endpoint containment: list and read computers, isolate/unisolate a host, list events, and read a computer's trajectory. HTTP Basic authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get computers, isolate/stop-isolation, list events, get trajectory." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list/get computers, isolate/stop-isolation, list events, get trajectory." category: endpoint # Per-instance configuration. HTTP Basic auth with the API client ID + key. @@ -46,6 +46,7 @@ commands: - id: isolate_computer name: cisco-amp-isolate-computer description: "Isolate a computer from the network (containment)." + risk: destructive inputs_schema: properties: connector_guid: { type: string, description: "Connector GUID" } @@ -55,6 +56,7 @@ commands: - id: stop_isolation name: cisco-amp-stop-isolation description: "Stop isolation on a computer." + risk: destructive inputs_schema: properties: connector_guid: { type: string, description: "Connector GUID" } diff --git a/integrations/cisco-umbrella-enforcement/manifest.yaml b/integrations/cisco-umbrella-enforcement/manifest.yaml index 5f27aa0..117a6c2 100644 --- a/integrations/cisco-umbrella-enforcement/manifest.yaml +++ b/integrations/cisco-umbrella-enforcement/manifest.yaml @@ -1,8 +1,8 @@ id: cisco_umbrella_enforcement name: Cisco Umbrella Enforcement -version: 1.0.0 +version: 1.1.0 description: "Cisco Umbrella Enforcement API — DNS-layer containment: push malicious domains to the enforcement block list, list enforced domains, and remove them. Customer-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: add domain event (block), list domains, delete domain." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: add domain event (block), list domains, delete domain." category: network # Per-instance configuration. The customer key is appended as the 'customerKey' @@ -24,6 +24,7 @@ commands: - id: add_domain name: umbrella-add-domain description: "Submit a security event that adds a domain to the Umbrella enforcement block list." + risk: destructive inputs_schema: properties: domain: { type: string, description: "Domain to block (e.g. malicious.example.com)" } @@ -46,6 +47,7 @@ commands: - id: delete_domain name: umbrella-delete-domain description: "Remove a domain from the enforcement block list by its numeric id." + risk: destructive inputs_schema: properties: domain_id: { type: string, description: "Numeric id of the domain to remove (from umbrella-list-domains)" } diff --git a/integrations/cloudflare/manifest.yaml b/integrations/cloudflare/manifest.yaml index 5ebfced..75ace82 100644 --- a/integrations/cloudflare/manifest.yaml +++ b/integrations/cloudflare/manifest.yaml @@ -1,8 +1,8 @@ id: cloudflare name: Cloudflare -version: 1.0.0 +version: 1.1.0 description: "Cloudflare (client API v4) — network containment at the edge: list zones, block/unblock IPs (firewall access rules), list access rules, and manage DNS records (list/create/delete). API-token (Bearer) authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get zones, block IP, list/delete access rules, list/create/delete DNS records." +changelog: "1.1.0 — Declare the risk tier on the 4 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list/get zones, block IP, list/delete access rules, list/create/delete DNS records." category: network # Per-instance configuration. The API token is sent as 'Authorization: Bearer '. @@ -37,6 +37,7 @@ commands: - id: block_ip name: cloudflare-block-ip description: "Create a firewall access rule to block (or challenge) an IP, range, ASN, or country." + risk: destructive inputs_schema: properties: zone_id: { type: string, description: "Zone ID" } @@ -58,6 +59,7 @@ commands: - id: delete_access_rule name: cloudflare-delete-access-rule description: "Delete a firewall access rule (unblock)." + risk: destructive inputs_schema: properties: zone_id: { type: string, description: "Zone ID" } @@ -78,6 +80,7 @@ commands: - id: create_dns_record name: cloudflare-create-dns-record description: "Create a DNS record (e.g. sinkhole a malicious host)." + risk: destructive inputs_schema: properties: zone_id: { type: string, description: "Zone ID" } @@ -91,6 +94,7 @@ commands: - id: delete_dns_record name: cloudflare-delete-dns-record description: "Delete a DNS record." + risk: destructive inputs_schema: properties: zone_id: { type: string, description: "Zone ID" } diff --git a/integrations/confluence/manifest.yaml b/integrations/confluence/manifest.yaml index 52fe721..0434232 100644 --- a/integrations/confluence/manifest.yaml +++ b/integrations/confluence/manifest.yaml @@ -1,8 +1,8 @@ id: confluence name: Confluence -version: 1.0.0 +version: 1.1.0 description: "Atlassian Confluence (REST API) — runbook and knowledge handling: search content (CQL), read a page, create and update pages, and list spaces. Basic (email + API token) authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: search content, get page, create/update page, list spaces." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 2 safe_write. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: search content, get page, create/update page, list spaces." category: productivity # Per-instance configuration. HTTP Basic auth with an email + API token (Cloud) @@ -47,6 +47,7 @@ commands: - id: create_page name: confluence-create-page description: "Create a page in a space." + risk: safe_write inputs_schema: properties: space_key: { type: string, description: "Space key" } @@ -58,6 +59,7 @@ commands: - id: update_page name: confluence-update-page description: "Update a page's title/body (increments the version)." + risk: safe_write inputs_schema: properties: page_id: { type: string, description: "Page ID" } diff --git a/integrations/cortex-xdr/manifest.yaml b/integrations/cortex-xdr/manifest.yaml index c3f29e5..acc5a26 100644 --- a/integrations/cortex-xdr/manifest.yaml +++ b/integrations/cortex-xdr/manifest.yaml @@ -1,8 +1,8 @@ id: cortex_xdr name: Cortex XDR -version: 1.5.0 +version: 1.6.0 description: "Palo Alto Cortex XDR (public API v1) — incident and alert ingestion + write-back, endpoint isolation/scan/delete/tagging, XQL queries against the data lake, RTR scripts, hash block/allow lists, file quarantine/restore/retrieval, alert exclusions, external alert push (parsed/CEF), device-control violations, audits, distributions and RBAC/risk." -changelog: "1.5.0 — The full-incident mapper now carries the investigation. XDR names action_process_image_* the process an alert is actually about — the child a prevention module blocked — and it was mapped nowhere, so the single most investigable string in the payload, that process’s command line, existed only inside raw: on a Child Process Protection alert, a WScript.exe invocation on a .js file sitting in the user’s Downloads folder. It fills process.* now, the group the SentinelOne (targetProcessInfo) and Carbon Black (childproc_*) mappers already reserve for the process acted upon. The chain above it lands in process.lineage as OCSF Process objects, root-first and ancestry only, which is what lineage means in OCSF; a generation XDR leaves entirely null — os_actor on an agent-side prevention — drops out rather than showing as an empty level. Every alert’s chain also travels under a process_tree context key, deliberately not an OCSF field: process.lineage describes the ancestry of ONE process, and an XDR incident groups N alerts, each with its own chain and often a shared ancestor, which OCSF has no shape for. Nodes there carry their role because the chain is positional — nothing in the payload links a child to a parent, action_process_instance_id is null, and the *_causality_id fields name the causality GROUP rather than the node, so merging chains on a causality id fuses two distinct processes. Also mapped, all for the same reason: the actor’s pid and MD5, the causality actor’s command line (mapped in the alerts feed but not here), the endpoint’s FQDN, AD domain, MAC and OS build, the protection module that fired and the agent version, the firing alert’s id, the incident id as the correlation key both feeds join on, the activity kind, and the registry, DNS and user-agent fields the other alert kinds in this feed carry. action_country is dropped when it is the literal UNKNOWN, which XDR writes on alerts that have no network dimension at all: mapping it put a destination country on process-execution incidents that never had a destination. 1.4.0 — XQL. Four commands reach the data lake: cortex-xdr-xql-query runs a query and waits for its rows, cortex-xdr-xql-start-query and cortex-xdr-xql-get-query-results split that work in two when the query outlives a command, and cortex-xdr-xql-get-quota says what the day’s hunting has already cost — an XQL query is billed by the data it scans. Two things the API makes easy to get wrong are handled here. Past 1000 rows it stops answering with results and hands over a stream id instead: gzipped JSON lines, unpacked into rows rather than dropped on the playbook as an archive. And a query carrying no limit stage is served the tenant’s own default, so one is appended (100 rows, configurable) unless the query already has its own. Waiting is a budget, not a promise: a command is killed at 60 seconds, so a query still running comes back PENDING with its execution_id, which the results command collects afterwards — re-running the query would be charged against the quota a second time. 1.3.2 — The mappers fill the Actor group, as the HarfangLab and SentinelOne mappers already did. XDR names the process that acted actor_process_* and its account actor_effective_username, but both landed outside the actor: the process in process.*, the account in user.name — the OCSF slot for the user an event was done TO. So a Cortex tenant answered nothing to a correlation or pre-processing rule written on actor.user.name / actor.process.name, and any rule reading user.name as the victim read the attacker instead. actor_process_* now maps to actor.process.*, causality_actor_process_* to actor.process.parent_process.*, actor_effective_username to actor.user.name; process.* is left free for the process acted upon, which is what it holds in the SentinelOne (targetProcessInfo) and Carbon Black (childproc_*) mappers. On get_incidents_full the incident's impacted users[] and the first alert's user_name both wrote user.name, so the alert's actor overwrote the impacted user; they are now two fields. Rules and columns written against the old Cortex paths need repointing. 1.3.1 — get_incidents_full can watermark on modification_time (modified_after), which is what ingestion wants: an XDR incident keeps growing after creation, and a creation_time watermark fetches it once and never looks again, so every alert that joins it afterwards is lost. The full-incident fetch command is named cortex-xdr-get-incidents-full (id get_incidents_full), not cortex-xdr-fetch-incidents: sitting next to cortex-xdr-get-incidents in the command list, it now reads as what it is — the same call, everything included. A rule created against the old id must be pointed at the new one. 1.3.0 — Richer incident ingestion (get_incidents_full, on get_multiple_incidents_extra_data): incidents now arrive with their alerts in full and their file/network artifacts, where get_incidents only ever answered a 21-field summary carrying neither hosts, users, MITRE nor a single alert. Alert ingestion, and the alerts endpoint answers at last: get_alerts was sending the incidents dialect ({filters, search_from, search_to, sort}) to a grid endpoint that speaks request_data.filter_data (SEARCH_FIELD/SEARCH_TYPE/SEARCH_VALUE blocks, paging.from/to, sort as a list), and every call came back HTTP 500. Body rebuilt from the reference client, rows unwrapped out of their alert_fields envelope, severity code and the dotted status.progress key derived into readable fields. Alert ingestion: get_alerts is now a fetch command (results path reply.alerts, dedup on alert_id, incremental on source_insert_ts) with a bundled OCSF mapper and a Cortex XDR Alert incident type, so detections can be ingested alongside — or instead of — incidents. The incident mapper is fixed on the way past: its severity expression compared strings, which the mapping engine cannot do, so every ingested incident silently took the rule's default severity; it also now carries a detection anchor so MTTD is measurable. It pages past the API's 100-results-per-call ceiling, and sorts oldest-first on an incremental fetch so a truncated window drops the alerts the next poll can still see. 1.2.1 — Connection troubleshooting: the URL is normalised to the tenant host (a pasted /public_api/v1 or console path no longer breaks the call), a non-JSON reply reports the status, content type and body instead of a bare JSON parse error, missing key/key ID is caught up front, nonce and timestamp are sent in both auth modes as the reference client does, and test_connection now probes get_incidents. 1.2.0 — Incident write-back (update_incident: status/severity/assignment/resolve comment) and external alert push (insert_parsed_alerts, insert_cef_alerts). 1.1.0 — Full command coverage: added delete/alias/tag endpoints, abort scan, original alerts, script metadata/code/snippet/exec-status, file retrieval (+details), alert exclusions, device-control violations, audits, distribution url/status/create and RBAC (users, roles, groups, risk score, risky users/hosts). 1.0.0 — Initial release: incident ingestion (get_incidents) with OCSF mapper, endpoints, isolate/unisolate, scan, hash blocklist/allowlist, quarantine/restore, run script + results, alerts retrieval, distributions and action status. Standard or Advanced API authentication." +changelog: "1.6.0 — Declare the risk tier on the 25 commands that carried none: 10 safe_write, 15 destructive. An unset risk is read as destructive by the agent approval gate, so the 10 that only annotate sat behind the same prompt as the ones that change the estate. | 1.5.0 — The full-incident mapper now carries the investigation. XDR names action_process_image_* the process an alert is actually about — the child a prevention module blocked — and it was mapped nowhere, so the single most investigable string in the payload, that process’s command line, existed only inside raw: on a Child Process Protection alert, a WScript.exe invocation on a .js file sitting in the user’s Downloads folder. It fills process.* now, the group the SentinelOne (targetProcessInfo) and Carbon Black (childproc_*) mappers already reserve for the process acted upon. The chain above it lands in process.lineage as OCSF Process objects, root-first and ancestry only, which is what lineage means in OCSF; a generation XDR leaves entirely null — os_actor on an agent-side prevention — drops out rather than showing as an empty level. Every alert’s chain also travels under a process_tree context key, deliberately not an OCSF field: process.lineage describes the ancestry of ONE process, and an XDR incident groups N alerts, each with its own chain and often a shared ancestor, which OCSF has no shape for. Nodes there carry their role because the chain is positional — nothing in the payload links a child to a parent, action_process_instance_id is null, and the *_causality_id fields name the causality GROUP rather than the node, so merging chains on a causality id fuses two distinct processes. Also mapped, all for the same reason: the actor’s pid and MD5, the causality actor’s command line (mapped in the alerts feed but not here), the endpoint’s FQDN, AD domain, MAC and OS build, the protection module that fired and the agent version, the firing alert’s id, the incident id as the correlation key both feeds join on, the activity kind, and the registry, DNS and user-agent fields the other alert kinds in this feed carry. action_country is dropped when it is the literal UNKNOWN, which XDR writes on alerts that have no network dimension at all: mapping it put a destination country on process-execution incidents that never had a destination. 1.4.0 — XQL. Four commands reach the data lake: cortex-xdr-xql-query runs a query and waits for its rows, cortex-xdr-xql-start-query and cortex-xdr-xql-get-query-results split that work in two when the query outlives a command, and cortex-xdr-xql-get-quota says what the day’s hunting has already cost — an XQL query is billed by the data it scans. Two things the API makes easy to get wrong are handled here. Past 1000 rows it stops answering with results and hands over a stream id instead: gzipped JSON lines, unpacked into rows rather than dropped on the playbook as an archive. And a query carrying no limit stage is served the tenant’s own default, so one is appended (100 rows, configurable) unless the query already has its own. Waiting is a budget, not a promise: a command is killed at 60 seconds, so a query still running comes back PENDING with its execution_id, which the results command collects afterwards — re-running the query would be charged against the quota a second time. 1.3.2 — The mappers fill the Actor group, as the HarfangLab and SentinelOne mappers already did. XDR names the process that acted actor_process_* and its account actor_effective_username, but both landed outside the actor: the process in process.*, the account in user.name — the OCSF slot for the user an event was done TO. So a Cortex tenant answered nothing to a correlation or pre-processing rule written on actor.user.name / actor.process.name, and any rule reading user.name as the victim read the attacker instead. actor_process_* now maps to actor.process.*, causality_actor_process_* to actor.process.parent_process.*, actor_effective_username to actor.user.name; process.* is left free for the process acted upon, which is what it holds in the SentinelOne (targetProcessInfo) and Carbon Black (childproc_*) mappers. On get_incidents_full the incident's impacted users[] and the first alert's user_name both wrote user.name, so the alert's actor overwrote the impacted user; they are now two fields. Rules and columns written against the old Cortex paths need repointing. 1.3.1 — get_incidents_full can watermark on modification_time (modified_after), which is what ingestion wants: an XDR incident keeps growing after creation, and a creation_time watermark fetches it once and never looks again, so every alert that joins it afterwards is lost. The full-incident fetch command is named cortex-xdr-get-incidents-full (id get_incidents_full), not cortex-xdr-fetch-incidents: sitting next to cortex-xdr-get-incidents in the command list, it now reads as what it is — the same call, everything included. A rule created against the old id must be pointed at the new one. 1.3.0 — Richer incident ingestion (get_incidents_full, on get_multiple_incidents_extra_data): incidents now arrive with their alerts in full and their file/network artifacts, where get_incidents only ever answered a 21-field summary carrying neither hosts, users, MITRE nor a single alert. Alert ingestion, and the alerts endpoint answers at last: get_alerts was sending the incidents dialect ({filters, search_from, search_to, sort}) to a grid endpoint that speaks request_data.filter_data (SEARCH_FIELD/SEARCH_TYPE/SEARCH_VALUE blocks, paging.from/to, sort as a list), and every call came back HTTP 500. Body rebuilt from the reference client, rows unwrapped out of their alert_fields envelope, severity code and the dotted status.progress key derived into readable fields. Alert ingestion: get_alerts is now a fetch command (results path reply.alerts, dedup on alert_id, incremental on source_insert_ts) with a bundled OCSF mapper and a Cortex XDR Alert incident type, so detections can be ingested alongside — or instead of — incidents. The incident mapper is fixed on the way past: its severity expression compared strings, which the mapping engine cannot do, so every ingested incident silently took the rule's default severity; it also now carries a detection anchor so MTTD is measurable. It pages past the API's 100-results-per-call ceiling, and sorts oldest-first on an incremental fetch so a truncated window drops the alerts the next poll can still see. 1.2.1 — Connection troubleshooting: the URL is normalised to the tenant host (a pasted /public_api/v1 or console path no longer breaks the call), a non-JSON reply reports the status, content type and body instead of a bare JSON parse error, missing key/key ID is caught up front, nonce and timestamp are sent in both auth modes as the reference client does, and test_connection now probes get_incidents. 1.2.0 — Incident write-back (update_incident: status/severity/assignment/resolve comment) and external alert push (insert_parsed_alerts, insert_cef_alerts). 1.1.0 — Full command coverage: added delete/alias/tag endpoints, abort scan, original alerts, script metadata/code/snippet/exec-status, file retrieval (+details), alert exclusions, device-control violations, audits, distribution url/status/create and RBAC (users, roles, groups, risk score, risky users/hosts). 1.0.0 — Initial release: incident ingestion (get_incidents) with OCSF mapper, endpoints, isolate/unisolate, scan, hash blocklist/allowlist, quarantine/restore, run script + results, alerts retrieval, distributions and action status. Standard or Advanced API authentication." category: endpoint # Per-instance configuration. The base URL is the tenant API root, e.g. @@ -87,6 +87,7 @@ commands: - id: update_incident name: cortex-xdr-update-incident description: "Update an incident's status, severity, assignment and resolve comment (write-back / close the loop)." + risk: safe_write inputs_schema: properties: incident_id: { type: string, description: "Incident ID to update" } @@ -118,6 +119,7 @@ commands: - id: insert_parsed_alerts name: cortex-xdr-insert-parsed-alerts description: "Push external alerts (parsed JSON objects) into Cortex XDR for correlation." + risk: safe_write inputs_schema: properties: alerts: { type: string, description: "JSON array of parsed alert objects (each with product, vendor, severity, alert_name, etc.)" } @@ -126,6 +128,7 @@ commands: - id: insert_cef_alerts name: cortex-xdr-insert-cef-alerts description: "Push external alerts in CEF format into Cortex XDR for correlation." + risk: safe_write inputs_schema: properties: alerts: { type: string, description: "CEF alert lines: a JSON array of CEF strings, or newline-separated CEF lines" } @@ -149,6 +152,7 @@ commands: - id: isolate_endpoint name: cortex-xdr-isolate-endpoint description: "Network-isolate an endpoint by endpoint (agent) ID." + risk: destructive inputs_schema: properties: endpoint_id: { type: string, description: "Endpoint (agent) ID to isolate" } @@ -158,6 +162,7 @@ commands: - id: unisolate_endpoint name: cortex-xdr-unisolate-endpoint description: "Remove network isolation from an endpoint by endpoint (agent) ID." + risk: destructive inputs_schema: properties: endpoint_id: { type: string, description: "Endpoint (agent) ID to unisolate" } @@ -167,6 +172,7 @@ commands: - id: scan_endpoints name: cortex-xdr-scan-endpoints description: "Trigger a malware scan on endpoints matching the given filters (or all)." + risk: safe_write inputs_schema: properties: endpoint_id_list: { type: string, description: "Comma-separated endpoint IDs (omit + use all=true to scan all)" } @@ -189,6 +195,7 @@ commands: - id: blocklist_files name: cortex-xdr-blocklist-files description: "Add file hashes to the block list." + risk: destructive inputs_schema: properties: hash_list: { type: string, description: "Comma-separated SHA-256 hashes to block" } @@ -199,6 +206,7 @@ commands: - id: remove_blocklist_files name: cortex-xdr-remove-blocklist-files description: "Remove file hashes from the block list." + risk: destructive inputs_schema: properties: hash_list: { type: string, description: "Comma-separated SHA-256 hashes to remove" } @@ -209,6 +217,7 @@ commands: - id: allowlist_files name: cortex-xdr-allowlist-files description: "Add file hashes to the allow list." + risk: destructive inputs_schema: properties: hash_list: { type: string, description: "Comma-separated SHA-256 hashes to allow" } @@ -219,6 +228,7 @@ commands: - id: remove_allowlist_files name: cortex-xdr-remove-allowlist-files description: "Remove file hashes from the allow list." + risk: destructive inputs_schema: properties: hash_list: { type: string, description: "Comma-separated SHA-256 hashes to remove" } @@ -231,6 +241,7 @@ commands: - id: quarantine_files name: cortex-xdr-quarantine-files description: "Quarantine a file by path + hash on the given endpoints." + risk: destructive inputs_schema: properties: endpoint_id_list: { type: string, description: "Comma-separated endpoint IDs" } @@ -242,6 +253,7 @@ commands: - id: restore_file name: cortex-xdr-restore-file description: "Restore a quarantined file by hash." + risk: destructive inputs_schema: properties: file_hash: { type: string, description: "SHA-256 of the file to restore" } @@ -265,6 +277,7 @@ commands: - id: run_script name: cortex-xdr-run-script description: "Run a script (by UID) on endpoints with optional parameters." + risk: destructive inputs_schema: properties: script_uid: { type: string, description: "Script UID" } @@ -364,6 +377,7 @@ commands: - id: delete_endpoints name: cortex-xdr-delete-endpoints description: "Delete endpoints (agents) by ID." + risk: destructive inputs_schema: properties: endpoint_ids: { type: string, description: "Comma-separated endpoint IDs to delete" } @@ -372,6 +386,7 @@ commands: - id: set_endpoint_alias name: cortex-xdr-set-endpoint-alias description: "Set the alias name on endpoints." + risk: safe_write inputs_schema: properties: endpoint_ids: { type: string, description: "Comma-separated endpoint IDs" } @@ -381,6 +396,7 @@ commands: - id: abort_scan name: cortex-xdr-abort-scan description: "Abort a running malware scan on endpoints matching the filters (or all)." + risk: safe_write inputs_schema: properties: endpoint_id_list: { type: string, description: "Comma-separated endpoint IDs (omit to abort all)" } @@ -417,6 +433,7 @@ commands: - id: run_snippet_code_script name: cortex-xdr-run-snippet-code-script description: "Run an arbitrary code snippet on endpoints." + risk: destructive inputs_schema: properties: snippet_code: { type: string, description: "Code snippet to run" } @@ -436,6 +453,7 @@ commands: - id: retrieve_file name: cortex-xdr-retrieve-file description: "Retrieve files from endpoints by OS-specific path lists." + risk: safe_write inputs_schema: properties: endpoint_ids: { type: string, description: "Comma-separated endpoint IDs" } @@ -457,6 +475,7 @@ commands: - id: add_exclusion name: cortex-xdr-add-exclusion description: "Add an alert exclusion." + risk: destructive inputs_schema: properties: name: { type: string, description: "Exclusion name" } @@ -467,6 +486,7 @@ commands: - id: delete_exclusion name: cortex-xdr-delete-exclusion description: "Delete an alert exclusion by ID." + risk: destructive inputs_schema: properties: alert_exclusion_id: { type: number, description: "Exclusion ID" } @@ -484,6 +504,7 @@ commands: - id: add_tag_endpoint name: cortex-xdr-add-tag-endpoint description: "Add a tag to endpoints." + risk: safe_write inputs_schema: properties: endpoint_ids: { type: string, description: "Comma-separated endpoint IDs" } @@ -493,6 +514,7 @@ commands: - id: remove_tag_endpoint name: cortex-xdr-remove-tag-endpoint description: "Remove a tag from endpoints." + risk: safe_write inputs_schema: properties: endpoint_ids: { type: string, description: "Comma-separated endpoint IDs" } @@ -564,6 +586,7 @@ commands: - id: set_user_role name: cortex-xdr-set-user-role description: "Assign a role to users." + risk: destructive inputs_schema: properties: user_emails: { type: string, description: "Comma-separated user emails" } @@ -573,6 +596,7 @@ commands: - id: remove_user_role name: cortex-xdr-remove-user-role description: "Remove the role assignment from users." + risk: destructive inputs_schema: properties: user_emails: { type: string, description: "Comma-separated user emails" } @@ -624,6 +648,7 @@ commands: - id: create_distribution name: cortex-xdr-create-distribution description: "Create an agent installer distribution." + risk: safe_write inputs_schema: properties: name: { type: string, description: "Distribution name" } diff --git a/integrations/cuckoo/manifest.yaml b/integrations/cuckoo/manifest.yaml index cdf0413..3cbc3dd 100644 --- a/integrations/cuckoo/manifest.yaml +++ b/integrations/cuckoo/manifest.yaml @@ -1,8 +1,8 @@ id: cuckoo name: Cuckoo Sandbox -version: 1.0.0 +version: 1.1.0 description: "Cuckoo Sandbox (REST API) — dynamic malware analysis: submit files and URLs for detonation, read task status and reports, list tasks, and delete a task. Optional token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: submit file/URL, get task, get report, list tasks, delete task." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none: 2 safe_write, 1 destructive. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: submit file/URL, get task, get report, list tasks, delete task." category: enrichment # Per-instance configuration. If the Cuckoo API server requires a token it is @@ -27,6 +27,7 @@ commands: - id: submit_file name: cuckoo-submit-file description: "Submit a file (base64) for analysis." + risk: safe_write inputs_schema: properties: file_name: { type: string, description: "File name" } @@ -36,6 +37,7 @@ commands: - id: submit_url name: cuckoo-submit-url description: "Submit a URL for analysis." + risk: safe_write inputs_schema: properties: url: { type: string, description: "URL to detonate" } @@ -71,6 +73,7 @@ commands: - id: delete_task name: cuckoo-delete-task description: "Delete a task and its data." + risk: destructive inputs_schema: properties: task_id: { type: string, description: "Task ID" } diff --git a/integrations/cybelangel/manifest.yaml b/integrations/cybelangel/manifest.yaml index 6e6efbc..ab81f56 100644 --- a/integrations/cybelangel/manifest.yaml +++ b/integrations/cybelangel/manifest.yaml @@ -1,8 +1,8 @@ id: cybelangel name: CybelAngel -version: 1.0.0 +version: 1.1.0 description: "CybelAngel (External Attack Surface / data-leak detection API) — read exposure reports: list reports, get a report, and update a report's status. OAuth2 client-credentials authentication; stdlib-only, no extra Python dependencies. (French vendor.)" -changelog: "1.0.0 — Initial release: list/get reports, update report status." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list/get reports, update report status." category: threat_intel # Per-instance configuration. Client credentials are exchanged for a bearer @@ -50,6 +50,7 @@ commands: - id: update_report_status name: cybelangel-update-report-status description: "Update a report's status." + risk: safe_write inputs_schema: properties: report_id: { type: string, description: "Report ID" } diff --git a/integrations/cyberark-pas/manifest.yaml b/integrations/cyberark-pas/manifest.yaml index a08ce46..468fc5c 100644 --- a/integrations/cyberark-pas/manifest.yaml +++ b/integrations/cyberark-pas/manifest.yaml @@ -1,8 +1,8 @@ id: cyberark_pas name: CyberArk PAS -version: 1.0.0 +version: 1.1.0 description: "CyberArk Privileged Access Security (PVWA REST API) — PAM containment and IR: list and read privileged accounts, rotate/verify/reconcile credentials (CPM), retrieve a password for incident response, add/delete accounts, and list safes and vault users. Session (logon) authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get accounts, change/verify/reconcile credentials, retrieve password, add/delete account, list safes, list users." +changelog: "1.1.0 — Declare the risk tier on the 6 commands that carried none: 2 safe_write, 4 destructive. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list/get accounts, change/verify/reconcile credentials, retrieve password, add/delete account, list safes, list users." category: identity # Per-instance configuration. Each command logs on to PVWA (returns a session @@ -56,6 +56,7 @@ commands: - id: change_credentials name: cyberark-change-credentials description: "Rotate an account's credential immediately to a new random password (CPM change). Use to contain a compromised privileged account." + risk: destructive inputs_schema: properties: account_id: { type: string, description: "Account ID" } @@ -65,6 +66,7 @@ commands: - id: verify_credentials name: cyberark-verify-credentials description: "Mark an account's credential for verification by the CPM." + risk: safe_write inputs_schema: properties: account_id: { type: string, description: "Account ID" } @@ -73,6 +75,7 @@ commands: - id: reconcile_credentials name: cyberark-reconcile-credentials description: "Mark an account's credential for reconciliation by the CPM." + risk: destructive inputs_schema: properties: account_id: { type: string, description: "Account ID" } @@ -81,6 +84,7 @@ commands: - id: get_password name: cyberark-get-password description: "Retrieve an account's current password (for incident response). Requires a reason." + risk: destructive inputs_schema: properties: account_id: { type: string, description: "Account ID" } @@ -90,6 +94,7 @@ commands: - id: add_account name: cyberark-add-account description: "Add a new privileged account to a safe." + risk: safe_write inputs_schema: properties: name: { type: string, description: "Account name" } @@ -104,6 +109,7 @@ commands: - id: delete_account name: cyberark-delete-account description: "Delete an account by ID." + risk: destructive inputs_schema: properties: account_id: { type: string, description: "Account ID" } diff --git a/integrations/cybereason/manifest.yaml b/integrations/cybereason/manifest.yaml index 96eb53f..5aa152a 100644 --- a/integrations/cybereason/manifest.yaml +++ b/integrations/cybereason/manifest.yaml @@ -1,8 +1,8 @@ id: cybereason name: Cybereason -version: 1.0.0 +version: 1.1.0 description: "Cybereason EDR — endpoint containment and investigation: query Malops, list sensors, isolate/un-isolate a machine (containment), block a file hash, and read machine details. Session (login) authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: query Malops, list sensors, isolate/un-isolate machine, block file, get machine details." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: query Malops, list sensors, isolate/un-isolate machine, block file, get machine details." category: endpoint # Per-instance configuration. Each command logs in (form POST to /login.html, @@ -67,6 +67,7 @@ commands: - id: isolate_machine name: cybereason-isolate-machine description: "Isolate one or more machines from the network (containment)." + risk: destructive inputs_schema: properties: sensor_ids: { type: string, description: "Comma-separated sensor IDs to isolate" } @@ -75,6 +76,7 @@ commands: - id: unisolate_machine name: cybereason-unisolate-machine description: "Remove one or more machines from isolation." + risk: destructive inputs_schema: properties: sensor_ids: { type: string, description: "Comma-separated sensor IDs to un-isolate" } @@ -83,6 +85,7 @@ commands: - id: block_file name: cybereason-block-file description: "Block a file by hash (add to the block list)." + risk: destructive inputs_schema: properties: md5: { type: string, description: "MD5 hash of the file to block" } diff --git a/integrations/darktrace/manifest.yaml b/integrations/darktrace/manifest.yaml index ea2acc8..409dd45 100644 --- a/integrations/darktrace/manifest.yaml +++ b/integrations/darktrace/manifest.yaml @@ -1,8 +1,8 @@ id: darktrace name: Darktrace -version: 1.0.0 +version: 1.1.0 description: "Darktrace (Threat Visualizer API) — network detection and autonomous response: read model breaches, acknowledge a breach, look up devices, and read/activate Antigena network actions (containment). HMAC-SHA1 signed authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: get/acknowledge model breaches, get devices, get/activate Antigena actions." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 1 safe_write, 1 destructive. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: get/acknowledge model breaches, get devices, get/activate Antigena actions." category: ndr # Per-instance configuration. Requests are signed (HMAC-SHA1) with the public + @@ -52,6 +52,7 @@ commands: - id: acknowledge_breach name: darktrace-acknowledge-breach description: "Acknowledge a model breach." + risk: safe_write inputs_schema: properties: pbid: { type: string, description: "Policy breach ID (PBID)" } @@ -80,6 +81,7 @@ commands: - id: activate_antigena name: darktrace-activate-antigena description: "Activate an Antigena action (containment — enforce autonomous response)." + risk: destructive inputs_schema: properties: codeid: { type: string, description: "Antigena action code ID" } diff --git a/integrations/datadog/manifest.yaml b/integrations/datadog/manifest.yaml index f840b05..6e02e8d 100644 --- a/integrations/datadog/manifest.yaml +++ b/integrations/datadog/manifest.yaml @@ -1,8 +1,8 @@ id: datadog name: Datadog -version: 1.0.0 +version: 1.1.0 description: "Datadog (API v1/v2) — observability and monitoring: search logs, list and read monitors, submit and list events. API-key + Application-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: search logs, list/get monitors, submit event, list events." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: search logs, list/get monitors, submit event, list events." category: siem # Per-instance configuration. Auth uses the 'DD-API-KEY' and 'DD-APPLICATION-KEY' @@ -59,6 +59,7 @@ commands: - id: submit_event name: datadog-submit-event description: "Post an event to the Datadog event stream." + risk: safe_write inputs_schema: properties: title: { type: string, description: "Event title" } diff --git a/integrations/delinea-secret-server/manifest.yaml b/integrations/delinea-secret-server/manifest.yaml index 7e92a09..e8dfb06 100644 --- a/integrations/delinea-secret-server/manifest.yaml +++ b/integrations/delinea-secret-server/manifest.yaml @@ -1,8 +1,8 @@ id: delinea_secret_server name: Delinea Secret Server -version: 1.0.0 +version: 1.1.0 description: "Delinea Secret Server (REST API v1) — privileged-credential retrieval for IR: search secrets, read a secret, read a specific secret field, and list folders. OAuth2 password-grant authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: search secrets, get secret, get secret field, list folders." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: search secrets, get secret, get secret field, list folders." category: identity # Per-instance configuration. Credentials are exchanged for a bearer token at @@ -42,6 +42,7 @@ commands: - id: get_secret name: delinea-get-secret description: "Get a secret (with its fields) by ID." + risk: destructive inputs_schema: properties: secret_id: { type: string, description: "Secret ID" } @@ -50,6 +51,7 @@ commands: - id: get_secret_field name: delinea-get-secret-field description: "Get a single field's value from a secret (e.g. password)." + risk: destructive inputs_schema: properties: secret_id: { type: string, description: "Secret ID" } diff --git a/integrations/discord/manifest.yaml b/integrations/discord/manifest.yaml index 9bc5e56..5f0fc6e 100644 --- a/integrations/discord/manifest.yaml +++ b/integrations/discord/manifest.yaml @@ -1,8 +1,8 @@ id: discord name: Discord -version: 1.0.0 +version: 1.1.0 description: "Discord — SOC alerting and ChatOps: post messages via an incoming webhook, and (with a bot token) send channel messages, read recent channel messages, and get channel info. Webhook + bot-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: webhook message, bot channel message, list channel messages, get channel." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 2 safe_write. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: webhook message, bot channel message, list channel messages, get channel." category: notification # Per-instance configuration. webhook_url is used by the simple message command; @@ -23,6 +23,7 @@ commands: - id: send_webhook_message name: discord-send-webhook-message description: "Post a message via the configured incoming webhook." + risk: safe_write inputs_schema: properties: content: { type: string, description: "Message text" } @@ -32,6 +33,7 @@ commands: - id: send_channel_message name: discord-send-channel-message description: "Send a message to a channel using the bot token." + risk: safe_write inputs_schema: properties: channel_id: { type: string, description: "Channel ID" } diff --git a/integrations/dropbox/manifest.yaml b/integrations/dropbox/manifest.yaml index 19baf70..9f59d04 100644 --- a/integrations/dropbox/manifest.yaml +++ b/integrations/dropbox/manifest.yaml @@ -1,8 +1,8 @@ id: dropbox name: Dropbox -version: 1.0.0 +version: 1.1.0 description: "Dropbox (API v2) — evidence and file handling: search files, get file/folder metadata, list a folder, and create a shared link. Bearer-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: search, get metadata, list folder, create shared link." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: search, get metadata, list folder, create shared link." category: productivity # Per-instance configuration. Auth header 'Authorization: Bearer '. @@ -47,6 +47,7 @@ commands: - id: create_shared_link name: dropbox-create-shared-link description: "Create a shared link for a file or folder." + risk: destructive inputs_schema: properties: path: { type: string, description: "Path to share" } diff --git a/integrations/duo/manifest.yaml b/integrations/duo/manifest.yaml index a9250c3..14c6ba0 100644 --- a/integrations/duo/manifest.yaml +++ b/integrations/duo/manifest.yaml @@ -1,8 +1,8 @@ id: duo name: Cisco Duo -version: 1.0.0 +version: 1.1.0 description: "Cisco Duo (Admin API) — MFA/identity containment and investigation: list and read users, disable/enable/bypass a user (containment), delete users, read bypass codes and devices, and pull authentication logs. HMAC-SHA1 signed authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: get users/user, modify user status (disable/enable/bypass), delete user, get bypass codes, get devices, get user devices, authentication logs." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: get users/user, modify user status (disable/enable/bypass), delete user, get bypass codes, get devices, get user devices, authentication logs." category: identity # Per-instance configuration. Requests are signed (HMAC-SHA1) with the @@ -48,6 +48,7 @@ commands: - id: modify_user name: duo-modify-user description: "Change a user's status — disable (containment), enable (active), or bypass." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "Duo user ID" } @@ -57,6 +58,7 @@ commands: - id: delete_user name: duo-delete-user description: "Delete a user." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "Duo user ID" } diff --git a/integrations/efficientip/manifest.yaml b/integrations/efficientip/manifest.yaml index b0c91ff..8f605cc 100644 --- a/integrations/efficientip/manifest.yaml +++ b/integrations/efficientip/manifest.yaml @@ -1,8 +1,8 @@ id: efficientip name: EfficientIP SOLIDserver -version: 1.0.0 +version: 1.1.0 description: "EfficientIP SOLIDserver (REST API) — DNS/DDI containment and visibility: add an RPZ record to block a domain (DNS sinkhole), list DNS zones, search IP addresses, and list networks. HTTP Basic authentication; stdlib-only, no extra Python dependencies. (French vendor.)" -changelog: "1.0.0 — Initial release: add RPZ record, list DNS zones, search IP, list networks." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: add RPZ record, list DNS zones, search IP, list networks." category: network # Per-instance configuration. HTTP Basic auth against the SOLIDserver REST API. @@ -31,6 +31,7 @@ commands: - id: add_rpz_record name: efficientip-add-rpz-record description: "Add an RPZ resource record to block a domain (DNS sinkhole)." + risk: destructive inputs_schema: properties: dns_name: { type: string, description: "DNS server name that hosts the RPZ zone" } diff --git a/integrations/elasticsearch/manifest.yaml b/integrations/elasticsearch/manifest.yaml index 6cbb454..8e0aa76 100644 --- a/integrations/elasticsearch/manifest.yaml +++ b/integrations/elasticsearch/manifest.yaml @@ -1,8 +1,8 @@ id: elasticsearch name: Elasticsearch -version: 1.0.0 +version: 1.1.0 description: "Elasticsearch (REST API) — log search and enrichment for security data: run queries, count and read documents, list indices, index a document, and delete by query. API-key authentication; stdlib-only, no extra Python dependencies. Works with Elastic Security indices." -changelog: "1.0.0 — Initial release: search, count, get document, index document, list indices, delete by query." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 1 safe_write, 1 destructive. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: search, count, get document, index document, list indices, delete by query." category: siem # Per-instance configuration. Auth header 'Authorization: ApiKey '. @@ -59,6 +59,7 @@ commands: - id: index_document name: elasticsearch-index-document description: "Index (create) a document." + risk: safe_write inputs_schema: properties: index: { type: string, description: "Index name" } @@ -77,6 +78,7 @@ commands: - id: delete_by_query name: elasticsearch-delete-by-query description: "Delete documents matching a query." + risk: destructive inputs_schema: properties: index: { type: string, description: "Index name" } diff --git a/integrations/emailrep/manifest.yaml b/integrations/emailrep/manifest.yaml index f15d25e..5977847 100644 --- a/integrations/emailrep/manifest.yaml +++ b/integrations/emailrep/manifest.yaml @@ -1,8 +1,8 @@ id: emailrep name: EmailRep -version: 1.0.0 +version: 1.1.0 description: "EmailRep.io (API) — reputation and risk profile of an email address (deliverability, first/last seen, malicious activity, breaches, profiles), plus reporting an address as malicious. API-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: email reputation lookup and malicious-address reporting." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: email reputation lookup and malicious-address reporting." category: enrichment config_schema: @@ -27,6 +27,7 @@ commands: - id: report name: emailrep-report description: "Report an email address as malicious to EmailRep.io." + risk: destructive inputs_schema: properties: email: { type: string, description: "Email address to report" } diff --git a/integrations/f5-bigip/manifest.yaml b/integrations/f5-bigip/manifest.yaml index 6965ee6..9698642 100644 --- a/integrations/f5-bigip/manifest.yaml +++ b/integrations/f5-bigip/manifest.yaml @@ -1,8 +1,8 @@ id: f5_bigip name: F5 BIG-IP -version: 1.0.0 +version: 1.1.0 description: "F5 BIG-IP (iControl REST) — application-delivery visibility and containment: list virtual servers and pools, read pool members, disable a pool member, and add an IP to an internal data-group (block list). HTTP Basic authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list virtual servers/pools, get pool members, disable pool member, add data-group record." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list virtual servers/pools, get pool members, disable pool member, add data-group record." category: network # Per-instance configuration. HTTP Basic auth against the iControl REST API. @@ -56,6 +56,7 @@ commands: - id: disable_pool_member name: f5-disable-pool-member description: "Disable a pool member (drains it — containment)." + risk: destructive inputs_schema: properties: pool_name: { type: string, description: "Pool name (partition path)" } @@ -65,6 +66,7 @@ commands: - id: add_datagroup_record name: f5-add-datagroup-record description: "Add a record (e.g. an IP) to an internal data-group used by a block iRule." + risk: destructive inputs_schema: properties: datagroup_name: { type: string, description: "Internal data-group name (partition path)" } diff --git a/integrations/forcepoint-dlp/manifest.yaml b/integrations/forcepoint-dlp/manifest.yaml index a311a73..cee87f2 100644 --- a/integrations/forcepoint-dlp/manifest.yaml +++ b/integrations/forcepoint-dlp/manifest.yaml @@ -1,8 +1,8 @@ id: forcepoint_dlp name: Forcepoint DLP -version: 1.0.0 +version: 1.1.0 description: "Forcepoint DLP (Security Manager REST API v1) — data-loss-prevention incident handling: list incidents in a time window, read an incident, and update incident status/severity/assignment. Token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list incidents, get incident, update incident." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list incidents, get incident, update incident." category: dlp # Per-instance configuration. Credentials are exchanged for an access token @@ -52,6 +52,7 @@ commands: - id: update_incident name: forcepoint-update-incident description: "Update DLP incidents (status, severity, or assignee)." + risk: safe_write inputs_schema: properties: incident_ids: { type: string, description: "Comma-separated incident IDs" } diff --git a/integrations/fortigate/manifest.yaml b/integrations/fortigate/manifest.yaml index 470c05f..840ffc2 100644 --- a/integrations/fortigate/manifest.yaml +++ b/integrations/fortigate/manifest.yaml @@ -1,8 +1,8 @@ id: fortigate name: FortiGate -version: 1.0.0 +version: 1.1.0 description: "Fortinet FortiGate (FortiOS REST API v2) — network containment: ban/unban IP addresses (quarantine), manage firewall address objects and address groups, and read firewall policies and services. API-token authentication; stdlib-only, no extra Python dependencies. Supports multi-VDOM." -changelog: "1.0.0 — Initial release: ban/unban/list banned IPs, address object create/delete/list, address-group update/list, firewall policy and service listing." +changelog: "1.1.0 — Declare the risk tier on the 5 commands that carried none: 1 safe_write, 4 destructive. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: ban/unban/list banned IPs, address object create/delete/list, address-group update/list, firewall policy and service listing." category: network # Per-instance configuration. The API token is sent as 'Authorization: Bearer '. @@ -31,6 +31,7 @@ commands: - id: ban_ip name: fortigate-ban-ip description: "Quarantine one or more source IP addresses (adds them to the FortiGate banned-IP list)." + risk: destructive inputs_schema: properties: ip_addresses: { type: string, description: "Comma-separated IPv4/IPv6 addresses to ban" } @@ -41,6 +42,7 @@ commands: - id: unban_ip name: fortigate-unban-ip description: "Remove one or more IP addresses from the FortiGate banned-IP list." + risk: destructive inputs_schema: properties: ip_addresses: { type: string, description: "Comma-separated addresses to unban (empty = clear all)" } @@ -59,6 +61,7 @@ commands: - id: create_address name: fortigate-create-firewall-address description: "Create a firewall address object (subnet type)." + risk: safe_write inputs_schema: properties: name: { type: string, description: "Address object name" } @@ -70,6 +73,7 @@ commands: - id: delete_address name: fortigate-delete-firewall-address description: "Delete a firewall address object by name." + risk: destructive inputs_schema: properties: name: { type: string, description: "Address object name" } @@ -89,6 +93,7 @@ commands: - id: update_address_group name: fortigate-update-firewall-address-group description: "Replace the members of a firewall address group (e.g. a blocked-hosts group referenced by a deny policy)." + risk: destructive inputs_schema: properties: name: { type: string, description: "Address group name" } diff --git a/integrations/freshservice/manifest.yaml b/integrations/freshservice/manifest.yaml index 2ce5157..f419938 100644 --- a/integrations/freshservice/manifest.yaml +++ b/integrations/freshservice/manifest.yaml @@ -1,8 +1,8 @@ id: freshservice name: Freshservice -version: 1.0.0 +version: 1.1.0 description: "Freshservice (REST API v2) — IT service management: create, read, update and list tickets, add notes (public or private), and list agents. API-key (Basic) authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: create/get/update/list tickets, add note, list agents." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none: 3 safe_write. An unset risk is read as destructive by the agent approval gate, so the 3 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: create/get/update/list tickets, add note, list agents." category: ticketing # Per-instance configuration. Auth is HTTP Basic with ':X'. @@ -23,6 +23,7 @@ commands: - id: create_ticket name: freshservice-create-ticket description: "Create a ticket." + risk: safe_write inputs_schema: properties: subject: { type: string, description: "Ticket subject" } @@ -45,6 +46,7 @@ commands: - id: update_ticket name: freshservice-update-ticket description: "Update a ticket (status, priority, or assignment)." + risk: safe_write inputs_schema: properties: ticket_id: { type: string, description: "Ticket ID" } @@ -66,6 +68,7 @@ commands: - id: add_note name: freshservice-add-note description: "Add a note to a ticket (public or private)." + risk: safe_write inputs_schema: properties: ticket_id: { type: string, description: "Ticket ID" } diff --git a/integrations/gcp-security/manifest.yaml b/integrations/gcp-security/manifest.yaml index 702c032..64e7956 100644 --- a/integrations/gcp-security/manifest.yaml +++ b/integrations/gcp-security/manifest.yaml @@ -1,8 +1,8 @@ id: gcp_security name: Google Cloud -version: 1.0.0 +version: 1.1.0 description: "Google Cloud Platform (Compute Engine + Security Command Center) — cloud containment: list/create/delete VPC firewall rules (deny to isolate), list and stop Compute Engine instances, and list Security Command Center findings. Authenticates with a Google service account (RS256 JWT bearer flow). Runs on a remote engine. Requires the Python 'PyJWT' and 'cryptography' libraries on the engine host (pip install pyjwt cryptography)." -changelog: "1.0.0 — Initial release: list/create/delete firewall rules, list/stop instances, list Security Command Center findings." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list/create/delete firewall rules, list/stop instances, list Security Command Center findings." category: cloud # Per-instance configuration. The scripts build a signed RS256 assertion from the @@ -37,6 +37,7 @@ commands: - id: create_firewall name: gcp-create-firewall description: "Create a VPC firewall rule (e.g. a deny rule to isolate targets)." + risk: destructive inputs_schema: properties: name: { type: string, description: "Firewall rule name" } @@ -53,6 +54,7 @@ commands: - id: delete_firewall name: gcp-delete-firewall description: "Delete a VPC firewall rule by name." + risk: destructive inputs_schema: properties: name: { type: string, description: "Firewall rule name" } @@ -70,6 +72,7 @@ commands: - id: stop_instance name: gcp-stop-instance description: "Stop a Compute Engine instance (containment)." + risk: destructive inputs_schema: properties: zone: { type: string, description: "Zone of the instance" } diff --git a/integrations/github/manifest.yaml b/integrations/github/manifest.yaml index 6e0d44e..73ceb8d 100644 --- a/integrations/github/manifest.yaml +++ b/integrations/github/manifest.yaml @@ -1,8 +1,8 @@ id: github name: GitHub -version: 1.0.0 +version: 1.1.0 description: "GitHub (REST API) — code security and issue tracking: list secret-scanning, code-scanning and Dependabot alerts for a repository, read a repository, and create an issue. Personal-access-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list secret/code/Dependabot alerts, get repo, create issue." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list secret/code/Dependabot alerts, get repo, create issue." category: devsecops # Per-instance configuration. Auth header 'Authorization: Bearer '. @@ -62,6 +62,7 @@ commands: - id: create_issue name: github-create-issue description: "Create an issue in a repository." + risk: safe_write inputs_schema: properties: owner: { type: string, description: "Repository owner" } diff --git a/integrations/gitlab/manifest.yaml b/integrations/gitlab/manifest.yaml index 7f3d807..26c5341 100644 --- a/integrations/gitlab/manifest.yaml +++ b/integrations/gitlab/manifest.yaml @@ -1,8 +1,8 @@ id: gitlab name: GitLab -version: 1.0.0 +version: 1.1.0 description: "GitLab (API v4) — project security and issue tracking: list project vulnerabilities, list and create issues, read a project, and list audit events. Private-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list vulnerabilities, list/create issues, get project, list audit events." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list vulnerabilities, list/create issues, get project, list audit events." category: devsecops # Per-instance configuration. Auth header 'PRIVATE-TOKEN: '. @@ -42,6 +42,7 @@ commands: - id: create_issue name: gitlab-create-issue description: "Create an issue in a project." + risk: safe_write inputs_schema: properties: project_id: { type: string, description: "Project ID or path" } diff --git a/integrations/glimps/manifest.yaml b/integrations/glimps/manifest.yaml index 8f6d237..967db60 100644 --- a/integrations/glimps/manifest.yaml +++ b/integrations/glimps/manifest.yaml @@ -1,8 +1,8 @@ id: glimps name: GLIMPS Detect -version: 1.0.0 +version: 1.1.0 description: "GLIMPS Detect (GDetect API lite v2) — deep malware analysis: submit a file for analysis, poll the result by UUID, and look up a file by SHA-256. Token authentication; stdlib-only, no extra Python dependencies. (French vendor.)" -changelog: "1.0.0 — Initial release: submit file, get result, search by hash." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: submit file, get result, search by hash." category: enrichment # Per-instance configuration. Auth header 'X-Auth-Token: '. @@ -23,6 +23,7 @@ commands: - id: submit_file name: glimps-submit-file description: "Submit a file (base64) for analysis. Returns an analysis UUID." + risk: safe_write inputs_schema: properties: file_name: { type: string, description: "File name" } diff --git a/integrations/gmail-single-user/manifest.yaml b/integrations/gmail-single-user/manifest.yaml index fe27822..f31736c 100644 --- a/integrations/gmail-single-user/manifest.yaml +++ b/integrations/gmail-single-user/manifest.yaml @@ -1,8 +1,8 @@ id: gmail_single_user name: Gmail Single User -version: 1.0.0 +version: 1.1.0 description: "Gmail for a single mailbox over OAuth 2.0 (no service account, no domain-wide delegation) — search/read messages, send and reply (with attachments), retrieve attachments, and ingest messages (get_incidents) with an OCSF mapper. Uses a per-mailbox OAuth refresh token; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: OAuth authorization link + code exchange, connectivity test, message ingestion with OCSF mapper, send/reply mail with attachments, and attachment retrieval." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none: 2 safe_write, 1 destructive. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: OAuth authorization link + code exchange, connectivity test, message ingestion with OCSF mapper, send/reply mail with attachments, and attachment retrieval." category: email # Per-instance configuration. This integration authenticates as ONE Gmail user @@ -55,6 +55,7 @@ commands: - id: exchange_code name: gmail-single-user-exchange-code description: "Exchange an OAuth authorization code for a refresh token (paste the refresh_token into the instance config afterwards)." + risk: destructive inputs_schema: properties: code: { type: string, description: "Authorization code from the consent redirect" } @@ -112,6 +113,7 @@ commands: - id: send_mail name: gmail-single-user-send-mail description: "Send an email from the mailbox (optional single attachment as base64)." + risk: safe_write inputs_schema: properties: to: { type: string, description: "Recipient(s), comma-separated" } @@ -128,6 +130,7 @@ commands: - id: reply_mail name: gmail-single-user-reply-mail description: "Reply to a message (sets In-Reply-To/References so it threads correctly)." + risk: safe_write inputs_schema: properties: to: { type: string, description: "Recipient(s), comma-separated" } diff --git a/integrations/gmail/manifest.yaml b/integrations/gmail/manifest.yaml index 923790a..e7ecf69 100644 --- a/integrations/gmail/manifest.yaml +++ b/integrations/gmail/manifest.yaml @@ -1,8 +1,8 @@ id: gmail name: Gmail -version: 1.0.0 +version: 1.1.0 description: "Gmail API + Directory API — mailbox search/read/send/trash/labels, attachments retrieval, vacation auto-reply, filters, forwarding addresses, delegates, and Workspace user administration; message ingestion (get_incidents) with an OCSF mapper; service-account auth with domain-wide delegation. Runs on a remote engine. Requires the Python 'PyJWT' and 'cryptography' libraries on the engine host (pip install pyjwt cryptography)." -changelog: "1.0.0 — Initial release: mailbox commands (search, get mail/thread, send with attachments, trash/permanent delete, label moves, attachments download, labels list), vacation auto-reply get/set, mail filters (add/list/remove), forwarding addresses and auto-forwarding, delegates, Workspace user administration (list/get/create/delete, password reset, directory visibility), and message ingestion with a bundled OCSF mapper." +changelog: "1.1.0 — Declare the risk tier on the 15 commands that carried none: 4 safe_write, 11 destructive. An unset risk is read as destructive by the agent approval gate, so the 4 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: mailbox commands (search, get mail/thread, send with attachments, trash/permanent delete, label moves, attachments download, labels list), vacation auto-reply get/set, mail filters (add/list/remove), forwarding addresses and auto-forwarding, delegates, Workspace user administration (list/get/create/delete, password reset, directory visibility), and message ingestion with a bundled OCSF mapper." category: email # Authentication: Google service account with domain-wide delegation. @@ -84,6 +84,7 @@ commands: - id: send_mail name: gmail-send-mail description: "Send an email from the impersonated mailbox — plain text and/or HTML body, optional single attachment (base64), reply threading via In-Reply-To/References." + risk: safe_write inputs_schema: properties: to: { type: string, description: "Recipients, comma-separated" } @@ -103,6 +104,7 @@ commands: - id: delete_mail name: gmail-delete-mail description: "Move a message to Trash, or delete it permanently (bypasses Trash) when permanent is true." + risk: destructive inputs_schema: properties: message_id: { type: string, description: "Gmail message ID" } @@ -113,6 +115,7 @@ commands: - id: move_mail name: gmail-move-mail description: "Add and/or remove labels on a message (move between folders — e.g. remove INBOX, add SPAM or a quarantine label)." + risk: safe_write inputs_schema: properties: message_id: { type: string, description: "Gmail message ID" } @@ -154,6 +157,7 @@ commands: - id: autoreply_set name: gmail-autoreply-set description: "Enable, update or disable the mailbox's vacation auto-reply." + risk: safe_write inputs_schema: properties: enable: { type: boolean, description: "Enable the auto-reply (default true; false disables it)" } @@ -172,6 +176,7 @@ commands: - id: add_filter name: gmail-add-filter description: "Create a mail filter on the mailbox (criteria: from/to/subject/query/has_attachment; actions: add/remove labels, forward)." + risk: destructive inputs_schema: properties: from: { type: string, description: "Criteria — sender address" } @@ -197,6 +202,7 @@ commands: - id: remove_filter name: gmail-remove-filter description: "Delete a mail filter by ID." + risk: destructive inputs_schema: properties: filter_id: { type: string, description: "Filter ID (from gmail-list-filters)" } @@ -208,6 +214,7 @@ commands: - id: forwarding_add name: gmail-forwarding-add description: "Register a forwarding address on the mailbox (Google may require verification before it becomes usable)." + risk: destructive inputs_schema: properties: forwarding_email: { type: string, description: "Forwarding address to register" } @@ -226,6 +233,7 @@ commands: - id: forwarding_remove name: gmail-forwarding-remove description: "Delete a forwarding address from the mailbox." + risk: destructive inputs_schema: properties: forwarding_email: { type: string, description: "Forwarding address to remove" } @@ -235,6 +243,7 @@ commands: - id: forwarding_update name: gmail-forwarding-update description: "Enable auto-forwarding of the mailbox to a verified forwarding address, with a disposition for the forwarded copy." + risk: destructive inputs_schema: properties: forwarding_email: { type: string, description: "Verified forwarding address to auto-forward to" } @@ -247,6 +256,7 @@ commands: - id: delegate_add name: gmail-delegate-add description: "Grant a delegate access to the mailbox (delegate can read, send and delete on the owner's behalf)." + risk: destructive inputs_schema: properties: delegate_email: { type: string, description: "Delegate's email address (same Workspace domain)" } @@ -256,6 +266,7 @@ commands: - id: delegate_remove name: gmail-delegate-remove description: "Revoke a delegate's access to the mailbox." + risk: destructive inputs_schema: properties: delegate_email: { type: string, description: "Delegate's email address to revoke" } @@ -289,6 +300,7 @@ commands: - id: create_user name: gmail-create-user description: "Create a Workspace user (Directory API)." + risk: destructive inputs_schema: properties: email: { type: string, description: "New user's primary email address" } @@ -300,6 +312,7 @@ commands: - id: delete_user name: gmail-delete-user description: "Delete a Workspace user (Directory API)." + risk: destructive inputs_schema: properties: user_key: { type: string, description: "User's primary email, alias email or unique ID" } @@ -308,6 +321,7 @@ commands: - id: set_password name: gmail-set-password description: "Reset a Workspace user's password (Directory API) — a common containment step for a compromised account." + risk: destructive inputs_schema: properties: user_key: { type: string, description: "User's primary email, alias email or unique ID" } @@ -317,6 +331,7 @@ commands: - id: hide_user name: gmail-hide-user description: "Set a Workspace user's global directory visibility (Directory API)." + risk: safe_write inputs_schema: properties: user_key: { type: string, description: "User's primary email, alias email or unique ID" } diff --git a/integrations/google-calendar/manifest.yaml b/integrations/google-calendar/manifest.yaml index e144106..1b257b3 100644 --- a/integrations/google-calendar/manifest.yaml +++ b/integrations/google-calendar/manifest.yaml @@ -1,8 +1,8 @@ id: google_calendar name: Google Calendar -version: 1.0.0 +version: 1.1.0 description: "Google Calendar (Calendar API v3) — manage calendar access control lists: grant a role on a calendar to a user, group, domain or the public, and list the existing ACL rules. Service-account authentication with domain-wide delegation. Runs on a remote engine. Requires the Python 'PyJWT' and 'cryptography' libraries on the engine host (pip install pyjwt cryptography)." -changelog: "1.0.0 — Initial release: ACL rule creation and listing on user calendars." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: ACL rule creation and listing on user calendars." category: productivity # Per-instance configuration. Create a Google Cloud service account with @@ -27,6 +27,7 @@ commands: - id: acl_add name: google-calendar-acl-add description: "Create an access control rule on a calendar (grant a role to a user, group, domain or the public)." + risk: destructive inputs_schema: properties: calendar_id: { type: string, description: "Calendar identifier — use 'primary' for the impersonated user's main calendar" } diff --git a/integrations/google-drive/manifest.yaml b/integrations/google-drive/manifest.yaml index 989ef3d..066ce81 100644 --- a/integrations/google-drive/manifest.yaml +++ b/integrations/google-drive/manifest.yaml @@ -1,8 +1,8 @@ id: google_drive name: Google Drive -version: 1.0.0 +version: 1.1.0 description: "Google Drive (Drive API v3) — manage shared drives (create/list/get/delete), track file changes (start page token + change lists), query Drive activity, search and read files, create folders and metadata, upload/replace/download file content, copy, move and delete files, manage permissions (list/create/update/delete) and work with Drive labels. Authenticates with a Google service account (JWT bearer flow with domain-wide delegation to impersonate a Workspace user). Runs on a remote engine. Requires the Python 'PyJWT' and 'cryptography' libraries on the engine host (pip install pyjwt cryptography)." -changelog: "1.0.0 — Initial release: shared drive management, changes tracking, Drive activity queries, file search/get/create, content upload/replace/download, copy/move/delete, parents, permissions management, Drive labels, test connection." +changelog: "1.1.0 — Declare the risk tier on the 12 commands that carried none: 6 safe_write, 6 destructive. An unset risk is read as destructive by the agent approval gate, so the 6 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: shared drive management, changes tracking, Drive activity queries, file search/get/create, content upload/replace/download, copy/move/delete, parents, permissions management, Drive labels, test connection." category: productivity # Per-instance configuration. Authentication uses the Google service-account @@ -29,6 +29,7 @@ commands: - id: drive_create name: google-drive-drive-create description: "Create a new shared drive." + risk: safe_write inputs_schema: properties: name: { type: string, description: "Name of the shared drive to create" } @@ -63,6 +64,7 @@ commands: - id: drive_delete name: google-drive-drive-delete description: "Permanently delete a shared drive." + risk: destructive inputs_schema: properties: drive_id: { type: string, description: "ID of the shared drive to delete" } @@ -141,6 +143,7 @@ commands: - id: file_create name: google-drive-file-create description: "Create a folder or an empty file (metadata only — use file-upload for content)." + risk: safe_write inputs_schema: properties: file_name: { type: string, description: "Name of the file or folder to create" } @@ -153,6 +156,7 @@ commands: - id: file_upload name: google-drive-file-upload description: "Upload a new file with content (base64-encoded)." + risk: safe_write inputs_schema: properties: file_name: { type: string, description: "Name of the file to create" } @@ -164,6 +168,7 @@ commands: - id: file_replace name: google-drive-file-replace description: "Replace an existing file's content (base64-encoded)." + risk: destructive inputs_schema: properties: file_id: { type: string, description: "ID of the file to update" } @@ -184,6 +189,7 @@ commands: - id: file_copy name: google-drive-file-copy description: "Copy a file, optionally with a new title." + risk: safe_write inputs_schema: properties: file_id: { type: string, description: "ID of the file to copy" } @@ -194,6 +200,7 @@ commands: - id: file_move name: google-drive-file-move description: "Move a file between folders (add one parent, remove another)." + risk: safe_write inputs_schema: properties: file_id: { type: string, description: "ID of the file to move" } @@ -205,6 +212,7 @@ commands: - id: file_delete name: google-drive-file-delete description: "Delete a file — permanently, or move it to the trash with soft_delete." + risk: destructive inputs_schema: properties: file_id: { type: string, description: "ID of the file to delete" } @@ -238,6 +246,7 @@ commands: - id: permission_create name: google-drive-permission-create description: "Grant a permission on a file or shared drive (share with a user, group, domain or anyone)." + risk: destructive inputs_schema: properties: file_id: { type: string, description: "ID of the file or shared drive" } @@ -254,6 +263,7 @@ commands: - id: permission_update name: google-drive-permission-update description: "Update a permission's role or expiration time." + risk: destructive inputs_schema: properties: file_id: { type: string, description: "ID of the file or shared drive" } @@ -266,6 +276,7 @@ commands: - id: permission_delete name: google-drive-permission-delete description: "Revoke a permission from a file or shared drive." + risk: destructive inputs_schema: properties: file_id: { type: string, description: "ID of the file or shared drive" } @@ -295,6 +306,7 @@ commands: - id: modify_label name: google-drive-modify-label description: "Apply, update or remove a Drive label on a file." + risk: safe_write inputs_schema: properties: file_id: { type: string, description: "ID of the file" } diff --git a/integrations/harfanglab/manifest.yaml b/integrations/harfanglab/manifest.yaml index 17e54dd..3c41012 100644 --- a/integrations/harfanglab/manifest.yaml +++ b/integrations/harfanglab/manifest.yaml @@ -1,8 +1,8 @@ id: harfanglab name: HarfangLab EDR -version: 1.4.1 +version: 1.5.0 description: "HarfangLab EDR — endpoint detection & response: alert/threat ingestion, endpoint enrichment, isolation, threat-intelligence (IOC/whitelist), telemetry hunting and forensic collection jobs." -changelog: "1.4.1 — get_alerts now maps image_name, the one process path present on every alert subtype and the only one on those carrying neither a process object nor an event log (yara, binary, ioc). HarfangLab prefixes it with the matched threat name in brackets, so both halves are split out: the clean path feeds actor.process.file.path and its basename actor.process.name, and the threat name feeds malware.name — which now surfaces on every subtype rather than only on Defender event-log detections. Each half is guarded on the bracket being present so an unprefixed path is never written into malware.name. 1.4.0 — Mapper coverage from real payloads: get_alerts now maps the Windows event-log payload sigma alerts carry (alert_subtype = eventlog), which was entirely unmapped — Defender 1116/1117 yields the malware name, classification, severity and provider, the detected file, the process that touched it and the acting user, plus the log provider and event code. Also added the agent IP, DNS domain, device type, agent version and groups, the tenant, the alert subtype and threat type, the string severity and the event time. get_threats gained the threat level (previously never reaching the OCSF document at all), the event time and the top agent's reachability. 1.3.1 — Flagged get_alerts as ingestion-ready (ingest hints: results_path/dedup/incremental on from_date) so it appears in the recommended ingestion commands when creating an instance. 1.3.0 — Response & triage expansion: kill/dump process, on-demand AV/YARA scans, file/service/scheduled-task deletion, quarantine management, threat-level isolation, job cancel/relaunch/wait; alert search (get_alerts) and full alert/threat triage (tag, comments, notes, status, level, history, details); exhaustive alert OCSF mappers; reworked get_threats mapper (fixed MITRE tactics map handling, full top-agent/user/rule and counts coverage, rule-based incident title/description). 1.2.2 — Documentation wording cleanup. 1.2.1 — Corrected the get_threats OCSF mapper to native threat fields (top_agents/top_impacted_users/top_rules/mitre_tactics) instead of enriched-only arrays; added agent.osversion to get_security_events. 1.2.0 — Added ingestion commands get_security_events (alerts) and get_threats with bundled OCSF mappers and ingest hints (results_path/dedup/incremental). 1.1.1 — Added test_connection for the instance Test button. 1.1.0 — Command names prefixed with 'harfanglab-' (e.g. harfanglab-isolate-endpoint) for easier toolbox search; command IDs unchanged. 1.0.0 — Initial release: endpoint/agent management, isolation, policy assignment, IOC & whitelist management, security-event triage, telemetry hunting (processes, network, DNS, authentications, binaries, event logs), threat hunting by hash, and forensic collection jobs (pipes, prefetch, run keys, scheduled tasks, drivers, services, processes, network, sessions, WMI, IOC scan, artifacts, RAM dump) with their result retrieval commands. Compatible with HarfangLab EDR 2.13.7+." +changelog: "1.5.0 — Declare the risk tier on the 71 commands that carried none: 39 read, 24 safe_write, 8 destructive. An unset risk is read as destructive by the agent approval gate, so the 63 that only read or only annotate sat behind the same prompt as the ones that change the estate. deisolate_from_threat and unquarantine_file move from safe_write to destructive in the same pass: undoing a containment mid-incident is its own decision, and is tiered like the containment it lifts. | 1.4.1 — get_alerts now maps image_name, the one process path present on every alert subtype and the only one on those carrying neither a process object nor an event log (yara, binary, ioc). HarfangLab prefixes it with the matched threat name in brackets, so both halves are split out: the clean path feeds actor.process.file.path and its basename actor.process.name, and the threat name feeds malware.name — which now surfaces on every subtype rather than only on Defender event-log detections. Each half is guarded on the bracket being present so an unprefixed path is never written into malware.name. 1.4.0 — Mapper coverage from real payloads: get_alerts now maps the Windows event-log payload sigma alerts carry (alert_subtype = eventlog), which was entirely unmapped — Defender 1116/1117 yields the malware name, classification, severity and provider, the detected file, the process that touched it and the acting user, plus the log provider and event code. Also added the agent IP, DNS domain, device type, agent version and groups, the tenant, the alert subtype and threat type, the string severity and the event time. get_threats gained the threat level (previously never reaching the OCSF document at all), the event time and the top agent's reachability. 1.3.1 — Flagged get_alerts as ingestion-ready (ingest hints: results_path/dedup/incremental on from_date) so it appears in the recommended ingestion commands when creating an instance. 1.3.0 — Response & triage expansion: kill/dump process, on-demand AV/YARA scans, file/service/scheduled-task deletion, quarantine management, threat-level isolation, job cancel/relaunch/wait; alert search (get_alerts) and full alert/threat triage (tag, comments, notes, status, level, history, details); exhaustive alert OCSF mappers; reworked get_threats mapper (fixed MITRE tactics map handling, full top-agent/user/rule and counts coverage, rule-based incident title/description). 1.2.2 — Documentation wording cleanup. 1.2.1 — Corrected the get_threats OCSF mapper to native threat fields (top_agents/top_impacted_users/top_rules/mitre_tactics) instead of enriched-only arrays; added agent.osversion to get_security_events. 1.2.0 — Added ingestion commands get_security_events (alerts) and get_threats with bundled OCSF mappers and ingest hints (results_path/dedup/incremental). 1.1.1 — Added test_connection for the instance Test button. 1.1.0 — Command names prefixed with 'harfanglab-' (e.g. harfanglab-isolate-endpoint) for easier toolbox search; command IDs unchanged. 1.0.0 — Initial release: endpoint/agent management, isolation, policy assignment, IOC & whitelist management, security-event triage, telemetry hunting (processes, network, DNS, authentications, binaries, event logs), threat hunting by hash, and forensic collection jobs (pipes, prefetch, run keys, scheduled tasks, drivers, services, processes, network, sessions, WMI, IOC scan, artifacts, RAM dump) with their result retrieval commands. Compatible with HarfangLab EDR 2.13.7+." category: endpoint # Per-instance configuration. Scripts use as the API base and call /api/... paths. @@ -68,6 +68,7 @@ commands: - id: get_endpoint_info name: harfanglab-get-endpoint-info description: Get endpoint (agent) information by agent ID. + risk: read inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -76,6 +77,7 @@ commands: - id: endpoint_search name: harfanglab-endpoint-search description: Search endpoints (agents) by hostname. + risk: read inputs_schema: properties: hostname: { type: string, description: "Hostname to filter agents by" } @@ -84,6 +86,7 @@ commands: - id: isolate_endpoint name: harfanglab-isolate-endpoint description: Network-isolate an endpoint (agent) by agent ID. + risk: destructive inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -92,6 +95,7 @@ commands: - id: deisolate_endpoint name: harfanglab-deisolate-endpoint description: Remove network isolation from an endpoint (agent) by agent ID. + risk: destructive inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -100,6 +104,7 @@ commands: - id: assign_policy_to_agent name: harfanglab-assign-policy-to-agent description: Assign a security policy to an agent by policy name and agent ID. + risk: destructive inputs_schema: properties: policy: { type: string, description: "Name of the policy to assign" } @@ -111,6 +116,7 @@ commands: - id: whitelist_search name: harfanglab-whitelist-search description: Search threat-intelligence whitelists by keyword. + risk: read inputs_schema: properties: keyword: { type: string, description: "Keyword to search" } @@ -120,6 +126,7 @@ commands: - id: whitelist_add name: harfanglab-whitelist-add description: Create a threat-intelligence whitelist rule with an initial criterion. + risk: destructive inputs_schema: properties: comment: { type: string, description: "Whitelist comment" } @@ -134,6 +141,7 @@ commands: - id: whitelist_add_criterion name: harfanglab-whitelist-add-criterion description: Append a criterion to an existing whitelist rule. + risk: destructive inputs_schema: properties: id: { type: string, description: "Whitelist rule id" } @@ -146,6 +154,7 @@ commands: - id: whitelist_delete name: harfanglab-whitelist-delete description: Delete a threat-intelligence whitelist rule by id. + risk: destructive inputs_schema: properties: id: { type: string, description: "Whitelist rule id" } @@ -156,6 +165,7 @@ commands: - id: add_ioc_to_source name: harfanglab-add-ioc-to-source description: Add an IOC to a named IOC source if it does not already exist. + risk: safe_write inputs_schema: properties: ioc_value: { type: string, description: "IOC value" } @@ -168,6 +178,7 @@ commands: - id: delete_ioc_from_source name: harfanglab-delete-ioc-from-source description: Remove an IOC from a named IOC source if it exists. + risk: destructive inputs_schema: properties: ioc_value: { type: string, description: "IOC value" } @@ -179,6 +190,7 @@ commands: - id: change_security_event_status name: harfanglab-change-security-event-status description: "Change the status of a security event (New, Investigating, False Positive, Closed)." + risk: safe_write inputs_schema: properties: security_event_id: { type: string, description: "Security event ID" } @@ -190,6 +202,7 @@ commands: - id: api_call name: harfanglab-api-call description: "Perform a generic authenticated call to the HarfangLab API." + risk: destructive inputs_schema: properties: api_method: { type: string, description: "HTTP method (GET, POST, PUT, DELETE, PATCH)" } @@ -201,6 +214,7 @@ commands: - id: telemetry_process_graph name: harfanglab-telemetry-process-graph description: "Retrieve the process graph for a telemetry process UUID." + risk: read inputs_schema: properties: process_uuid: { type: string, description: "Telemetry process UUID" } @@ -211,6 +225,7 @@ commands: - id: hunt_search_hash name: harfanglab-hunt-search-hash description: "Search the data explorer for a file hash." + risk: read inputs_schema: properties: hash: { type: string, description: "File hash to search for" } @@ -219,6 +234,7 @@ commands: - id: hunt_search_running_process_hash name: harfanglab-hunt-search-running-process-hash description: "Hunt for currently running processes matching a SHA-256 hash." + risk: read inputs_schema: properties: hash: { type: string, description: "SHA-256 hash to search for" } @@ -227,6 +243,7 @@ commands: - id: hunt_search_runned_process_hash name: harfanglab-hunt-search-runned-process-hash description: "Search process telemetry for executions matching a SHA-256 hash." + risk: read inputs_schema: properties: hash: { type: string, description: "SHA-256 hash to search for" } @@ -237,6 +254,7 @@ commands: - id: telemetry_processes name: harfanglab-telemetry-processes description: Search process telemetry. + risk: read inputs_schema: properties: hash: { type: string, description: "File hash (md5, sha1 or sha256)" } @@ -249,6 +267,7 @@ commands: - id: telemetry_dns name: harfanglab-telemetry-dns description: Search DNS resolution telemetry. + risk: read inputs_schema: properties: hostname: { type: string, description: "Endpoint hostname" } @@ -262,6 +281,7 @@ commands: - id: telemetry_network name: harfanglab-telemetry-network description: Search network connection telemetry. + risk: read inputs_schema: properties: hostname: { type: string, description: "Endpoint hostname" } @@ -277,6 +297,7 @@ commands: - id: telemetry_eventlog name: harfanglab-telemetry-eventlog description: Search Windows full event log telemetry. + risk: read inputs_schema: properties: hostname: { type: string, description: "Endpoint hostname" } @@ -289,6 +310,7 @@ commands: - id: telemetry_binary name: harfanglab-telemetry-binary description: Search binary telemetry. + risk: read inputs_schema: properties: hash: { type: string, description: "File hash (md5, sha1 or sha256)" } @@ -300,6 +322,7 @@ commands: - id: telemetry_authentication_windows name: harfanglab-telemetry-authentication-windows description: Search Windows authentication telemetry. + risk: read inputs_schema: properties: hostname: { type: string, description: "Endpoint hostname" } @@ -317,6 +340,7 @@ commands: - id: telemetry_authentication_linux name: harfanglab-telemetry-authentication-linux description: Search Linux authentication telemetry. + risk: read inputs_schema: properties: hostname: { type: string, description: "Endpoint hostname" } @@ -332,6 +356,7 @@ commands: - id: telemetry_authentication_macos name: harfanglab-telemetry-authentication-macos description: Search macOS authentication telemetry. + risk: read inputs_schema: properties: hostname: { type: string, description: "Endpoint hostname" } @@ -347,6 +372,7 @@ commands: - id: telemetry_authentication_users name: harfanglab-telemetry-authentication-users description: Rank users by authentication attempts across Windows, Linux and macOS. + risk: read inputs_schema: properties: hostname: { type: string, description: "Endpoint hostname" } @@ -360,6 +386,7 @@ commands: - id: job_pipelist name: harfanglab-job-pipelist description: Start a job to list named pipes on a host (Windows). + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -368,6 +395,7 @@ commands: - id: job_prefetchlist name: harfanglab-job-prefetchlist description: Start a job to collect Windows prefetch files on a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -376,6 +404,7 @@ commands: - id: job_runkeylist name: harfanglab-job-runkeylist description: Start a job to collect registry run keys (hives) on a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -384,6 +413,7 @@ commands: - id: job_scheduledtasklist name: harfanglab-job-scheduledtasklist description: Start a job to list scheduled tasks on a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -392,6 +422,7 @@ commands: - id: job_driverlist name: harfanglab-job-driverlist description: Start a job to list loaded drivers on a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -400,6 +431,7 @@ commands: - id: job_servicelist name: harfanglab-job-servicelist description: Start a job to collect services from registry hives on a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -408,6 +440,7 @@ commands: - id: job_processlist name: harfanglab-job-processlist description: Start a job to list running processes with signature info on a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -416,6 +449,7 @@ commands: - id: job_networkconnectionlist name: harfanglab-job-networkconnectionlist description: Start a job to list processes with their active network connections on a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -424,6 +458,7 @@ commands: - id: job_networksharelist name: harfanglab-job-networksharelist description: Start a job to list network shares on a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -432,6 +467,7 @@ commands: - id: job_sessionlist name: harfanglab-job-sessionlist description: Start a job to list active user sessions on a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -440,6 +476,7 @@ commands: - id: job_persistencelist name: harfanglab-job-persistencelist description: Start a job to scan for persistence mechanisms on a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -448,6 +485,7 @@ commands: - id: job_startuplist name: harfanglab-job-startuplist description: Start a job to list startup files on a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -456,6 +494,7 @@ commands: - id: job_wmilist name: harfanglab-job-wmilist description: Start a job to collect WMI persistence artifacts on a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -464,6 +503,7 @@ commands: - id: job_ioc name: harfanglab-job-ioc description: Start an IOC scan job on a host using filename, filepath, hash, registry, or regex indicators. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -480,6 +520,7 @@ commands: - id: job_info name: harfanglab-job-info description: Retrieve information for one or more jobs by their identifiers. + risk: read inputs_schema: properties: ids: { type: string, description: "Comma-separated list of job IDs to retrieve" } @@ -490,6 +531,7 @@ commands: - id: job_artifact_mft name: harfanglab-job-artifact-mft description: Start a job to collect the NTFS Master File Table (MFT) from a host (Windows). + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -498,6 +540,7 @@ commands: - id: job_artifact_hives name: harfanglab-job-artifact-hives description: Start a job to collect the Windows registry hives from a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -506,6 +549,7 @@ commands: - id: job_artifact_evtx name: harfanglab-job-artifact-evtx description: Start a job to collect the Windows event logs (EVTX) from a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -514,6 +558,7 @@ commands: - id: job_artifact_logs name: harfanglab-job-artifact-logs description: Start a job to collect the system logs from a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -522,6 +567,7 @@ commands: - id: job_artifact_filesystem name: harfanglab-job-artifact-filesystem description: Start a job to collect the filesystem listing from a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -530,6 +576,7 @@ commands: - id: job_artifact_all name: harfanglab-job-artifact-all description: Start a job to collect all raw forensic evidence (hives, event logs, MFT, prefetch, USN journal, logs, filesystem) from a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -538,6 +585,7 @@ commands: - id: job_artifact_ramdump name: harfanglab-job-artifact-ramdump description: Start a job to capture a full memory (RAM) dump from a host. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -546,6 +594,7 @@ commands: - id: job_artifact_downloadfile name: harfanglab-job-artifact-downloadfile description: Start a job to download a specific file from a host by its full path. + risk: safe_write inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -557,6 +606,7 @@ commands: - id: result_pipelist name: harfanglab-result-pipelist description: Get a host's list of named pipes from a job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching job command" } @@ -565,6 +615,7 @@ commands: - id: result_prefetchlist name: harfanglab-result-prefetchlist description: Get a host's prefetch entries from a job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching job command" } @@ -573,6 +624,7 @@ commands: - id: result_runkeylist name: harfanglab-result-runkeylist description: Get a host's registry run keys from a job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching job command" } @@ -581,6 +633,7 @@ commands: - id: result_scheduledtasklist name: harfanglab-result-scheduledtasklist description: Get a host's scheduled tasks from a job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching job command" } @@ -589,6 +642,7 @@ commands: - id: result_driverlist name: harfanglab-result-driverlist description: Get a host's list of drivers from a job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching job command" } @@ -597,6 +651,7 @@ commands: - id: result_servicelist name: harfanglab-result-servicelist description: Get a host's list of services from a job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching job command" } @@ -605,6 +660,7 @@ commands: - id: result_processlist name: harfanglab-result-processlist description: Get a host's list of running processes from a job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching job command" } @@ -613,6 +669,7 @@ commands: - id: result_networkconnectionlist name: harfanglab-result-networkconnectionlist description: Get a host's network connections from a job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching job command" } @@ -621,6 +678,7 @@ commands: - id: result_networksharelist name: harfanglab-result-networksharelist description: Get a host's list of network shares from a job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching job command" } @@ -629,6 +687,7 @@ commands: - id: result_sessionlist name: harfanglab-result-sessionlist description: Get a host's list of user sessions from a job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching job command" } @@ -637,6 +696,7 @@ commands: - id: result_persistencelist name: harfanglab-result-persistencelist description: Get a host's persistence files from a job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching job command" } @@ -645,6 +705,7 @@ commands: - id: result_startuplist name: harfanglab-result-startuplist description: Get a host's startup items from a job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching job command" } @@ -653,6 +714,7 @@ commands: - id: result_wmilist name: harfanglab-result-wmilist description: Get a host's WMI persistence entries from a job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching job command" } @@ -661,6 +723,7 @@ commands: - id: result_ioc name: harfanglab-result-ioc description: Get a host's IOC matches from a job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching job command" } @@ -671,6 +734,7 @@ commands: - id: result_artifact_mft name: harfanglab-result-artifact-mft description: Get the MFT download links from a collection job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching artifact job command" } @@ -679,6 +743,7 @@ commands: - id: result_artifact_hives name: harfanglab-result-artifact-hives description: Get the Windows registry hive download links from a collection job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching artifact job command" } @@ -687,6 +752,7 @@ commands: - id: result_artifact_evtx name: harfanglab-result-artifact-evtx description: Get the Windows event log (EVTX) download links from a collection job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching artifact job command" } @@ -695,6 +761,7 @@ commands: - id: result_artifact_logs name: harfanglab-result-artifact-logs description: Get the Linux system log download links from a collection job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching artifact job command" } @@ -703,6 +770,7 @@ commands: - id: result_artifact_filesystem name: harfanglab-result-artifact-filesystem description: Get the filesystem listing download links from a collection job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching artifact job command" } @@ -711,6 +779,7 @@ commands: - id: result_artifact_all name: harfanglab-result-artifact-all description: Get the download links for all collected artifacts from a collection job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching artifact job command" } @@ -719,6 +788,7 @@ commands: - id: result_artifact_downloadfile name: harfanglab-result-artifact-downloadfile description: Get the download link for a file retrieved by a download-file job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching artifact job command" } @@ -727,6 +797,7 @@ commands: - id: result_artifact_ramdump name: harfanglab-result-artifact-ramdump description: Get the memory (RAM) dump download links from a collection job result. + risk: read inputs_schema: properties: job_id: { type: string, description: "Job ID returned by the matching artifact job command" } @@ -829,7 +900,7 @@ commands: - id: unquarantine_file name: harfanglab-unquarantine-file description: "Restore a quarantined file to its original location on the endpoint. Returns the created job." - risk: safe_write + risk: destructive inputs_schema: properties: agent_id: { type: string, description: "Agent unique identifier from the HarfangLab EDR Manager" } @@ -873,7 +944,7 @@ commands: - id: deisolate_from_threat name: harfanglab-deisolate-from-threat description: "Remove network isolation from all agents involved in a threat." - risk: safe_write + risk: destructive inputs_schema: properties: threat_id: { type: string, description: "Threat identifier" } diff --git a/integrations/hibp/manifest.yaml b/integrations/hibp/manifest.yaml index bc44422..fc32b1c 100644 --- a/integrations/hibp/manifest.yaml +++ b/integrations/hibp/manifest.yaml @@ -1,8 +1,8 @@ id: hibp name: Have I Been Pwned -version: 1.0.0 +version: 1.1.0 description: "Have I Been Pwned (API v3 + Pwned Passwords) — breach enrichment: check an email for breaches and pastes, list and read breaches, and check whether a password appears in breaches (k-anonymity, password never sent). API-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: account breaches/pastes, list/get breach, password pwned check." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 read. An unset risk is read as destructive by the agent approval gate, so the 1 that only read sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: account breaches/pastes, list/get breach, password pwned check." category: enrichment # Per-instance configuration. The API key is sent as the 'hibp-api-key' header @@ -56,6 +56,7 @@ commands: - id: password_pwned name: hibp-password-pwned description: "Check whether a password appears in known breaches (via k-anonymity; the password itself is never transmitted)." + risk: read inputs_schema: properties: password: { type: string, description: "The password to check" } diff --git a/integrations/hybrid-analysis/manifest.yaml b/integrations/hybrid-analysis/manifest.yaml index af2483c..a07c6db 100644 --- a/integrations/hybrid-analysis/manifest.yaml +++ b/integrations/hybrid-analysis/manifest.yaml @@ -1,8 +1,8 @@ id: hybrid_analysis name: Hybrid Analysis -version: 1.0.0 +version: 1.1.0 description: "Hybrid Analysis / CrowdStrike Falcon Sandbox (API v2) — detonate files and URLs, poll analysis state, retrieve report summaries, search by hash, and list sandbox environments. API-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: file/URL submission, report summary and state, hash search and environment listing." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 2 safe_write. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: file/URL submission, report summary and state, hash search and environment listing." category: enrichment # The API key is sent in the 'api-key' header; Hybrid Analysis also requires a @@ -20,6 +20,7 @@ commands: - id: submit_file name: hybrid-analysis-submit-file description: "Submit a file (base64) for analysis in a sandbox environment. Returns a job/sha256; poll with hybrid-analysis-get-state." + risk: safe_write inputs_schema: properties: file_name: { type: string, description: "File name" } @@ -30,6 +31,7 @@ commands: - id: submit_url name: hybrid-analysis-submit-url description: "Submit a URL for analysis in a sandbox environment." + risk: safe_write inputs_schema: properties: url: { type: string, description: "URL to detonate" } diff --git a/integrations/imperva/manifest.yaml b/integrations/imperva/manifest.yaml index c3a67ec..0cb40b0 100644 --- a/integrations/imperva/manifest.yaml +++ b/integrations/imperva/manifest.yaml @@ -1,8 +1,8 @@ id: imperva name: Imperva Cloud WAF -version: 1.0.0 +version: 1.1.0 description: "Imperva Cloud WAF (Cloud Application Security API v1) — edge containment: list sites, read a site's status, block/unblock IPs via the site ACL, and set a security setting. API-ID/API-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list sites, get site status, configure ACL (block IPs), configure security setting." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list sites, get site status, configure ACL (block IPs), configure security setting." category: network # Per-instance configuration. api_id + api_key are sent as form parameters. @@ -40,6 +40,7 @@ commands: - id: block_ips name: imperva-block-ips description: "Set the site's blacklisted-IPs ACL (replaces the current list)." + risk: destructive inputs_schema: properties: site_id: { type: string, description: "Site ID" } @@ -49,6 +50,7 @@ commands: - id: whitelist_ips name: imperva-whitelist-ips description: "Set the site's whitelisted-IPs ACL (replaces the current list)." + risk: destructive inputs_schema: properties: site_id: { type: string, description: "Site ID" } diff --git a/integrations/infoblox/manifest.yaml b/integrations/infoblox/manifest.yaml index 999f159..b3eb283 100644 --- a/integrations/infoblox/manifest.yaml +++ b/integrations/infoblox/manifest.yaml @@ -1,8 +1,8 @@ id: infoblox name: Infoblox NIOS -version: 1.0.0 +version: 1.1.0 description: "Infoblox NIOS (WAPI) — DNS-layer containment and DDI lookups: block a domain via an RPZ record (DNS sinkhole), list and delete RPZ records, search host records, look up networks, and add A records. HTTP Basic authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: add/list/delete RPZ records, search hosts, get networks, add A record." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: add/list/delete RPZ records, search hosts, get networks, add A record." category: network # Per-instance configuration. HTTP Basic auth against the Grid Master WAPI. @@ -35,6 +35,7 @@ commands: - id: add_rpz_domain name: infoblox-add-rpz-domain description: "Block a domain by adding an RPZ CNAME record (returns NXDOMAIN — DNS sinkhole)." + risk: destructive inputs_schema: properties: domain: { type: string, description: "Domain to block (e.g. bad.example.com)" } @@ -55,6 +56,7 @@ commands: - id: delete_rpz_record name: infoblox-delete-rpz-record description: "Delete an RPZ record (unblock) by its object reference." + risk: destructive inputs_schema: properties: ref: { type: string, description: "WAPI object reference (_ref) of the record" } @@ -83,6 +85,7 @@ commands: - id: add_a_record name: infoblox-add-a-record description: "Add a DNS A record." + risk: destructive inputs_schema: properties: name: { type: string, description: "FQDN of the record" } diff --git a/integrations/intezer/manifest.yaml b/integrations/intezer/manifest.yaml index ca8ddaf..652356c 100644 --- a/integrations/intezer/manifest.yaml +++ b/integrations/intezer/manifest.yaml @@ -1,8 +1,8 @@ id: intezer name: Intezer -version: 1.0.0 +version: 1.1.0 description: "Intezer Analyze (API v2) — genetic malware analysis: analyze files (base64), hashes and URLs, retrieve analysis verdicts, IOCs, metadata and sub-analyses. API-key authentication (exchanged for a short-lived access token); stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: analyze by file/hash/URL, analysis result, IOCs, metadata and sub-analyses." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none: 3 safe_write. An unset risk is read as destructive by the agent approval gate, so the 3 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: analyze by file/hash/URL, analysis result, IOCs, metadata and sub-analyses." category: enrichment config_schema: @@ -18,6 +18,7 @@ commands: - id: analyze_by_hash name: intezer-analyze-by-hash description: "Submit a file hash (SHA256, SHA1 or MD5) for analysis. Returns an analysis_id; poll with intezer-get-file-analysis." + risk: safe_write inputs_schema: properties: hash: { type: string, description: "File hash" } @@ -26,6 +27,7 @@ commands: - id: analyze_by_file name: intezer-analyze-by-file description: "Submit a file (base64) for analysis. Returns an analysis_id." + risk: safe_write inputs_schema: properties: file_name: { type: string, description: "File name" } @@ -35,6 +37,7 @@ commands: - id: analyze_url name: intezer-analyze-url description: "Submit a URL for analysis. Returns an analysis_id (use intezer-get-url-analysis)." + risk: safe_write inputs_schema: properties: url: { type: string, description: "URL to analyze" } diff --git a/integrations/intune/manifest.yaml b/integrations/intune/manifest.yaml index aaada38..eb9945e 100644 --- a/integrations/intune/manifest.yaml +++ b/integrations/intune/manifest.yaml @@ -1,8 +1,8 @@ id: intune name: Microsoft Intune -version: 1.0.0 +version: 1.1.0 description: "Microsoft Intune (Microsoft Graph device management) — endpoint containment: list and read managed devices, and retire, wipe, or remote-lock a device. Azure AD OAuth2 client-credentials authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get managed devices, retire/wipe/remote-lock device." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list/get managed devices, retire/wipe/remote-lock device." category: endpoint # Per-instance configuration. Application (client-credentials) OAuth2. The app @@ -48,6 +48,7 @@ commands: - id: retire_device name: intune-retire-device description: "Retire a device (removes company data/management)." + risk: destructive inputs_schema: properties: device_id: { type: string, description: "Managed device ID" } @@ -56,6 +57,7 @@ commands: - id: wipe_device name: intune-wipe-device description: "Wipe a device (factory reset — containment)." + risk: destructive inputs_schema: properties: device_id: { type: string, description: "Managed device ID" } @@ -65,6 +67,7 @@ commands: - id: remote_lock_device name: intune-remote-lock-device description: "Remotely lock a device." + risk: destructive inputs_schema: properties: device_id: { type: string, description: "Managed device ID" } diff --git a/integrations/jira/manifest.yaml b/integrations/jira/manifest.yaml index 0c4fdf1..a1db68f 100644 --- a/integrations/jira/manifest.yaml +++ b/integrations/jira/manifest.yaml @@ -1,8 +1,8 @@ id: jira name: Jira -version: 1.1.0 +version: 1.2.0 description: "Atlassian Jira (REST API, Cloud and On-Prem/Data Center) — issue lifecycle (create/read/edit/delete, transitions, assign), comments, web + issue links, attachments (upload/download/delete), field and user lookups, agile boards/sprints/epics, plus issue ingestion (get_incidents) with an OCSF mapper. Basic (email + API token) or Personal Access Token authentication. Stdlib-only, no extra Python dependencies." -changelog: "1.1.0 — New command list_filters: the saved filters a Jira instance already holds, with their id, JQL and owner, plus the exact clause to paste into a fetch. A saved filter could always be ingested — filter = 12345 is ordinary JQL — but nothing told you the id, so the workflow was invisible. get_incidents and query_issues now mention it in their help. 1.0.2 — Command field help rewritten: every input now says what to type, in what format, and which command finds the value, instead of restating the field name. get_incidents explains that the fetch adds its own created >= watermark clause and ORDER BY, that the watermark is filled by the alert rule, and that a run does not page. Assignee, board, sprint, comment and attachment fields name the command that returns their id. 1.0.1 — A personal access token silently outranked Basic credentials, so an unusable value left in pat turned every call into an opaque 401. Basic authentication now wins whenever username and api_key are both set, pat serves the rest, and a 401/403 names the method it used and whether the other was configured and ignored. Three configurations that cannot work are refused with the reason instead of being sent to Jira: no usable credential, the Cloud gateway URL without a cloud_id, and a cloud_id set against any other host. HTML error pages are condensed to their message rather than dumped whole, and a non-JSON body reports what answered and where. 1.0.0 — Initial release: JQL ingestion + query, full issue CRUD and transitions, comments, links, attachments, fields/users, and agile board/sprint/epic listing. Cloud (API v3, ADF bodies) and On-Prem (API v2) supported." +changelog: "1.2.0 — Declare the risk tier on the 11 commands that carried none: 8 safe_write, 3 destructive. An unset risk is read as destructive by the agent approval gate, so the 8 that only annotate sat behind the same prompt as the ones that change the estate. | 1.1.0 — New command list_filters: the saved filters a Jira instance already holds, with their id, JQL and owner, plus the exact clause to paste into a fetch. A saved filter could always be ingested — filter = 12345 is ordinary JQL — but nothing told you the id, so the workflow was invisible. get_incidents and query_issues now mention it in their help. 1.0.2 — Command field help rewritten: every input now says what to type, in what format, and which command finds the value, instead of restating the field name. get_incidents explains that the fetch adds its own created >= watermark clause and ORDER BY, that the watermark is filled by the alert rule, and that a run does not page. Assignee, board, sprint, comment and attachment fields name the command that returns their id. 1.0.1 — A personal access token silently outranked Basic credentials, so an unusable value left in pat turned every call into an opaque 401. Basic authentication now wins whenever username and api_key are both set, pat serves the rest, and a 401/403 names the method it used and whether the other was configured and ignored. Three configurations that cannot work are refused with the reason instead of being sent to Jira: no usable credential, the Cloud gateway URL without a cloud_id, and a cloud_id set against any other host. HTML error pages are condensed to their message rather than dumped whole, and a non-JSON body reports what answered and where. 1.0.0 — Initial release: JQL ingestion + query, full issue CRUD and transitions, comments, links, attachments, fields/users, and agile board/sprint/epic listing. Cloud (API v3, ADF bodies) and On-Prem (API v2) supported." category: ticketing # Per-instance configuration. For Jira Cloud set cloud_id (found at @@ -88,6 +88,7 @@ commands: - id: create_issue name: jira-create-issue description: "Create a new issue. Provide project_key (or project_name), issue_type_name (or issue_type_id) and a summary." + risk: safe_write inputs_schema: properties: project_key: { type: string, description: "Project key — the prefix of its issue keys, so SOC for SOC-1423. Give this or project_name." } @@ -108,6 +109,7 @@ commands: - id: edit_issue name: jira-edit-issue description: "Edit an issue's fields, and/or move it with status/transition (see jira-list-transitions)." + risk: safe_write inputs_schema: properties: issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." } @@ -128,6 +130,7 @@ commands: - id: delete_issue name: jira-delete-issue description: "Delete an issue (its sub-tasks are deleted too)." + risk: destructive inputs_schema: properties: issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." } @@ -137,6 +140,7 @@ commands: - id: assign_issue name: jira-assign-issue description: "Assign an issue to a user (assignee_id for Cloud, assignee for On-Prem)." + risk: safe_write inputs_schema: properties: issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." } @@ -160,6 +164,7 @@ commands: - id: add_comment name: jira-add-comment description: "Add a comment to an issue." + risk: safe_write inputs_schema: properties: issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." } @@ -182,6 +187,7 @@ commands: - id: edit_comment name: jira-edit-comment description: "Edit an existing comment on an issue." + risk: safe_write inputs_schema: properties: issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." } @@ -194,6 +200,7 @@ commands: - id: delete_comment name: jira-delete-comment description: "Delete a comment from an issue." + risk: destructive inputs_schema: properties: issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." } @@ -206,6 +213,7 @@ commands: - id: add_link name: jira-add-link description: "Add a remote web link (URL) to an issue." + risk: safe_write inputs_schema: properties: issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." } @@ -219,6 +227,7 @@ commands: - id: link_issues name: jira-link-issues description: "Create a link between two issues (see jira-get-link-types for link_type names)." + risk: safe_write inputs_schema: properties: inward_issue: { type: string, description: "One end of the link, key or numeric ID, e.g. SOC-1423. get_link_types gives each type's inward and outward wording, which tells you which issue goes on which side." } @@ -240,6 +249,7 @@ commands: - id: upload_file name: jira-upload-file description: "Attach a file to an issue (content provided as base64)." + risk: safe_write inputs_schema: properties: issue_id: { type: string, description: "Numeric issue ID, e.g. 10042 — the id field the fetch returns. Give this or issue_key." } @@ -260,6 +270,7 @@ commands: - id: delete_attachment name: jira-delete-attachment description: "Delete an attachment by attachment ID." + risk: destructive inputs_schema: properties: attachment_id: { type: string, description: "Numeric attachment ID, e.g. 10520 — get_issue lists them under attachments." } diff --git a/integrations/joe-sandbox/manifest.yaml b/integrations/joe-sandbox/manifest.yaml index 4f97f61..41272ea 100644 --- a/integrations/joe-sandbox/manifest.yaml +++ b/integrations/joe-sandbox/manifest.yaml @@ -1,8 +1,8 @@ id: joe_sandbox name: Joe Sandbox -version: 1.0.0 +version: 1.1.0 description: "Joe Sandbox Cloud (Web API v2) — detonate files and URLs, poll submission/analysis status, search analyses, download reports and read the account quota. API-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: file/URL submission, submission and analysis info, search, report download and account quota." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 2 safe_write. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: file/URL submission, submission and analysis info, search, report download and account quota." category: enrichment # Per-instance configuration. The default server is Joe Sandbox Cloud Pro; set @@ -25,6 +25,7 @@ commands: - id: submit_sample name: joe-sandbox-submit-sample description: "Submit a file (base64) for analysis. Returns a submission_id; poll it with joe-sandbox-submission-info." + risk: safe_write inputs_schema: properties: file_name: { type: string, description: "File name" } @@ -36,6 +37,7 @@ commands: - id: submit_url name: joe-sandbox-submit-url description: "Submit a URL for analysis. Returns a submission_id." + risk: safe_write inputs_schema: properties: url: { type: string, description: "URL to detonate" } diff --git a/integrations/jumpcloud/manifest.yaml b/integrations/jumpcloud/manifest.yaml index 2fa6a67..81b5a2b 100644 --- a/integrations/jumpcloud/manifest.yaml +++ b/integrations/jumpcloud/manifest.yaml @@ -1,8 +1,8 @@ id: jumpcloud name: JumpCloud -version: 1.0.0 +version: 1.1.0 description: "JumpCloud (API v1) — identity and device containment: list and read users, suspend/activate a user, and list systems (devices). API-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get users, suspend/activate user, list systems." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list/get users, suspend/activate user, list systems." category: identity # Per-instance configuration. Auth header 'x-api-key: '. @@ -41,6 +41,7 @@ commands: - id: suspend_user name: jumpcloud-suspend-user description: "Suspend a user (containment)." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "System user ID" } @@ -49,6 +50,7 @@ commands: - id: activate_user name: jumpcloud-activate-user description: "Un-suspend (activate) a user." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "System user ID" } diff --git a/integrations/mail-sender/manifest.yaml b/integrations/mail-sender/manifest.yaml index 652fb12..75ea628 100644 --- a/integrations/mail-sender/manifest.yaml +++ b/integrations/mail-sender/manifest.yaml @@ -1,8 +1,8 @@ id: mail_sender name: Mail Sender -version: 1.0.0 +version: 1.1.0 description: "Send email over SMTP — plain-text and rich HTML bodies (with inline data-URI images), file attachments (base64), CC/BCC, Reply-To and custom headers. Supports plain, STARTTLS and SSL/TLS connections with optional authentication. Stdlib-only (smtplib), no extra Python dependencies; run on a remote engine when the SMTP server is only reachable from inside your network." -changelog: "1.0.0 — Initial release: send-mail (text/HTML, inline images, base64 attachment, CC/BCC/Reply-To/custom headers) and a connectivity test." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: send-mail (text/HTML, inline images, base64 attachment, CC/BCC/Reply-To/custom headers) and a connectivity test." category: email # Per-instance configuration. Connects to an SMTP server to send outbound mail. @@ -48,6 +48,7 @@ commands: - id: send_mail name: mail-sender-send-mail description: "Send an email. At least one recipient (to/cc/bcc) is required; subject and body may be empty." + risk: safe_write inputs_schema: properties: to: { type: string, description: "Recipient(s) for the To field, comma-separated" } diff --git a/integrations/mailinblack/manifest.yaml b/integrations/mailinblack/manifest.yaml index c21ece8..6d8f41c 100644 --- a/integrations/mailinblack/manifest.yaml +++ b/integrations/mailinblack/manifest.yaml @@ -1,8 +1,8 @@ id: mailinblack name: Mailinblack -version: 1.0.0 +version: 1.1.0 description: "Mailinblack (email protection API) — anti-phishing operations: list quarantined messages, release a message, and manage sender allow/block lists. Bearer-token authentication; stdlib-only, no extra Python dependencies. (French vendor. NOTE: exact API paths are best-effort — verify against the Mailinblack API documentation before production use.)" -changelog: "1.0.0 — Initial release: list quarantine, release message, block/allow sender." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list quarantine, release message, block/allow sender." category: email # Per-instance configuration. Auth header 'Authorization: Bearer '. @@ -33,6 +33,7 @@ commands: - id: release_message name: mailinblack-release-message description: "Release a quarantined message for delivery." + risk: destructive inputs_schema: properties: message_id: { type: string, description: "Message ID" } @@ -41,6 +42,7 @@ commands: - id: block_sender name: mailinblack-block-sender description: "Add a sender to the block list." + risk: destructive inputs_schema: properties: sender: { type: string, description: "Sender address to block" } @@ -49,6 +51,7 @@ commands: - id: allow_sender name: mailinblack-allow-sender description: "Add a sender to the allow list." + risk: destructive inputs_schema: properties: sender: { type: string, description: "Sender address to allow" } diff --git a/integrations/mattermost/manifest.yaml b/integrations/mattermost/manifest.yaml index e1a5f02..5e17ab2 100644 --- a/integrations/mattermost/manifest.yaml +++ b/integrations/mattermost/manifest.yaml @@ -1,8 +1,8 @@ id: mattermost name: Mattermost -version: 1.0.0 +version: 1.1.0 description: "Mattermost (REST API v4) — SOC ChatOps: create posts, look up channels by name, search posts, create channels, and look up users. Bearer-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: create post, get channel by name, search posts, create channel, get user." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 2 safe_write. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: create post, get channel by name, search posts, create channel, get user." category: notification # Per-instance configuration. Auth header 'Authorization: Bearer '. @@ -23,6 +23,7 @@ commands: - id: create_post name: mattermost-create-post description: "Create a post in a channel." + risk: safe_write inputs_schema: properties: channel_id: { type: string, description: "Channel ID" } @@ -52,6 +53,7 @@ commands: - id: create_channel name: mattermost-create-channel description: "Create a channel." + risk: safe_write inputs_schema: properties: team_id: { type: string, description: "Team ID" } diff --git a/integrations/microsoft-defender-endpoint/manifest.yaml b/integrations/microsoft-defender-endpoint/manifest.yaml index da73d34..8875e50 100644 --- a/integrations/microsoft-defender-endpoint/manifest.yaml +++ b/integrations/microsoft-defender-endpoint/manifest.yaml @@ -1,8 +1,8 @@ id: microsoft_defender_endpoint name: Microsoft Defender for Endpoint -version: 1.0.0 +version: 1.1.0 description: "Microsoft Defender for Endpoint (Security Center API) — machine isolation, app-execution restriction, antivirus scan, file quarantine, investigation package collection, offboarding, tagging, alert triage, advanced hunting (KQL), custom indicators, and alert ingestion (get_incidents) with an OCSF mapper. Azure AD OAuth 2.0 client-credentials authentication. Stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: alert ingestion + triage, machine actions (isolate/unisolate, restrict/unrestrict app execution, AV scan, quarantine file, collect package, offboard, tag), advanced hunting, custom indicators, and machine/action listing." +changelog: "1.1.0 — Declare the risk tier on the 12 commands that carried none: 4 safe_write, 8 destructive. An unset risk is read as destructive by the agent approval gate, so the 4 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: alert ingestion + triage, machine actions (isolate/unisolate, restrict/unrestrict app execution, AV scan, quarantine file, collect package, offboard, tag), advanced hunting, custom indicators, and machine/action listing." category: endpoint # Per-instance configuration. Register an Azure AD application, grant it the @@ -67,6 +67,7 @@ commands: - id: update_alert name: microsoft-defender-endpoint-update-alert description: "Update an alert's status, classification, determination or assignment." + risk: safe_write inputs_schema: properties: alert_id: { type: string, description: "Alert ID" } @@ -111,6 +112,7 @@ commands: - id: isolate_machine name: microsoft-defender-endpoint-isolate-machine description: "Network-isolate a machine." + risk: destructive inputs_schema: properties: machine_id: { type: string, description: "Machine ID" } @@ -121,6 +123,7 @@ commands: - id: unisolate_machine name: microsoft-defender-endpoint-unisolate-machine description: "Release a machine from network isolation." + risk: destructive inputs_schema: properties: machine_id: { type: string, description: "Machine ID" } @@ -130,6 +133,7 @@ commands: - id: restrict_app_execution name: microsoft-defender-endpoint-restrict-app-execution description: "Restrict application execution on a machine (allow only Microsoft-signed binaries)." + risk: destructive inputs_schema: properties: machine_id: { type: string, description: "Machine ID" } @@ -139,6 +143,7 @@ commands: - id: remove_app_restriction name: microsoft-defender-endpoint-remove-app-restriction description: "Remove the application-execution restriction from a machine." + risk: destructive inputs_schema: properties: machine_id: { type: string, description: "Machine ID" } @@ -148,6 +153,7 @@ commands: - id: run_antivirus_scan name: microsoft-defender-endpoint-run-antivirus-scan description: "Trigger a Defender antivirus scan on a machine." + risk: safe_write inputs_schema: properties: machine_id: { type: string, description: "Machine ID" } @@ -158,6 +164,7 @@ commands: - id: stop_and_quarantine_file name: microsoft-defender-endpoint-stop-and-quarantine-file description: "Stop execution of a file (by SHA1) and quarantine it on a machine." + risk: destructive inputs_schema: properties: machine_id: { type: string, description: "Machine ID" } @@ -168,6 +175,7 @@ commands: - id: collect_investigation_package name: microsoft-defender-endpoint-collect-investigation-package description: "Collect a forensic investigation package from a machine (returns a machine action; poll it for the download URI)." + risk: safe_write inputs_schema: properties: machine_id: { type: string, description: "Machine ID" } @@ -177,6 +185,7 @@ commands: - id: offboard_machine name: microsoft-defender-endpoint-offboard-machine description: "Offboard a machine from Defender for Endpoint." + risk: destructive inputs_schema: properties: machine_id: { type: string, description: "Machine ID" } @@ -186,6 +195,7 @@ commands: - id: tag_machine name: microsoft-defender-endpoint-tag-machine description: "Add or remove a tag on a machine." + risk: safe_write inputs_schema: properties: machine_id: { type: string, description: "Machine ID" } @@ -227,6 +237,7 @@ commands: - id: create_indicator name: microsoft-defender-endpoint-create-indicator description: "Create a custom indicator (file hash, IP, URL or domain) with an action." + risk: destructive inputs_schema: properties: indicator_value: { type: string, description: "Indicator value (hash, IP, URL or domain)" } @@ -241,6 +252,7 @@ commands: - id: delete_indicator name: microsoft-defender-endpoint-delete-indicator description: "Delete a custom indicator by ID." + risk: destructive inputs_schema: properties: indicator_id: { type: string, description: "Indicator ID" } diff --git a/integrations/microsoft-defender-o365/manifest.yaml b/integrations/microsoft-defender-o365/manifest.yaml index 8d6fe43..be747c9 100644 --- a/integrations/microsoft-defender-o365/manifest.yaml +++ b/integrations/microsoft-defender-o365/manifest.yaml @@ -1,8 +1,8 @@ id: microsoft_defender_o365 name: Microsoft Defender for Office 365 -version: 1.0.0 +version: 1.1.0 description: "Microsoft Defender for Office 365 email remediation (Microsoft Graph mail APIs) — anti-phishing containment: search a mailbox for messages, read a message and its attachments, move a message to a folder, and hard-delete (purge) a phishing message. Azure AD OAuth2 client-credentials authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: search mailbox messages, get message, list attachments, list folders, move message, delete (purge) message." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 1 safe_write, 1 destructive. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: search mailbox messages, get message, list attachments, list folders, move message, delete (purge) message." category: email # Per-instance configuration. Uses application (client-credentials) OAuth2. @@ -70,6 +70,7 @@ commands: - id: move_message name: mdo-move-message description: "Move a message to another folder (e.g. to Junk Email or a quarantine folder)." + risk: safe_write inputs_schema: properties: mailbox: { type: string, description: "Target mailbox (UPN or ID)" } @@ -80,6 +81,7 @@ commands: - id: delete_message name: mdo-delete-message description: "Hard-delete (purge) a message from the mailbox." + risk: destructive inputs_schema: properties: mailbox: { type: string, description: "Target mailbox (UPN or ID)" } diff --git a/integrations/microsoft-entra-id/manifest.yaml b/integrations/microsoft-entra-id/manifest.yaml index 8c8a722..f4e22d6 100644 --- a/integrations/microsoft-entra-id/manifest.yaml +++ b/integrations/microsoft-entra-id/manifest.yaml @@ -1,8 +1,8 @@ id: microsoft_entra_id name: Microsoft Entra ID -version: 1.0.0 +version: 1.1.0 description: "Microsoft Entra ID (Microsoft Graph, users) — identity response and lifecycle: look up/list users, create/update/delete, disable and re-enable accounts, revoke sign-in sessions, force password reset, and read groups, manager and authentication methods. Azure AD OAuth 2.0 client-credentials authentication. Stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: user get/list/create/update/delete, account disable/enable, session revocation, password reset, and group/manager/auth-method reads." +changelog: "1.1.0 — Declare the risk tier on the 8 commands that carried none: 1 safe_write, 7 destructive. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: user get/list/create/update/delete, account disable/enable, session revocation, password reset, and group/manager/auth-method reads." category: identity # Per-instance configuration. Register an Azure AD application, grant it the @@ -53,6 +53,7 @@ commands: - id: create_user name: microsoft-entra-id-create-user description: "Create a user account." + risk: destructive inputs_schema: properties: user_principal_name: { type: string, description: "userPrincipalName (email), e.g. jdoe@contoso.com" } @@ -70,6 +71,7 @@ commands: - id: update_user name: microsoft-entra-id-update-user description: "Update a user's profile fields." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User object ID or userPrincipalName" } @@ -85,6 +87,7 @@ commands: - id: delete_user name: microsoft-entra-id-delete-user description: "Delete a user account." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User object ID or userPrincipalName" } @@ -93,6 +96,7 @@ commands: - id: disable_account name: microsoft-entra-id-disable-account description: "Disable a user account (accountEnabled = false)." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User object ID or userPrincipalName" } @@ -101,6 +105,7 @@ commands: - id: enable_account name: microsoft-entra-id-enable-account description: "Re-enable a user account (accountEnabled = true)." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User object ID or userPrincipalName" } @@ -109,6 +114,7 @@ commands: - id: revoke_sessions name: microsoft-entra-id-revoke-sessions description: "Revoke all refresh tokens / sign-in sessions for a user (forces re-authentication)." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User object ID or userPrincipalName" } @@ -117,6 +123,7 @@ commands: - id: reset_password name: microsoft-entra-id-reset-password description: "Set a user's password (optionally forcing a change at next sign-in)." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User object ID or userPrincipalName" } @@ -146,6 +153,7 @@ commands: - id: assign_manager name: microsoft-entra-id-assign-manager description: "Set a user's manager." + risk: safe_write inputs_schema: properties: user_id: { type: string, description: "User object ID or userPrincipalName" } diff --git a/integrations/microsoft-graph-files/manifest.yaml b/integrations/microsoft-graph-files/manifest.yaml index f44274c..73b0a5a 100644 --- a/integrations/microsoft-graph-files/manifest.yaml +++ b/integrations/microsoft-graph-files/manifest.yaml @@ -1,8 +1,8 @@ id: microsoft_graph_files name: Microsoft Graph Files -version: 1.0.0 +version: 1.1.0 description: "Microsoft Graph file management for O365 (OneDrive / SharePoint / Teams) — browse sites, drives and content, create folders, upload/replace/download files, manage site permissions, read SharePoint lists, and edit Excel worksheets. App-only authentication (client credentials)." -changelog: "1.0.0 — Initial release: SharePoint sites/drives/content browsing, folder creation, file delete/upload/replace/download (via URL or base64), site permission management (list/create/update/delete), SharePoint list reading (lists/items/get-item), and Excel worksheet editing (add-row/get-worksheet/update-cell). App-only client-credentials authentication." +changelog: "1.1.0 — Declare the risk tier on the 9 commands that carried none: 4 safe_write, 5 destructive. An unset risk is read as destructive by the agent approval gate, so the 4 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: SharePoint sites/drives/content browsing, folder creation, file delete/upload/replace/download (via URL or base64), site permission management (list/create/update/delete), SharePoint list reading (lists/items/get-item), and Excel worksheet editing (add-row/get-worksheet/update-cell). App-only client-credentials authentication." category: productivity # Per-instance configuration. Uses app-only (client credentials) authentication @@ -95,6 +95,7 @@ commands: - id: create_new_folder name: msgraph-create-new-folder description: "Create a folder under a parent item in a drive." + risk: safe_write inputs_schema: properties: object_type: { type: string, description: "drives, groups, sites or users" } @@ -106,6 +107,7 @@ commands: - id: delete_file name: msgraph-delete-file description: "Delete a drive item (file or folder) by its ID." + risk: destructive inputs_schema: properties: object_type: { type: string, description: "drives, groups, sites or users" } @@ -130,6 +132,7 @@ commands: - id: upload_new_file name: msgraph-upload-new-file description: "Upload a new file into a folder. Provide the content via content_base64 or source_url." + risk: safe_write inputs_schema: properties: object_type: { type: string, description: "drives, groups, sites or users" } @@ -143,6 +146,7 @@ commands: - id: replace_existing_file name: msgraph-replace-existing-file description: "Replace the content of an existing file. Provide the new content via content_base64 or source_url." + risk: destructive inputs_schema: properties: object_type: { type: string, description: "drives, groups, sites or users" } @@ -168,6 +172,7 @@ commands: - id: create_site_permissions name: msgraph-create-site-permissions description: "Grant an application permission (read/write/owner) on a site." + risk: destructive inputs_schema: properties: site_id: { type: string, description: "Site ID (or provide site_name)" } @@ -180,6 +185,7 @@ commands: - id: update_site_permissions name: msgraph-update-site-permissions description: "Update the role of an existing site permission." + risk: destructive inputs_schema: properties: site_id: { type: string, description: "Site ID (or provide site_name)" } @@ -191,6 +197,7 @@ commands: - id: delete_site_permissions name: msgraph-delete-site-permissions description: "Delete an application permission from a site." + risk: destructive inputs_schema: properties: site_id: { type: string, description: "Site ID (or provide site_name)" } @@ -247,6 +254,7 @@ commands: - id: excel_add_row name: msgraph-excel-add-row description: "Append a row to an Excel worksheet. 'data' is a JSON object mapping column number (1-based) to value, e.g. {\"1\":\"foo\",\"2\":42}." + risk: safe_write inputs_schema: properties: object_type: { type: string, description: "drives, groups, sites or users" } @@ -273,6 +281,7 @@ commands: - id: excel_update_cell name: msgraph-excel-update-cell description: "Overwrite a single Excel cell. 'column' may be a number or 'Col_2'." + risk: safe_write inputs_schema: properties: object_type: { type: string, description: "drives, groups, sites or users" } diff --git a/integrations/microsoft-purview/manifest.yaml b/integrations/microsoft-purview/manifest.yaml index 51c167c..756f5a1 100644 --- a/integrations/microsoft-purview/manifest.yaml +++ b/integrations/microsoft-purview/manifest.yaml @@ -1,8 +1,8 @@ id: microsoft_purview name: Microsoft Purview -version: 1.0.0 +version: 1.1.0 description: "Microsoft Purview DLP alerts (via Microsoft Graph Security API) — data-loss-prevention triage: list and read DLP security alerts, update alert status/assignment, and list/read security incidents. Azure AD OAuth2 client-credentials authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get DLP alerts, update alert, list/get incidents." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list/get DLP alerts, update alert, list/get incidents." category: dlp # Per-instance configuration. Application (client-credentials) OAuth2. Needs Graph @@ -47,6 +47,7 @@ commands: - id: update_alert name: purview-update-alert description: "Update an alert's status and/or assignee." + risk: safe_write inputs_schema: properties: alert_id: { type: string, description: "Alert ID" } diff --git a/integrations/microsoft-sentinel/manifest.yaml b/integrations/microsoft-sentinel/manifest.yaml index 3ca30bb..ad3e1b7 100644 --- a/integrations/microsoft-sentinel/manifest.yaml +++ b/integrations/microsoft-sentinel/manifest.yaml @@ -1,8 +1,8 @@ id: microsoft_sentinel name: Microsoft Sentinel -version: 1.0.0 +version: 1.1.0 description: "Microsoft Sentinel (Azure Resource Manager API) — incident management (list/get/create/update/delete, comments, related alerts/entities), watchlists, threat indicators, and incident ingestion (get_incidents) with an OCSF mapper. Azure AD OAuth 2.0 client-credentials authentication. Stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: incident CRUD + comments + related data, watchlist listing/upsert, threat indicator CRUD, and incident ingestion with an OCSF mapper." +changelog: "1.1.0 — Declare the risk tier on the 8 commands that carried none: 6 safe_write, 2 destructive. An unset risk is read as destructive by the agent approval gate, so the 6 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: incident CRUD + comments + related data, watchlist listing/upsert, threat indicator CRUD, and incident ingestion with an OCSF mapper." category: siem # Per-instance configuration. Register an Azure AD application, grant it the @@ -78,6 +78,7 @@ commands: - id: create_incident name: microsoft-sentinel-create-incident description: "Create an incident." + risk: safe_write inputs_schema: properties: title: { type: string, description: "Incident title" } @@ -90,6 +91,7 @@ commands: - id: update_incident name: microsoft-sentinel-update-incident description: "Update an incident's title, status, severity, classification or owner." + risk: safe_write inputs_schema: properties: incident_id: { type: string, description: "Incident name/ID (GUID)" } @@ -105,6 +107,7 @@ commands: - id: delete_incident name: microsoft-sentinel-delete-incident description: "Delete an incident." + risk: destructive inputs_schema: properties: incident_id: { type: string, description: "Incident name/ID (GUID)" } @@ -113,6 +116,7 @@ commands: - id: add_comment name: microsoft-sentinel-add-comment description: "Add a comment to an incident." + risk: safe_write inputs_schema: properties: incident_id: { type: string, description: "Incident name/ID (GUID)" } @@ -180,6 +184,7 @@ commands: - id: upsert_watchlist_item name: microsoft-sentinel-upsert-watchlist-item description: "Create or update a watchlist item (properties as a JSON object)." + risk: safe_write inputs_schema: properties: watchlist_alias: { type: string, description: "Watchlist alias" } @@ -202,6 +207,7 @@ commands: - id: create_threat_indicator name: microsoft-sentinel-create-threat-indicator description: "Create a threat intelligence indicator." + risk: safe_write inputs_schema: properties: value: { type: string, description: "Indicator value" } @@ -215,6 +221,7 @@ commands: - id: update_threat_indicator name: microsoft-sentinel-update-threat-indicator description: "Update a threat intelligence indicator (display name, confidence, expiry, threat types)." + risk: safe_write inputs_schema: properties: indicator_name: { type: string, description: "Indicator name (from list_threat_indicators)" } @@ -227,6 +234,7 @@ commands: - id: delete_threat_indicator name: microsoft-sentinel-delete-threat-indicator description: "Delete a threat intelligence indicator by name." + risk: destructive inputs_schema: properties: indicator_name: { type: string, description: "Indicator name (from list_threat_indicators)" } diff --git a/integrations/microsoft-teams/manifest.yaml b/integrations/microsoft-teams/manifest.yaml index 85bab7d..54f3245 100644 --- a/integrations/microsoft-teams/manifest.yaml +++ b/integrations/microsoft-teams/manifest.yaml @@ -1,8 +1,8 @@ id: microsoft_teams name: Microsoft Teams -version: 1.0.0 +version: 1.1.0 description: "Microsoft Teams (incoming webhook / Power Automate Workflows) — SOC notification: post plain messages and rich Adaptive Cards (title, text, facts, optional action button) to a Teams channel. Webhook-URL authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: send message, send Adaptive Card." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 2 safe_write. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: send message, send Adaptive Card." category: notification # Per-instance configuration. The webhook URL is created in Teams @@ -21,6 +21,7 @@ commands: - id: send_message name: teams-send-message description: "Post a plain-text message to the Teams channel." + risk: safe_write inputs_schema: properties: text: { type: string, description: "Message text (Markdown supported)" } @@ -29,6 +30,7 @@ commands: - id: send_card name: teams-send-card description: "Post an Adaptive Card built from a title, body text, optional facts, and an optional action button." + risk: safe_write inputs_schema: properties: title: { type: string, description: "Card title" } diff --git a/integrations/mimecast/manifest.yaml b/integrations/mimecast/manifest.yaml index 4917f60..5fe27ff 100644 --- a/integrations/mimecast/manifest.yaml +++ b/integrations/mimecast/manifest.yaml @@ -1,8 +1,8 @@ id: mimecast name: Mimecast -version: 1.0.0 +version: 1.1.0 description: "Mimecast (Email Security API) — anti-phishing containment: list/release/reject held messages, search messages and get message info, block URLs (managed URLs), block senders, create remediation incidents, and decode rewritten URLs. HMAC-SHA1 signed authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: held-message list/release/reject, message search + info, managed URL create/list, block sender, create remediation, URL decode." +changelog: "1.1.0 — Declare the risk tier on the 5 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: held-message list/release/reject, message search + info, managed URL create/list, block sender, create remediation, URL decode." category: email # Per-instance configuration. Requests are signed (HMAC-SHA1) with the @@ -48,6 +48,7 @@ commands: - id: release_held_message name: mimecast-release-held-message description: "Release a held message for delivery." + risk: destructive inputs_schema: properties: message_id: { type: string, description: "Held message ID" } @@ -56,6 +57,7 @@ commands: - id: reject_held_message name: mimecast-reject-held-message description: "Reject a held message." + risk: destructive inputs_schema: properties: message_id: { type: string, description: "Held message ID" } @@ -87,6 +89,7 @@ commands: - id: create_managed_url name: mimecast-create-managed-url description: "Add a URL to the managed URL list (block or permit)." + risk: destructive inputs_schema: properties: url: { type: string, description: "URL to manage" } @@ -106,6 +109,7 @@ commands: - id: block_sender name: mimecast-block-sender description: "Block (or permit) a sender for a recipient." + risk: destructive inputs_schema: properties: sender: { type: string, description: "Sender address to block/permit" } @@ -116,6 +120,7 @@ commands: - id: create_remediation name: mimecast-create-remediation description: "Create a remediation incident to pull malicious messages from mailboxes." + risk: destructive inputs_schema: properties: message_hash: { type: string, description: "File hash to remediate (provide this or message_id)" } diff --git a/integrations/misp/manifest.yaml b/integrations/misp/manifest.yaml index 61e35da..536c735 100644 --- a/integrations/misp/manifest.yaml +++ b/integrations/misp/manifest.yaml @@ -1,8 +1,8 @@ id: misp name: MISP -version: 1.0.0 +version: 1.1.0 description: "MISP (threat-intelligence platform, REST API) — search events and attributes, read and create events, add attributes, tag events, add sightings, publish and delete events. API-key authentication; stdlib-only, no extra Python dependencies. Works with any MISP instance." -changelog: "1.0.0 — Initial release: event/attribute search, event read/create/publish/delete, attribute add, event tagging and sightings." +changelog: "1.1.0 — Declare the risk tier on the 6 commands that carried none: 4 safe_write, 2 destructive. An unset risk is read as destructive by the agent approval gate, so the 4 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: event/attribute search, event read/create/publish/delete, attribute add, event tagging and sightings." category: enrichment # Per-instance configuration. The API key (auth key) is sent in the @@ -64,6 +64,7 @@ commands: - id: create_event name: misp-create-event description: "Create a new event." + risk: safe_write inputs_schema: properties: info: { type: string, description: "Event description/info" } @@ -76,6 +77,7 @@ commands: - id: add_attribute name: misp-add-attribute description: "Add an attribute (indicator) to an event." + risk: safe_write inputs_schema: properties: event_id: { type: string, description: "Event ID" } @@ -89,6 +91,7 @@ commands: - id: add_tag_to_event name: misp-add-tag-to-event description: "Attach a tag to an event." + risk: safe_write inputs_schema: properties: event_id: { type: string, description: "Event ID or UUID" } @@ -98,6 +101,7 @@ commands: - id: add_sighting name: misp-add-sighting description: "Add a sighting for an attribute value." + risk: safe_write inputs_schema: properties: value: { type: string, description: "Attribute value that was sighted" } @@ -107,6 +111,7 @@ commands: - id: publish_event name: misp-publish-event description: "Publish an event." + risk: destructive inputs_schema: properties: event_id: { type: string, description: "Event ID" } @@ -115,6 +120,7 @@ commands: - id: delete_event name: misp-delete-event description: "Delete an event." + risk: destructive inputs_schema: properties: event_id: { type: string, description: "Event ID" } diff --git a/integrations/netskope/manifest.yaml b/integrations/netskope/manifest.yaml index 70c36e0..c09c3fc 100644 --- a/integrations/netskope/manifest.yaml +++ b/integrations/netskope/manifest.yaml @@ -1,8 +1,8 @@ id: netskope name: Netskope -version: 1.0.0 +version: 1.1.0 description: "Netskope (SASE/CASB REST API v2) — web/cloud containment: list and read URL lists, replace a URL list (block list) and deploy it, and list enrolled users/clients. API-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get URL lists, replace URL list, deploy URL lists, list users." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list/get URL lists, replace URL list, deploy URL lists, list users." category: network # Per-instance configuration. The token is sent as the 'Netskope-Api-Token' header. @@ -40,6 +40,7 @@ commands: - id: replace_url_list name: netskope-replace-url-list description: "Replace the URLs of a URL list (e.g. update a block list)." + risk: destructive inputs_schema: properties: list_id: { type: string, description: "URL list ID" } @@ -51,6 +52,7 @@ commands: - id: deploy_url_lists name: netskope-deploy-url-lists description: "Deploy pending URL-list changes so they take effect." + risk: destructive inputs_schema: properties: {} required: [] diff --git a/integrations/okta/manifest.yaml b/integrations/okta/manifest.yaml index 27e98a6..e1abb5d 100644 --- a/integrations/okta/manifest.yaml +++ b/integrations/okta/manifest.yaml @@ -1,8 +1,8 @@ id: okta name: Okta -version: 1.0.0 +version: 1.1.0 description: "Okta (Core API) — identity containment and investigation: suspend/unsuspend/deactivate/unlock users, clear active sessions and tokens, expire passwords, reset MFA factors, read users and factors, query the System Log, and manage group membership. API-token (SSWS) authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: user lifecycle (suspend/unsuspend/deactivate/unlock), clear sessions, expire password, reset factors, get/list users, get factors, system log, add/remove group membership." +changelog: "1.1.0 — Declare the risk tier on the 9 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: user lifecycle (suspend/unsuspend/deactivate/unlock), clear sessions, expire password, reset factors, get/list users, get factors, system log, add/remove group membership." category: identity # Per-instance configuration. The API token is sent as 'Authorization: SSWS '. @@ -23,6 +23,7 @@ commands: - id: suspend_user name: okta-suspend-user description: "Suspend a user (blocks sign-in without deleting the account)." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User ID or login" } @@ -31,6 +32,7 @@ commands: - id: unsuspend_user name: okta-unsuspend-user description: "Unsuspend a user (restores an ACTIVE status)." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User ID or login" } @@ -39,6 +41,7 @@ commands: - id: deactivate_user name: okta-deactivate-user description: "Deactivate a user (stronger than suspend; requires reactivation to restore)." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User ID or login" } @@ -47,6 +50,7 @@ commands: - id: unlock_user name: okta-unlock-user description: "Unlock a user that was locked out by failed sign-ins." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User ID or login" } @@ -55,6 +59,7 @@ commands: - id: clear_user_sessions name: okta-clear-user-sessions description: "Revoke all of a user's active sessions and (optionally) OAuth tokens." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User ID" } @@ -64,6 +69,7 @@ commands: - id: expire_password name: okta-expire-password description: "Expire a user's password, forcing a reset at next sign-in." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User ID or login" } @@ -72,6 +78,7 @@ commands: - id: reset_factors name: okta-reset-factors description: "Reset (remove) all enrolled MFA factors for a user." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User ID" } @@ -123,6 +130,7 @@ commands: - id: add_user_to_group name: okta-add-user-to-group description: "Add a user to a group." + risk: destructive inputs_schema: properties: group_id: { type: string, description: "Group ID" } @@ -132,6 +140,7 @@ commands: - id: remove_user_from_group name: okta-remove-user-from-group description: "Remove a user from a group." + risk: destructive inputs_schema: properties: group_id: { type: string, description: "Group ID" } diff --git a/integrations/onelogin/manifest.yaml b/integrations/onelogin/manifest.yaml index 60acd45..adb3463 100644 --- a/integrations/onelogin/manifest.yaml +++ b/integrations/onelogin/manifest.yaml @@ -1,8 +1,8 @@ id: onelogin name: OneLogin -version: 1.0.0 +version: 1.1.0 description: "OneLogin (API v1/v2) — identity containment: list and read users, lock a user, log a user out of all sessions, and read events. OAuth2 client-credentials authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get users, lock user, logout user, list events." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list/get users, lock user, logout user, list events." category: identity # Per-instance configuration. Client credentials are exchanged for a bearer token. @@ -46,6 +46,7 @@ commands: - id: lock_user name: onelogin-lock-user description: "Lock a user account (containment)." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User ID" } @@ -55,6 +56,7 @@ commands: - id: logout_user name: onelogin-logout-user description: "Log a user out of all active sessions." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User ID" } diff --git a/integrations/opencti/manifest.yaml b/integrations/opencti/manifest.yaml index 6549676..ba12e22 100644 --- a/integrations/opencti/manifest.yaml +++ b/integrations/opencti/manifest.yaml @@ -1,8 +1,8 @@ id: opencti name: OpenCTI -version: 1.0.0 +version: 1.1.0 description: "OpenCTI threat-intelligence platform (GraphQL API, compatible with OpenCTI 5.x/6.x). Query and manage observables, indicators, incidents, relationships, labels, markings, organizations and external references; ingest OpenCTI incidents with an OCSF mapper. Runs on a remote engine. Requires the Python 'pycti' library on the engine host (pip install pycti)." -changelog: "1.0.0 — Initial release: observables (list/create/delete/field update/add/remove), indicators (list/create/update/field add/remove, types), incidents (list/create/delete, types) with OCSF ingestion mapper, relationships (list/create/delete), and reference data (organizations, labels, marking definitions, external references)." +changelog: "1.1.0 — Declare the risk tier on the 5 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: observables (list/create/delete/field update/add/remove), indicators (list/create/update/field add/remove, types), incidents (list/create/delete, types) with OCSF ingestion mapper, relationships (list/create/delete), and reference data (organizations, labels, marking definitions, external references)." category: threat_intel # Per-instance configuration. The integration talks to the OpenCTI GraphQL API at @@ -74,6 +74,7 @@ commands: - id: observable_delete name: opencti-observable-delete description: "Delete an observable by ID." + risk: destructive inputs_schema: properties: id: { type: string, description: "Observable ID" } @@ -104,6 +105,7 @@ commands: - id: observable_field_remove name: opencti-observable-field-remove description: "Remove a marking definition or label from an observable." + risk: destructive inputs_schema: properties: id: { type: string, description: "Observable ID" } @@ -190,6 +192,7 @@ commands: - id: indicator_field_remove name: opencti-indicator-field-remove description: "Remove a marking definition or label from an indicator." + risk: destructive inputs_schema: properties: id: { type: string, description: "Indicator ID" } @@ -253,6 +256,7 @@ commands: - id: incident_delete name: opencti-incident-delete description: "Delete an incident by ID." + risk: destructive inputs_schema: properties: id: { type: string, description: "Incident ID" } @@ -284,6 +288,7 @@ commands: - id: relationship_delete name: opencti-relationship-delete description: "Delete a relationship by ID." + risk: destructive inputs_schema: properties: id: { type: string, description: "Relationship ID" } diff --git a/integrations/opsgenie/manifest.yaml b/integrations/opsgenie/manifest.yaml index 4da639d..d250e2b 100644 --- a/integrations/opsgenie/manifest.yaml +++ b/integrations/opsgenie/manifest.yaml @@ -1,8 +1,8 @@ id: opsgenie name: Opsgenie -version: 1.0.0 +version: 1.1.0 description: "Atlassian Opsgenie (Alert API v2) — SOC alerting and on-call: create, close, acknowledge, get, and list alerts; add notes and tags; assign, snooze, and delete alerts; and read schedules and on-calls. GenieKey authentication (US/EU regions); stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: alert create/close/acknowledge/get/list, add note/tags, assign, snooze, delete, list schedules, on-calls." +changelog: "1.1.0 — Declare the risk tier on the 8 commands that carried none: 7 safe_write, 1 destructive. An unset risk is read as destructive by the agent approval gate, so the 7 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: alert create/close/acknowledge/get/list, add note/tags, assign, snooze, delete, list schedules, on-calls." category: notification # Per-instance configuration. The API key is sent as 'Authorization: GenieKey '. @@ -24,6 +24,7 @@ commands: - id: create_alert name: opsgenie-create-alert description: "Create a new alert." + risk: safe_write inputs_schema: properties: message: { type: string, description: "Alert message (title)" } @@ -37,6 +38,7 @@ commands: - id: close_alert name: opsgenie-close-alert description: "Close an alert." + risk: safe_write inputs_schema: properties: identifier: { type: string, description: "Alert id, tiny id, or alias" } @@ -47,6 +49,7 @@ commands: - id: acknowledge_alert name: opsgenie-acknowledge-alert description: "Acknowledge an alert." + risk: safe_write inputs_schema: properties: identifier: { type: string, description: "Alert id, tiny id, or alias" } @@ -77,6 +80,7 @@ commands: - id: add_note name: opsgenie-add-note description: "Add a note to an alert." + risk: safe_write inputs_schema: properties: identifier: { type: string, description: "Alert id, tiny id, or alias" } @@ -87,6 +91,7 @@ commands: - id: add_tags name: opsgenie-add-tags description: "Add tags to an alert." + risk: safe_write inputs_schema: properties: identifier: { type: string, description: "Alert id, tiny id, or alias" } @@ -97,6 +102,7 @@ commands: - id: assign_alert name: opsgenie-assign-alert description: "Assign an alert to a user." + risk: safe_write inputs_schema: properties: identifier: { type: string, description: "Alert id, tiny id, or alias" } @@ -107,6 +113,7 @@ commands: - id: snooze_alert name: opsgenie-snooze-alert description: "Snooze an alert until a given time." + risk: safe_write inputs_schema: properties: identifier: { type: string, description: "Alert id, tiny id, or alias" } @@ -117,6 +124,7 @@ commands: - id: delete_alert name: opsgenie-delete-alert description: "Delete an alert." + risk: destructive inputs_schema: properties: identifier: { type: string, description: "Alert id, tiny id, or alias" } diff --git a/integrations/pagerduty/manifest.yaml b/integrations/pagerduty/manifest.yaml index 001d54b..fd3d599 100644 --- a/integrations/pagerduty/manifest.yaml +++ b/integrations/pagerduty/manifest.yaml @@ -1,8 +1,8 @@ id: pagerduty name: PagerDuty -version: 1.0.0 +version: 1.1.0 description: "PagerDuty (Events API v2 + REST API v2) — SOC alerting and on-call: trigger/acknowledge/resolve incidents via the routing key, list and read incidents, add notes, and read on-calls, users, and services. Token + routing-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: trigger/acknowledge/resolve incident, list/get incident, add note, list on-calls/users/services." +changelog: "1.1.0 — Declare the risk tier on the 4 commands that carried none: 4 safe_write. An unset risk is read as destructive by the agent approval gate, so the 4 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: trigger/acknowledge/resolve incident, list/get incident, add note, list on-calls/users/services." category: notification # Per-instance configuration. api_token authenticates the REST API @@ -29,6 +29,7 @@ commands: - id: trigger_incident name: pagerduty-trigger-incident description: "Trigger an incident through the Events API v2. Returns a dedup_key used to acknowledge/resolve it." + risk: safe_write inputs_schema: properties: summary: { type: string, description: "Short incident summary" } @@ -41,6 +42,7 @@ commands: - id: acknowledge_incident name: pagerduty-acknowledge-incident description: "Acknowledge an incident by its dedup_key (Events API v2)." + risk: safe_write inputs_schema: properties: dedup_key: { type: string, description: "The incident dedup_key" } @@ -49,6 +51,7 @@ commands: - id: resolve_incident name: pagerduty-resolve-incident description: "Resolve an incident by its dedup_key (Events API v2)." + risk: safe_write inputs_schema: properties: dedup_key: { type: string, description: "The incident dedup_key" } @@ -79,6 +82,7 @@ commands: - id: add_note name: pagerduty-add-note description: "Add a note to an incident (requires from_email in the configuration)." + risk: safe_write inputs_schema: properties: incident_id: { type: string, description: "Incident ID" } diff --git a/integrations/panos/manifest.yaml b/integrations/panos/manifest.yaml index 5e29027..9b1116f 100644 --- a/integrations/panos/manifest.yaml +++ b/integrations/panos/manifest.yaml @@ -1,8 +1,8 @@ id: panos name: PAN-OS / Panorama -version: 1.0.0 +version: 1.1.0 description: "Palo Alto Networks PAN-OS / Panorama (XML API) — firewall containment: register/unregister IP tags for Dynamic Address Groups (fast block, no commit), create/delete address objects, create/edit custom URL categories, list and refresh External Dynamic Lists, and commit. API-key authentication; stdlib-only, no extra Python dependencies. Targets a firewall vsys." -changelog: "1.0.0 — Initial release: register/unregister IP tag, address create/delete, custom URL category create/edit, EDL list/refresh, commit." +changelog: "1.1.0 — Declare the risk tier on the 8 commands that carried none: 2 safe_write, 6 destructive. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: register/unregister IP tag, address create/delete, custom URL category create/edit, EDL list/refresh, commit." category: network # Per-instance configuration. The API key is sent as the 'key' query parameter. @@ -36,6 +36,7 @@ commands: - id: register_ip_tag name: panos-register-ip-tag description: "Register (tag) an IP address so a Dynamic Address Group matching the tag blocks it immediately — no commit required." + risk: destructive inputs_schema: properties: ip: { type: string, description: "IP address to tag" } @@ -46,6 +47,7 @@ commands: - id: unregister_ip_tag name: panos-unregister-ip-tag description: "Remove tags from an IP address (releases it from tag-based Dynamic Address Groups)." + risk: destructive inputs_schema: properties: ip: { type: string, description: "IP address to untag" } @@ -55,6 +57,7 @@ commands: - id: create_address name: panos-create-address description: "Create an address object (ip-netmask, ip-range, or fqdn)." + risk: safe_write inputs_schema: properties: name: { type: string, description: "Address object name" } @@ -66,6 +69,7 @@ commands: - id: delete_address name: panos-delete-address description: "Delete an address object by name." + risk: destructive inputs_schema: properties: name: { type: string, description: "Address object name" } @@ -74,6 +78,7 @@ commands: - id: create_custom_url_category name: panos-create-custom-url-category description: "Create a custom URL category populated with the given URLs (used by a URL-filtering deny rule)." + risk: safe_write inputs_schema: properties: name: { type: string, description: "Custom URL category name" } @@ -84,6 +89,7 @@ commands: - id: edit_custom_url_category name: panos-edit-custom-url-category description: "Replace the URL list of an existing custom URL category." + risk: destructive inputs_schema: properties: name: { type: string, description: "Custom URL category name" } @@ -101,6 +107,7 @@ commands: - id: refresh_edl name: panos-refresh-edl description: "Force an immediate refresh of an External Dynamic List." + risk: destructive inputs_schema: properties: name: { type: string, description: "External Dynamic List name" } @@ -109,6 +116,7 @@ commands: - id: commit name: panos-commit description: "Commit the candidate configuration." + risk: destructive inputs_schema: properties: description: { type: string, description: "Optional commit description" } diff --git a/integrations/pingone/manifest.yaml b/integrations/pingone/manifest.yaml index 40aabe1..b3aea9b 100644 --- a/integrations/pingone/manifest.yaml +++ b/integrations/pingone/manifest.yaml @@ -1,8 +1,8 @@ id: pingone name: PingOne -version: 1.0.0 +version: 1.1.0 description: "Ping Identity PingOne (Platform API) — identity containment: list and read users, enable/disable a user, and list populations. OAuth2 client-credentials authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get users, enable/disable user, list populations." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list/get users, enable/disable user, list populations." category: identity # Per-instance configuration. Client credentials are exchanged for a token at the @@ -55,6 +55,7 @@ commands: - id: disable_user name: pingone-disable-user description: "Disable a user account (containment)." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User ID" } @@ -63,6 +64,7 @@ commands: - id: enable_user name: pingone-enable-user description: "Enable a user account." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User ID" } diff --git a/integrations/prisma-cloud/manifest.yaml b/integrations/prisma-cloud/manifest.yaml index 711e0b2..7c9aea2 100644 --- a/integrations/prisma-cloud/manifest.yaml +++ b/integrations/prisma-cloud/manifest.yaml @@ -1,8 +1,8 @@ id: prisma_cloud name: Prisma Cloud -version: 1.0.0 +version: 1.1.0 description: "Palo Alto Prisma Cloud (CSPM REST API) — cloud posture: list and read alerts, dismiss alerts, list policies and cloud accounts, and run a config (RQL) search. Access-key login authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get alerts, dismiss alerts, list policies, list cloud accounts, config search." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list/get alerts, dismiss alerts, list policies, list cloud accounts, config search." category: cloud # Per-instance configuration. Each command logs in with the access key ID + @@ -52,6 +52,7 @@ commands: - id: dismiss_alerts name: prisma-dismiss-alerts description: "Dismiss one or more alerts with a note." + risk: safe_write inputs_schema: properties: alert_ids: { type: string, description: "Comma-separated alert IDs" } diff --git a/integrations/pulsedive/manifest.yaml b/integrations/pulsedive/manifest.yaml index fd81924..758e5d1 100644 --- a/integrations/pulsedive/manifest.yaml +++ b/integrations/pulsedive/manifest.yaml @@ -1,8 +1,8 @@ id: pulsedive name: Pulsedive -version: 1.0.0 +version: 1.1.0 description: "Pulsedive (API) — reputation and threat context for any indicator (IP, domain, URL or hash), plus on-demand scanning and scan-result retrieval. API-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: indicator lookup, scan submission and scan-result retrieval." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: indicator lookup, scan submission and scan-result retrieval." category: enrichment config_schema: @@ -27,6 +27,7 @@ commands: - id: scan name: pulsedive-scan description: "Submit an indicator for an on-demand scan. Returns a qid; retrieve the report with pulsedive-scan-result once it finishes." + risk: destructive inputs_schema: properties: value: { type: string, description: "Indicator to scan (IP, domain or URL)" } diff --git a/integrations/qradar/manifest.yaml b/integrations/qradar/manifest.yaml index c320429..c18ac26 100644 --- a/integrations/qradar/manifest.yaml +++ b/integrations/qradar/manifest.yaml @@ -1,8 +1,8 @@ id: qradar name: IBM QRadar -version: 1.0.0 +version: 1.1.0 description: "IBM QRadar (REST API) — SIEM investigation and response: list and read offenses, update/close an offense, list reference sets and add/remove values (block/allow lists used by rules), and list assets. SEC-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get offenses, update offense, list reference sets, add/remove reference-set value, list assets." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none: 1 safe_write, 2 destructive. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list/get offenses, update offense, list reference sets, add/remove reference-set value, list assets." category: siem # Per-instance configuration. The API token is sent as the 'SEC' header. @@ -46,6 +46,7 @@ commands: - id: update_offense name: qradar-update-offense description: "Update an offense (status, assignee, or close with a reason)." + risk: safe_write inputs_schema: properties: offense_id: { type: string, description: "Offense ID" } @@ -65,6 +66,7 @@ commands: - id: add_to_reference_set name: qradar-add-to-reference-set description: "Add a value to a reference set (e.g. a block list consumed by rules)." + risk: destructive inputs_schema: properties: set_name: { type: string, description: "Reference set name" } @@ -74,6 +76,7 @@ commands: - id: delete_from_reference_set name: qradar-delete-from-reference-set description: "Remove a value from a reference set." + risk: destructive inputs_schema: properties: set_name: { type: string, description: "Reference set name" } diff --git a/integrations/qualys/manifest.yaml b/integrations/qualys/manifest.yaml index 4db5193..9ec4b57 100644 --- a/integrations/qualys/manifest.yaml +++ b/integrations/qualys/manifest.yaml @@ -1,8 +1,8 @@ id: qualys name: Qualys VMDR -version: 1.0.0 +version: 1.1.0 description: "Qualys Vulnerability Management (API v2) — asset and vulnerability context: list hosts, list host vulnerability detections, look up vulnerability (QID) knowledge-base details, and list/launch VM scans. HTTP Basic authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: host list, host detections, knowledge-base vulnerability details, scan list, launch scan." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: host list, host detections, knowledge-base vulnerability details, scan list, launch scan." category: vulnerability # Per-instance configuration. HTTP Basic auth against the Qualys API server @@ -68,6 +68,7 @@ commands: - id: launch_scan name: qualys-launch-scan description: "Launch a VM scan against a set of IPs." + risk: destructive inputs_schema: properties: scan_title: { type: string, description: "Title for the scan" } diff --git a/integrations/rapid7-insightvm/manifest.yaml b/integrations/rapid7-insightvm/manifest.yaml index 5e87820..1d33491 100644 --- a/integrations/rapid7-insightvm/manifest.yaml +++ b/integrations/rapid7-insightvm/manifest.yaml @@ -1,8 +1,8 @@ id: rapid7_insightvm name: Rapid7 InsightVM -version: 1.0.0 +version: 1.1.0 description: "Rapid7 InsightVM / Nexpose (Console API v3) — asset and vulnerability context: list and read assets and their vulnerabilities, list and read vulnerability definitions, list sites, start a site scan, and read scan status. HTTP Basic authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get assets, asset vulnerabilities, list/get vulnerabilities, list sites, start site scan, get scan." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list/get assets, asset vulnerabilities, list/get vulnerabilities, list sites, start site scan, get scan." category: vulnerability # Per-instance configuration. HTTP Basic auth against the InsightVM/Nexpose @@ -88,6 +88,7 @@ commands: - id: start_site_scan name: insightvm-start-site-scan description: "Start a scan of a site." + risk: destructive inputs_schema: properties: site_id: { type: string, description: "Site ID" } diff --git a/integrations/rocketchat/manifest.yaml b/integrations/rocketchat/manifest.yaml index 0c8a624..7915297 100644 --- a/integrations/rocketchat/manifest.yaml +++ b/integrations/rocketchat/manifest.yaml @@ -1,8 +1,8 @@ id: rocketchat name: Rocket.Chat -version: 1.0.0 +version: 1.1.0 description: "Rocket.Chat (REST API v1) — SOC ChatOps: post messages, get channel info, list channels, create channels, and look up users. Auth-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: post message, get channel info, list channels, create channel, get user." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 2 safe_write. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: post message, get channel info, list channels, create channel, get user." category: notification # Per-instance configuration. Auth uses the 'X-Auth-Token' and 'X-User-Id' headers. @@ -27,6 +27,7 @@ commands: - id: post_message name: rocketchat-post-message description: "Post a message to a channel or user." + risk: safe_write inputs_schema: properties: channel: { type: string, description: "Channel (#name) or user (@name) or room ID" } @@ -54,6 +55,7 @@ commands: - id: create_channel name: rocketchat-create-channel description: "Create a channel." + risk: safe_write inputs_schema: properties: name: { type: string, description: "Channel name" } diff --git a/integrations/sailpoint/manifest.yaml b/integrations/sailpoint/manifest.yaml index 2f0f0dd..baf3b65 100644 --- a/integrations/sailpoint/manifest.yaml +++ b/integrations/sailpoint/manifest.yaml @@ -1,8 +1,8 @@ id: sailpoint name: SailPoint IdentityNow -version: 1.0.0 +version: 1.1.0 description: "SailPoint IdentityNow (API v3) — identity governance and containment: list and read identities, list accounts, and disable/enable an account. OAuth2 client-credentials authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get identities, list accounts, disable/enable account." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list/get identities, list accounts, disable/enable account." category: identity # Per-instance configuration. Client credentials are exchanged for a bearer @@ -57,6 +57,7 @@ commands: - id: disable_account name: sailpoint-disable-account description: "Disable an account (containment)." + risk: destructive inputs_schema: properties: account_id: { type: string, description: "Account ID" } @@ -65,6 +66,7 @@ commands: - id: enable_account name: sailpoint-enable-account description: "Enable an account." + risk: destructive inputs_schema: properties: account_id: { type: string, description: "Account ID" } diff --git a/integrations/sekoia-xdr/manifest.yaml b/integrations/sekoia-xdr/manifest.yaml index 37055f1..ffe68e3 100644 --- a/integrations/sekoia-xdr/manifest.yaml +++ b/integrations/sekoia-xdr/manifest.yaml @@ -1,8 +1,8 @@ id: sekoia_xdr name: Sekoia XDR -version: 1.0.0 +version: 1.1.0 description: "Sekoia Defend (XDR) REST API — alert ingestion and lifecycle (list/get/search, status workflow, comments), event search jobs (create/status/results + one-shot search), cases, asset management (get/list, attributes/keys add/remove), users, kill chains and a generic authenticated HTTP passthrough." -changelog: "1.0.0 — Initial release: alert ingestion (list_alerts) with an exhaustive OCSF mapper, 20 commands across alerts, event search, cases, assets, users and kill chains." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: alert ingestion (list_alerts) with an exhaustive OCSF mapper, 20 commands across alerts, event search, cases, assets, users and kill chains." category: siem # Per-instance configuration. The API host defaults to the EU region; an @@ -254,6 +254,7 @@ commands: - id: http_request name: sekoia-xdr-http-request description: "Perform an authenticated HTTP request to the Sekoia API. Advanced escape hatch for endpoints without a dedicated command." + risk: destructive inputs_schema: properties: method: { type: string, description: "HTTP method (GET, POST, PUT, PATCH, DELETE). Default GET." } diff --git a/integrations/servicenow-cmdb/manifest.yaml b/integrations/servicenow-cmdb/manifest.yaml index 0d07455..0c12ae7 100644 --- a/integrations/servicenow-cmdb/manifest.yaml +++ b/integrations/servicenow-cmdb/manifest.yaml @@ -1,8 +1,8 @@ id: servicenow_cmdb name: ServiceNow CMDB -version: 1.0.0 +version: 1.1.0 description: "ServiceNow CMDB (CMDB Instance API) — query configuration items by CI class, read a record with its attributes and inbound/outbound relations, create and update records with attributes and relations, and add or delete relations between CIs. Basic or OAuth 2.0 (password grant) authentication." -changelog: "1.0.0 — Initial release: records list by class, record get by sys_id (attributes + relations), record create/update with attributes and discovery source, add/delete relations." +changelog: "1.1.0 — Declare the risk tier on the 4 commands that carried none: 3 safe_write, 1 destructive. An unset risk is read as destructive by the agent approval gate, so the 3 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: records list by class, record get by sys_id (attributes + relations), record create/update with attributes and discovery source, add/delete relations." category: asset_management # Per-instance configuration. The base URL is the instance root, e.g. @@ -80,6 +80,7 @@ commands: - id: create_record name: servicenow-cmdb-create-record description: "Create a CI record with attributes and optional inbound/outbound relations." + risk: safe_write inputs_schema: properties: class: { type: string, description: "CI class name to create the record in" } @@ -95,6 +96,7 @@ commands: - id: update_record name: servicenow-cmdb-update-record description: "Update a CI record's attributes." + risk: safe_write inputs_schema: properties: class: { type: string, description: "CI class name of the record" } @@ -109,6 +111,7 @@ commands: - id: add_relations name: servicenow-cmdb-add-relations description: "Add inbound and/or outbound relations to an existing CI record." + risk: safe_write inputs_schema: properties: class: { type: string, description: "CI class name of the record" } @@ -124,6 +127,7 @@ commands: - id: delete_relation name: servicenow-cmdb-delete-relation description: "Delete a relation from a CI record by the relation's sys_id." + risk: destructive inputs_schema: properties: class: { type: string, description: "CI class name of the record" } diff --git a/integrations/servicenow-iam/manifest.yaml b/integrations/servicenow-iam/manifest.yaml index 18778d3..3b5b80c 100644 --- a/integrations/servicenow-iam/manifest.yaml +++ b/integrations/servicenow-iam/manifest.yaml @@ -1,8 +1,8 @@ id: servicenow_iam name: ServiceNow IAM -version: 1.0.0 +version: 1.1.0 description: "ServiceNow identity lifecycle (sys_user table) — look up, create and update employee accounts, enable/disable accounts (with lock-out clearing), and discover the available user fields for mapping. Basic or OAuth 2.0 (password grant) authentication." -changelog: "1.0.0 — Initial release: get/create/update user, enable/disable user, user field discovery via sys_dictionary." +changelog: "1.1.0 — Declare the risk tier on the 4 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: get/create/update user, enable/disable user, user field discovery via sys_dictionary." category: identity # Per-instance configuration. The base URL is the instance root, e.g. @@ -65,6 +65,7 @@ commands: - id: create_user name: servicenow-iam-create-user description: "Create a user account. Common fields have named inputs; anything else goes through fields/custom_fields." + risk: destructive inputs_schema: properties: user_name: { type: string, description: "Username (user_name field)" } @@ -84,6 +85,7 @@ commands: - id: update_user name: servicenow-iam-update-user description: "Update a user account resolved by sys_id, username or email." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User sys_id" } @@ -103,6 +105,7 @@ commands: - id: enable_user name: servicenow-iam-enable-user description: "Enable a user account (sets active=true and clears locked_out), resolved by sys_id, username or email." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User sys_id" } @@ -113,6 +116,7 @@ commands: - id: disable_user name: servicenow-iam-disable-user description: "Disable a user account (sets active=false), resolved by sys_id, username or email." + risk: destructive inputs_schema: properties: user_id: { type: string, description: "User sys_id" } diff --git a/integrations/servicenow/manifest.yaml b/integrations/servicenow/manifest.yaml index a31ba8a..7a0db21 100644 --- a/integrations/servicenow/manifest.yaml +++ b/integrations/servicenow/manifest.yaml @@ -1,8 +1,8 @@ id: servicenow name: ServiceNow -version: 1.0.0 +version: 1.1.0 description: "ServiceNow ITSM (Table / Service Catalog / Change Management REST APIs) — ticket lifecycle (create/update/resolve/delete, comments, work notes, links, tags, journal notes), generic table records CRUD, CMDB and user/group queries, service catalog ordering, standard change creation, attachments, work-item queue routing, plus ticket ingestion (get_incidents) with an OCSF mapper. Basic or OAuth 2.0 (password grant) authentication." -changelog: "1.0.0 — Initial release: ticket lifecycle commands (incident, problem, change_request, sc_request, sc_task, sc_req_item), records/table CRUD and discovery, CMDB computer/group/user queries, service catalog (search, details, order), standard change from template + change tasks, attachments (list/upload/delete), queue routing, generic API call, and ticket ingestion with a bundled OCSF mapper." +changelog: "1.1.0 — Declare the risk tier on the 15 commands that carried none: 9 safe_write, 6 destructive. An unset risk is read as destructive by the agent approval gate, so the 9 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: ticket lifecycle commands (incident, problem, change_request, sc_request, sc_task, sc_req_item), records/table CRUD and discovery, CMDB computer/group/user queries, service catalog (search, details, order), standard change from template + change tasks, attachments (list/upload/delete), queue routing, generic API call, and ticket ingestion with a bundled OCSF mapper." category: ticketing # Per-instance configuration. The base URL is the instance root, e.g. @@ -91,6 +91,7 @@ commands: - id: create_ticket name: servicenow-create-ticket description: "Create a ticket. Common fields have named inputs; anything else goes through fields/custom_fields." + risk: safe_write inputs_schema: properties: ticket_type: { type: string, description: "Ticket table (default from instance config)" } @@ -115,6 +116,7 @@ commands: - id: update_ticket name: servicenow-update-ticket description: "Update a ticket by sys_id (state changes, reassignment, resolution fields, any field via fields/custom_fields)." + risk: safe_write inputs_schema: properties: id: { type: string, description: "Ticket sys_id to update" } @@ -142,6 +144,7 @@ commands: - id: delete_ticket name: servicenow-delete-ticket description: "Delete a ticket by sys_id." + risk: destructive inputs_schema: properties: id: { type: string, description: "Ticket sys_id to delete" } @@ -165,6 +168,7 @@ commands: - id: add_comment name: servicenow-add-comment description: "Add a customer-visible comment or an internal work note to a ticket." + risk: safe_write inputs_schema: properties: id: { type: string, description: "Ticket sys_id" } @@ -176,6 +180,7 @@ commands: - id: add_link name: servicenow-add-link description: "Post a clickable link (with optional text) into a ticket's comments or work notes." + risk: safe_write inputs_schema: properties: id: { type: string, description: "Ticket sys_id" } @@ -188,6 +193,7 @@ commands: - id: add_tag name: servicenow-add-tag description: "Attach an existing tag (label) to a ticket via the label_entry table." + risk: safe_write inputs_schema: properties: id: { type: string, description: "Ticket sys_id" } @@ -219,6 +225,7 @@ commands: - id: upload_file name: servicenow-upload-file description: "Attach a file to a record (content provided as base64)." + risk: safe_write inputs_schema: properties: id: { type: string, description: "Record sys_id to attach the file to" } @@ -230,6 +237,7 @@ commands: - id: delete_file name: servicenow-delete-file description: "Delete an attachment by its attachment sys_id." + risk: destructive inputs_schema: properties: file_sys_id: { type: string, description: "Attachment sys_id (from servicenow-get-ticket-attachments)" } @@ -252,6 +260,7 @@ commands: - id: create_record name: servicenow-create-record description: "Create a record in any table." + risk: destructive inputs_schema: properties: table_name: { type: string, description: "Table name" } @@ -263,6 +272,7 @@ commands: - id: update_record name: servicenow-update-record description: "Update a record in any table by sys_id." + risk: destructive inputs_schema: properties: table_name: { type: string, description: "Table name" } @@ -275,6 +285,7 @@ commands: - id: delete_record name: servicenow-delete-record description: "Delete a record from any table by sys_id." + risk: destructive inputs_schema: properties: table_name: { type: string, description: "Table name" } @@ -381,6 +392,7 @@ commands: - id: create_item_order name: servicenow-create-item-order description: "Order a catalog item (order_now). Mandatory item variables must be provided." + risk: safe_write inputs_schema: properties: id: { type: string, description: "Catalog item sys_id" } @@ -393,6 +405,7 @@ commands: - id: create_change_from_template name: servicenow-create-change-from-template description: "Create a standard change request from a standard change template (Change Management API)." + risk: safe_write inputs_schema: properties: template: { type: string, description: "Standard change template sys_id" } @@ -412,6 +425,7 @@ commands: - id: document_route_to_queue name: servicenow-document-route-to-queue description: "Route a document (ticket/record) to an Advanced Work Assignment queue." + risk: safe_write inputs_schema: properties: queue_id: { type: string, description: "Queue sys_id (awa_queue table)" } @@ -422,6 +436,7 @@ commands: - id: generic_api_call name: servicenow-generic-api-call description: "Call any instance REST endpoint (path relative to the instance URL, e.g. /api/now/table/incident)." + risk: destructive inputs_schema: properties: method: { type: string, description: "HTTP method: GET, POST, PATCH, PUT or DELETE" } diff --git a/integrations/signalsciences/manifest.yaml b/integrations/signalsciences/manifest.yaml index a9009d6..e8abe46 100644 --- a/integrations/signalsciences/manifest.yaml +++ b/integrations/signalsciences/manifest.yaml @@ -1,8 +1,8 @@ id: signalsciences name: Signal Sciences -version: 1.0.0 +version: 1.1.0 description: "Signal Sciences (Fastly NGWAF, API v0) — web-attack visibility and containment: list sites, read suspicious IPs and events, and add an IP to a site list (block). API-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list sites, get suspicious IPs, list events, add IP to list." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list sites, get suspicious IPs, list events, add IP to list." category: network # Per-instance configuration. Auth headers 'x-api-user' (email) and 'x-api-token'. @@ -54,6 +54,7 @@ commands: - id: add_ip_to_list name: sigsci-add-ip-to-list description: "Add an IP to a site custom list (e.g. a block list)." + risk: destructive inputs_schema: properties: site_name: { type: string, description: "Site short name" } diff --git a/integrations/slack/manifest.yaml b/integrations/slack/manifest.yaml index 8c07d1f..c8b70b4 100644 --- a/integrations/slack/manifest.yaml +++ b/integrations/slack/manifest.yaml @@ -1,8 +1,8 @@ id: slack name: Slack -version: 1.0.0 +version: 1.1.0 description: "Slack (Web API) — SOC notification and ChatOps: post messages (text or Block Kit), list/create channels, invite users, set channel topics, look up users, and add reactions. Bot-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: send message, list/create channel, invite to channel, set topic, get user, add reaction." +changelog: "1.1.0 — Declare the risk tier on the 5 commands that carried none: 5 safe_write. An unset risk is read as destructive by the agent approval gate, so the 5 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: send message, list/create channel, invite to channel, set topic, get user, add reaction." category: notification # Per-instance configuration. The bot token (xoxb-...) is sent as @@ -21,6 +21,7 @@ commands: - id: send_message name: slack-send-message description: "Post a message to a channel or user (text and/or Block Kit blocks)." + risk: safe_write inputs_schema: properties: channel: { type: string, description: "Channel ID, channel name (#alerts), or user ID for a DM" } @@ -42,6 +43,7 @@ commands: - id: create_channel name: slack-create-channel description: "Create a new channel." + risk: safe_write inputs_schema: properties: name: { type: string, description: "Channel name (lowercase, no spaces)" } @@ -51,6 +53,7 @@ commands: - id: invite_to_channel name: slack-invite-to-channel description: "Invite one or more users to a channel." + risk: safe_write inputs_schema: properties: channel: { type: string, description: "Channel ID" } @@ -60,6 +63,7 @@ commands: - id: set_channel_topic name: slack-set-channel-topic description: "Set a channel's topic." + risk: safe_write inputs_schema: properties: channel: { type: string, description: "Channel ID" } @@ -79,6 +83,7 @@ commands: - id: add_reaction name: slack-add-reaction description: "Add an emoji reaction to a message." + risk: safe_write inputs_schema: properties: channel: { type: string, description: "Channel ID of the message" } diff --git a/integrations/sophos-central/manifest.yaml b/integrations/sophos-central/manifest.yaml index 7dd12ba..6d18308 100644 --- a/integrations/sophos-central/manifest.yaml +++ b/integrations/sophos-central/manifest.yaml @@ -1,8 +1,8 @@ id: sophos_central name: Sophos Central -version: 1.0.0 +version: 1.1.0 description: "Sophos Central (Endpoint API) — endpoint containment: list and read endpoints, isolate/de-isolate a host, trigger a scan, and list alerts. OAuth2 client-credentials authentication (with tenant discovery); stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get endpoints, isolate/de-isolate, scan, list alerts." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none: 1 safe_write, 2 destructive. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list/get endpoints, isolate/de-isolate, scan, list alerts." category: endpoint # Per-instance configuration. Client credentials are exchanged for a token; the @@ -42,6 +42,7 @@ commands: - id: isolate_endpoint name: sophos-isolate-endpoint description: "Isolate an endpoint from the network (containment)." + risk: destructive inputs_schema: properties: endpoint_id: { type: string, description: "Endpoint ID" } @@ -51,6 +52,7 @@ commands: - id: deisolate_endpoint name: sophos-deisolate-endpoint description: "Remove an endpoint from isolation." + risk: destructive inputs_schema: properties: endpoint_id: { type: string, description: "Endpoint ID" } @@ -60,6 +62,7 @@ commands: - id: scan_endpoint name: sophos-scan-endpoint description: "Trigger a malware scan on an endpoint." + risk: safe_write inputs_schema: properties: endpoint_id: { type: string, description: "Endpoint ID" } diff --git a/integrations/splunk/manifest.yaml b/integrations/splunk/manifest.yaml index ada552a..1aec073 100644 --- a/integrations/splunk/manifest.yaml +++ b/integrations/splunk/manifest.yaml @@ -1,8 +1,8 @@ id: splunk name: Splunk -version: 1.1.0 +version: 1.2.0 description: "Splunk (REST API, management port 8089) — run SPL searches with notable/CIM finding ingestion and an OCSF mapper, manage search jobs, indexes and event submission (incl. HEC), full KV Store collection/entry management, and user administration. Token or basic authentication." -changelog: "1.1.0 — Full coverage: search jobs (create/status/results), indexes listing, event submission (receivers/simple + HEC), and the complete KV Store command set (collection create/config/delete, list, data list/add/delete, entry search/delete/update). 1.0.0 — Initial release: SPL search (oneshot) ingestion with a bundled OCSF mapper for notable/CIM events, get_users, delete_user and a KV Store entry update." +changelog: "1.2.0 — Declare the risk tier on the 10 commands that carried none: 6 safe_write, 4 destructive. An unset risk is read as destructive by the agent approval gate, so the 6 that only annotate sat behind the same prompt as the ones that change the estate. | 1.1.0 — Full coverage: search jobs (create/status/results), indexes listing, event submission (receivers/simple + HEC), and the complete KV Store command set (collection create/config/delete, list, data list/add/delete, entry search/delete/update). 1.0.0 — Initial release: SPL search (oneshot) ingestion with a bundled OCSF mapper for notable/CIM events, get_users, delete_user and a KV Store entry update." category: siem # Per-instance configuration. The REST API lives on the Splunk management port (default 8089), @@ -123,6 +123,7 @@ commands: - id: submit_event name: splunk-submit-event description: "Submit a single event to an index via the REST receivers/simple endpoint." + risk: safe_write inputs_schema: properties: index: { type: string, description: "Target index name" } @@ -135,6 +136,7 @@ commands: - id: submit_event_hec name: splunk-submit-event-hec description: "Submit an event through the HTTP Event Collector (HEC). Requires hec_url and hec_token in the instance config." + risk: safe_write inputs_schema: properties: event: { type: string, description: "Event payload (string or JSON object as a string)" } @@ -158,6 +160,7 @@ commands: - id: delete_user name: splunk-delete-user description: "Delete a Splunk user by username." + risk: destructive inputs_schema: properties: username: { type: string, description: "Username to delete" } @@ -177,6 +180,7 @@ commands: - id: kv_store_collection_create name: splunk-kv-store-collection-create description: "Create a new KV Store collection in an app." + risk: safe_write inputs_schema: properties: app_name: { type: string, description: "App namespace (defaults to the instance 'app' config)" } @@ -186,6 +190,7 @@ commands: - id: kv_store_collection_config name: splunk-kv-store-collection-config description: "Define field types on a KV Store collection (e.g. field.name=string). Pass a JSON object mapping field name to type." + risk: safe_write inputs_schema: properties: app_name: { type: string, description: "App namespace (defaults to the instance 'app' config)" } @@ -196,6 +201,7 @@ commands: - id: kv_store_collection_delete name: splunk-kv-store-collection-delete description: "Delete a KV Store collection and all of its data." + risk: destructive inputs_schema: properties: app_name: { type: string, description: "App namespace (defaults to the instance 'app' config)" } @@ -207,6 +213,7 @@ commands: - id: kv_store_collection_add_entries name: splunk-kv-store-collection-add-entries description: "Insert one or more entries into a KV Store collection (batch_save). Pass a JSON array of objects." + risk: safe_write inputs_schema: properties: app_name: { type: string, description: "App namespace (defaults to the instance 'app' config)" } @@ -228,6 +235,7 @@ commands: - id: kv_store_collection_data_delete name: splunk-kv-store-collection-data-delete description: "Delete ALL entries in a KV Store collection (the collection itself is kept)." + risk: destructive inputs_schema: properties: app_name: { type: string, description: "App namespace (defaults to the instance 'app' config)" } @@ -248,6 +256,7 @@ commands: - id: kv_store_collection_delete_entry name: splunk-kv-store-collection-delete-entry description: "Delete entries in a KV Store collection matching a Mongo-style query (JSON object)." + risk: destructive inputs_schema: properties: app_name: { type: string, description: "App namespace (defaults to the instance 'app' config)" } @@ -258,6 +267,7 @@ commands: - id: kv_store_update_entry name: splunk-kv-store-update-entry description: "Update a single field of an existing KV Store entry by key, preserving the other fields." + risk: safe_write inputs_schema: properties: app_name: { type: string, description: "App namespace (defaults to the instance 'app' config)" } diff --git a/integrations/stormshield/manifest.yaml b/integrations/stormshield/manifest.yaml index db9bb7a..c1c3e5e 100644 --- a/integrations/stormshield/manifest.yaml +++ b/integrations/stormshield/manifest.yaml @@ -1,8 +1,8 @@ id: stormshield name: Stormshield Network Security -version: 1.0.0 +version: 1.1.0 description: "Stormshield Network Security (SNS API) — firewall containment: authenticate, add or remove an IP from a block host-group object, and run a monitor query. Session-based authentication; stdlib-only, no extra Python dependencies. (French vendor.)" -changelog: "1.0.0 — Initial release: add/remove block-group member, list host objects, monitor query." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: add/remove block-group member, list host objects, monitor query." category: network # Per-instance configuration. Each command logs in (POST /api/auth/login) and @@ -32,6 +32,7 @@ commands: - id: add_block_group_member name: stormshield-add-block-group-member description: "Add an IP/host object to a block host-group (referenced by a filter rule)." + risk: destructive inputs_schema: properties: group: { type: string, description: "Host-group object name (e.g. RIPOSTE_BLOCK)" } @@ -41,6 +42,7 @@ commands: - id: remove_block_group_member name: stormshield-remove-block-group-member description: "Remove a host from a block host-group." + risk: destructive inputs_schema: properties: group: { type: string, description: "Host-group object name" } diff --git a/integrations/symantec-dlp/manifest.yaml b/integrations/symantec-dlp/manifest.yaml index 4715cbe..f3e0b6e 100644 --- a/integrations/symantec-dlp/manifest.yaml +++ b/integrations/symantec-dlp/manifest.yaml @@ -1,8 +1,8 @@ id: symantec_dlp name: Symantec DLP -version: 1.0.0 +version: 1.1.0 description: "Symantec DLP (Enforce Server REST API v2) — data-loss-prevention incident handling: list incidents, read an incident and its history, and update incident status/severity. OAuth2 password-grant authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get incidents, get incident history, update incident." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list/get incidents, get incident history, update incident." category: dlp # Per-instance configuration. The username/password are exchanged (OAuth2 @@ -60,6 +60,7 @@ commands: - id: update_incident name: symantec-dlp-update-incident description: "Update an incident's status and/or severity." + risk: safe_write inputs_schema: properties: incident_id: { type: string, description: "Incident ID" } diff --git a/integrations/tehtris/manifest.yaml b/integrations/tehtris/manifest.yaml index a58cbb6..7a12ad1 100644 --- a/integrations/tehtris/manifest.yaml +++ b/integrations/tehtris/manifest.yaml @@ -1,8 +1,8 @@ id: tehtris name: TEHTRIS XDR -version: 1.0.0 +version: 1.1.0 description: "TEHTRIS XDR Platform — endpoint detection and response: list and read alerts, list agents, and isolate an agent (containment). Bearer-token authentication; stdlib-only, no extra Python dependencies. (French vendor. NOTE: exact API paths are best-effort — verify against the TEHTRIS API documentation before production use.)" -changelog: "1.0.0 — Initial release: list/get alerts, list agents, isolate agent." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list/get alerts, list agents, isolate agent." category: endpoint # Per-instance configuration. Auth header 'Authorization: Bearer '. @@ -50,6 +50,7 @@ commands: - id: isolate_agent name: tehtris-isolate-agent description: "Isolate an endpoint agent from the network (containment)." + risk: destructive inputs_schema: properties: agent_id: { type: string, description: "Agent ID" } diff --git a/integrations/telegram/manifest.yaml b/integrations/telegram/manifest.yaml index e443bc4..0797253 100644 --- a/integrations/telegram/manifest.yaml +++ b/integrations/telegram/manifest.yaml @@ -1,8 +1,8 @@ id: telegram name: Telegram -version: 1.0.0 +version: 1.1.0 description: "Telegram Bot API — SOC alerting via a bot: send text messages and photos to a chat, read chat info, and poll updates. Bot-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: send message, send photo, get chat, get updates." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 2 safe_write. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: send message, send photo, get chat, get updates." category: notification # Per-instance configuration. The bot token is placed in the API path @@ -23,6 +23,7 @@ commands: - id: send_message name: telegram-send-message description: "Send a text message to a chat." + risk: safe_write inputs_schema: properties: chat_id: { type: string, description: "Chat ID (overrides the configured default)" } @@ -33,6 +34,7 @@ commands: - id: send_photo name: telegram-send-photo description: "Send a photo (by URL) to a chat." + risk: safe_write inputs_schema: properties: chat_id: { type: string, description: "Chat ID (overrides the configured default)" } diff --git a/integrations/tenable-io/manifest.yaml b/integrations/tenable-io/manifest.yaml index edc6e58..45dba45 100644 --- a/integrations/tenable-io/manifest.yaml +++ b/integrations/tenable-io/manifest.yaml @@ -1,8 +1,8 @@ id: tenable_io name: Tenable Vulnerability Management -version: 1.0.0 +version: 1.1.0 description: "Tenable Vulnerability Management (Tenable.io API) — asset and vulnerability context for incidents: list and read assets, list vulnerabilities and per-asset vulnerabilities, read vulnerability (plugin) details, and list/launch/status scans. API-key (access/secret) authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get assets, list vulnerabilities, per-asset vulnerabilities, vulnerability details, list scans, scan status, launch scan." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list/get assets, list vulnerabilities, per-asset vulnerabilities, vulnerability details, list scans, scan status, launch scan." category: vulnerability # Per-instance configuration. Keys are sent as @@ -90,6 +90,7 @@ commands: - id: launch_scan name: tenable-launch-scan description: "Launch a scan." + risk: destructive inputs_schema: properties: scan_id: { type: string, description: "Scan ID to launch" } diff --git a/integrations/thehive/manifest.yaml b/integrations/thehive/manifest.yaml index 5ffc927..990ad8a 100644 --- a/integrations/thehive/manifest.yaml +++ b/integrations/thehive/manifest.yaml @@ -1,8 +1,8 @@ id: thehive name: TheHive -version: 1.0.0 +version: 1.1.0 description: "TheHive (case-management API v1) — SOC case handling: create/read/update/search cases, create tasks, create and read alerts, promote an alert to a case, and add observables. Bearer (API key) authentication; stdlib-only, no extra Python dependencies. Targets TheHive 5." -changelog: "1.0.0 — Initial release: case create/get/update/search, create task, alert create/get/promote, add observable." +changelog: "1.1.0 — Declare the risk tier on the 6 commands that carried none: 6 safe_write. An unset risk is read as destructive by the agent approval gate, so the 6 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: case create/get/update/search, create task, alert create/get/promote, add observable." category: case_management # Per-instance configuration. The API key is sent as 'Authorization: Bearer '. @@ -23,6 +23,7 @@ commands: - id: create_case name: thehive-create-case description: "Create a case." + risk: safe_write inputs_schema: properties: title: { type: string, description: "Case title" } @@ -44,6 +45,7 @@ commands: - id: update_case name: thehive-update-case description: "Update a case (status, severity, or assignee)." + risk: safe_write inputs_schema: properties: case_id: { type: string, description: "Case ID" } @@ -65,6 +67,7 @@ commands: - id: create_task name: thehive-create-task description: "Add a task to a case." + risk: safe_write inputs_schema: properties: case_id: { type: string, description: "Case ID" } @@ -75,6 +78,7 @@ commands: - id: create_alert name: thehive-create-alert description: "Create an alert." + risk: safe_write inputs_schema: properties: title: { type: string, description: "Alert title" } @@ -97,6 +101,7 @@ commands: - id: promote_alert name: thehive-promote-alert description: "Promote an alert to a case." + risk: safe_write inputs_schema: properties: alert_id: { type: string, description: "Alert ID" } @@ -105,6 +110,7 @@ commands: - id: add_observable name: thehive-add-observable description: "Add an observable to a case." + risk: safe_write inputs_schema: properties: case_id: { type: string, description: "Case ID" } diff --git a/integrations/thinkst-canary/manifest.yaml b/integrations/thinkst-canary/manifest.yaml index 6542e6c..6a7b7e3 100644 --- a/integrations/thinkst-canary/manifest.yaml +++ b/integrations/thinkst-canary/manifest.yaml @@ -1,8 +1,8 @@ id: thinkst_canary name: Thinkst Canary -version: 1.0.0 +version: 1.1.0 description: "Thinkst Canary (Console API v1) — deception/honeypot alerting: list and read incidents, acknowledge an incident, and list Canary devices. API-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get incidents, acknowledge incident, list devices." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list/get incidents, acknowledge incident, list devices." category: endpoint # Per-instance configuration. The auth token is sent as a request parameter; the @@ -42,6 +42,7 @@ commands: - id: acknowledge_incident name: canary-acknowledge-incident description: "Acknowledge an incident." + risk: safe_write inputs_schema: properties: incident_id: { type: string, description: "Incident node/key ID" } diff --git a/integrations/threatconnect/manifest.yaml b/integrations/threatconnect/manifest.yaml index f0195d7..db66c1d 100644 --- a/integrations/threatconnect/manifest.yaml +++ b/integrations/threatconnect/manifest.yaml @@ -1,8 +1,8 @@ id: threatconnect name: ThreatConnect -version: 1.0.0 +version: 1.1.0 description: "ThreatConnect (API v3) — threat intelligence: query and read indicators and groups (TQL), create and delete indicators, create groups, and tag indicators. HMAC-SHA256 signed authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get/create/delete indicators, list/get/create groups, add indicator tag." +changelog: "1.1.0 — Declare the risk tier on the 4 commands that carried none: 3 safe_write, 1 destructive. An unset risk is read as destructive by the agent approval gate, so the 3 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list/get/create/delete indicators, list/get/create groups, add indicator tag." category: threat_intel # Per-instance configuration. Requests are signed with HMAC-SHA256 using the @@ -47,6 +47,7 @@ commands: - id: create_indicator name: tc-create-indicator description: "Create an indicator (e.g. Address, Host, File, URL, EmailAddress)." + risk: safe_write inputs_schema: properties: type: { type: string, description: "Indicator type: Address, Host, File, URL, or EmailAddress" } @@ -59,6 +60,7 @@ commands: - id: delete_indicator name: tc-delete-indicator description: "Delete an indicator by ID." + risk: destructive inputs_schema: properties: indicator_id: { type: string, description: "Indicator ID" } @@ -86,6 +88,7 @@ commands: - id: create_group name: tc-create-group description: "Create a group (Incident, Threat, Campaign, Adversary, ...)." + risk: safe_write inputs_schema: properties: type: { type: string, description: "Group type: Incident, Threat, Campaign, Adversary, Document, ..." } @@ -96,6 +99,7 @@ commands: - id: add_indicator_tag name: tc-add-indicator-tag description: "Add a tag to an indicator." + risk: safe_write inputs_schema: properties: indicator_id: { type: string, description: "Indicator ID" } diff --git a/integrations/threatq/manifest.yaml b/integrations/threatq/manifest.yaml index 3482934..bab0116 100644 --- a/integrations/threatq/manifest.yaml +++ b/integrations/threatq/manifest.yaml @@ -1,8 +1,8 @@ id: threatq name: ThreatQ -version: 1.0.0 +version: 1.1.0 description: "ThreatQuotient ThreatQ (REST API) — threat intelligence: search and read indicators, create an indicator, and list events. OAuth2 password-grant authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: search/get indicators, create indicator, list events." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: search/get indicators, create indicator, list events." category: threat_intel # Per-instance configuration. Credentials are exchanged for a bearer token at @@ -51,6 +51,7 @@ commands: - id: create_indicator name: threatq-create-indicator description: "Create an indicator." + risk: safe_write inputs_schema: properties: value: { type: string, description: "Indicator value" } diff --git a/integrations/trend-vision-one/manifest.yaml b/integrations/trend-vision-one/manifest.yaml index 1c2fd9d..c02dbc7 100644 --- a/integrations/trend-vision-one/manifest.yaml +++ b/integrations/trend-vision-one/manifest.yaml @@ -1,8 +1,8 @@ id: trend_vision_one name: Trend Vision One -version: 1.0.0 +version: 1.1.0 description: "Trend Micro Vision One (XDR, API v3.0) — endpoint containment and threat response: list endpoints, isolate/restore an endpoint, terminate a process, list and read Workbench alerts, and add/remove suspicious objects (block hash/URL/IP/domain). Bearer-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list endpoints, isolate/restore endpoint, terminate process, list/get Workbench alerts, add/remove suspicious object." +changelog: "1.1.0 — Declare the risk tier on the 5 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: list endpoints, isolate/restore endpoint, terminate process, list/get Workbench alerts, add/remove suspicious object." category: endpoint # Per-instance configuration. The API token is sent as 'Authorization: Bearer '. @@ -34,6 +34,7 @@ commands: - id: isolate_endpoint name: tmv1-isolate-endpoint description: "Isolate an endpoint from the network (containment)." + risk: destructive inputs_schema: properties: endpoint_name: { type: string, description: "Endpoint hostname (provide this or agent_guid)" } @@ -44,6 +45,7 @@ commands: - id: restore_endpoint name: tmv1-restore-endpoint description: "Restore (un-isolate) an endpoint's network connection." + risk: destructive inputs_schema: properties: endpoint_name: { type: string, description: "Endpoint hostname (provide this or agent_guid)" } @@ -54,6 +56,7 @@ commands: - id: terminate_process name: tmv1-terminate-process description: "Terminate a process on an endpoint by file SHA-1." + risk: destructive inputs_schema: properties: endpoint_name: { type: string, description: "Endpoint hostname (provide this or agent_guid)" } @@ -89,6 +92,7 @@ commands: - id: add_to_block_list name: tmv1-add-to-block-list description: "Add a suspicious object (file SHA-1, URL, IP, domain, or sender) to the block list." + risk: destructive inputs_schema: properties: object_type: { type: string, description: "One of: fileSha1, url, ip, domain, senderMailAddress" } @@ -99,6 +103,7 @@ commands: - id: remove_from_block_list name: tmv1-remove-from-block-list description: "Remove a suspicious object from the block list." + risk: destructive inputs_schema: properties: object_type: { type: string, description: "One of: fileSha1, url, ip, domain, senderMailAddress" } diff --git a/integrations/triage/manifest.yaml b/integrations/triage/manifest.yaml index bbb2b4b..c195509 100644 --- a/integrations/triage/manifest.yaml +++ b/integrations/triage/manifest.yaml @@ -1,8 +1,8 @@ id: triage name: Hatching Triage -version: 1.0.0 +version: 1.1.0 description: "Hatching Triage (tria.ge API v0) — dynamic malware analysis: submit files and URLs, read sample status and analysis overview, list samples, and search. Bearer-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: submit file/URL, get sample, get report overview, list samples, search." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 2 safe_write. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: submit file/URL, get sample, get report overview, list samples, search." category: enrichment # Per-instance configuration. The API key is sent as 'Authorization: Bearer '. @@ -23,6 +23,7 @@ commands: - id: submit_file name: triage-submit-file description: "Submit a file (base64) for analysis." + risk: safe_write inputs_schema: properties: file_name: { type: string, description: "File name" } @@ -32,6 +33,7 @@ commands: - id: submit_url name: triage-submit-url description: "Submit a URL for analysis." + risk: safe_write inputs_schema: properties: url: { type: string, description: "URL to detonate" } diff --git a/integrations/twilio/manifest.yaml b/integrations/twilio/manifest.yaml index 2d8b3db..95ac700 100644 --- a/integrations/twilio/manifest.yaml +++ b/integrations/twilio/manifest.yaml @@ -1,8 +1,8 @@ id: twilio name: Twilio -version: 1.0.0 +version: 1.1.0 description: "Twilio (REST API) — SOC out-of-band alerting: send SMS messages, place voice calls, and read message status/history. HTTP Basic authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: send SMS, make call, get/list messages." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 2 safe_write. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: send SMS, make call, get/list messages." category: notification # Per-instance configuration. HTTP Basic auth with the Account SID + Auth Token. @@ -26,6 +26,7 @@ commands: - id: send_sms name: twilio-send-sms description: "Send an SMS message." + risk: safe_write inputs_schema: properties: to: { type: string, description: "Recipient number (E.164)" } @@ -36,6 +37,7 @@ commands: - id: make_call name: twilio-make-call description: "Place a voice call that plays TwiML." + risk: safe_write inputs_schema: properties: to: { type: string, description: "Recipient number (E.164)" } diff --git a/integrations/urlscan/manifest.yaml b/integrations/urlscan/manifest.yaml index 09bb73f..bbd60d5 100644 --- a/integrations/urlscan/manifest.yaml +++ b/integrations/urlscan/manifest.yaml @@ -1,8 +1,8 @@ id: urlscan name: urlscan.io -version: 1.0.0 +version: 1.1.0 description: "urlscan.io (API v1) — submit URLs for scanning, retrieve scan results (verdicts, page metadata, screenshot and DOM references) and search historical scans. API-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: URL submission, result retrieval and historical search." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: URL submission, result retrieval and historical search." category: enrichment config_schema: @@ -18,6 +18,7 @@ commands: - id: submit name: urlscan-submit description: "Submit a URL for scanning. Returns a scan UUID; retrieve the report with urlscan-get-result once the scan finishes (usually ~10-30s)." + risk: safe_write inputs_schema: properties: url: { type: string, description: "URL to scan" } diff --git a/integrations/vade/manifest.yaml b/integrations/vade/manifest.yaml index c0c7691..d3331b7 100644 --- a/integrations/vade/manifest.yaml +++ b/integrations/vade/manifest.yaml @@ -1,8 +1,8 @@ id: vade name: Vade -version: 1.0.0 +version: 1.1.0 description: "Vade (email security API) — anti-phishing remediation: search messages, read a message, and remediate (remove/quarantine) a malicious message. Bearer-token authentication; stdlib-only, no extra Python dependencies. (French vendor. NOTE: exact API paths are best-effort — verify against the Vade API documentation before production use.)" -changelog: "1.0.0 — Initial release: search messages, get message, remediate message." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: search messages, get message, remediate message." category: email # Per-instance configuration. Auth header 'Authorization: Bearer '. @@ -44,6 +44,7 @@ commands: - id: remediate_message name: vade-remediate-message description: "Remediate (remove/quarantine) a malicious message." + risk: destructive inputs_schema: properties: message_id: { type: string, description: "Message ID" } diff --git a/integrations/vault/manifest.yaml b/integrations/vault/manifest.yaml index 1d62e6c..a6bbdf2 100644 --- a/integrations/vault/manifest.yaml +++ b/integrations/vault/manifest.yaml @@ -1,8 +1,8 @@ id: vault name: HashiCorp Vault -version: 1.0.0 +version: 1.1.0 description: "HashiCorp Vault (KV v2 + sys API) — secrets management for playbooks: read, write, delete and list secrets, list mounts, and look up the current token. Vault-token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: read/write/delete/list secrets, list mounts, lookup token." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: read/write/delete/list secrets, list mounts, lookup token." category: cloud # Per-instance configuration. The token is sent as the 'X-Vault-Token' header. @@ -32,6 +32,7 @@ commands: - id: read_secret name: vault-read-secret description: "Read a secret from the KV v2 store." + risk: destructive inputs_schema: properties: path: { type: string, description: "Secret path within the KV mount (e.g. app/db)" } @@ -40,6 +41,7 @@ commands: - id: write_secret name: vault-write-secret description: "Write (create/update) a secret in the KV v2 store." + risk: destructive inputs_schema: properties: path: { type: string, description: "Secret path" } @@ -49,6 +51,7 @@ commands: - id: delete_secret name: vault-delete-secret description: "Delete a secret (all versions/metadata) from the KV v2 store." + risk: destructive inputs_schema: properties: path: { type: string, description: "Secret path" } diff --git a/integrations/vectra/manifest.yaml b/integrations/vectra/manifest.yaml index 8cfc12f..bb27200 100644 --- a/integrations/vectra/manifest.yaml +++ b/integrations/vectra/manifest.yaml @@ -1,8 +1,8 @@ id: vectra name: Vectra AI -version: 1.0.0 +version: 1.1.0 description: "Vectra AI (Detect API v2.3) — network threat detection: list and read detections, mark a detection fixed, add a note, and list/read hosts and accounts. Token authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get detections, mark detection fixed, add note, list/get hosts, list accounts." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 2 safe_write. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list/get detections, mark detection fixed, add note, list/get hosts, list accounts." category: ndr # Per-instance configuration. Auth header 'Authorization: Token '. @@ -47,6 +47,7 @@ commands: - id: mark_detection_fixed name: vectra-mark-detection-fixed description: "Mark one or more detections as fixed." + risk: safe_write inputs_schema: properties: detection_ids: { type: string, description: "Comma-separated detection IDs" } @@ -55,6 +56,7 @@ commands: - id: add_detection_note name: vectra-add-detection-note description: "Add a note to a detection." + risk: safe_write inputs_schema: properties: detection_id: { type: string, description: "Detection ID" } diff --git a/integrations/vmray/manifest.yaml b/integrations/vmray/manifest.yaml index 43f540f..dd476a4 100644 --- a/integrations/vmray/manifest.yaml +++ b/integrations/vmray/manifest.yaml @@ -1,8 +1,8 @@ id: vmray name: VMRay -version: 1.0.0 +version: 1.1.0 description: "VMRay (REST API) — detonate files and URLs in the VMRay sandbox, retrieve samples/submissions/analyses (by ID or hash), and pull IOCs. API-key authentication; stdlib-only, no extra Python dependencies. Works with VMRay Cloud or an on-prem appliance." -changelog: "1.0.0 — Initial release: file/URL submission, sample/submission/analysis retrieval, sample-by-hash lookup and IOCs." +changelog: "1.1.0 — Declare the risk tier on the 2 commands that carried none: 2 safe_write. An unset risk is read as destructive by the agent approval gate, so the 2 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: file/URL submission, sample/submission/analysis retrieval, sample-by-hash lookup and IOCs." category: enrichment # Per-instance configuration. The API key is sent as 'Authorization: api_key '. @@ -23,6 +23,7 @@ commands: - id: upload_sample name: vmray-upload-sample description: "Submit a file (base64) for analysis. Returns submission and sample IDs." + risk: safe_write inputs_schema: properties: file_name: { type: string, description: "File name" } @@ -33,6 +34,7 @@ commands: - id: upload_url name: vmray-upload-url description: "Submit a URL for analysis." + risk: safe_write inputs_schema: properties: url: { type: string, description: "URL to detonate" } diff --git a/integrations/withsecure/manifest.yaml b/integrations/withsecure/manifest.yaml index a4c6c49..2310f7e 100644 --- a/integrations/withsecure/manifest.yaml +++ b/integrations/withsecure/manifest.yaml @@ -1,8 +1,8 @@ id: withsecure name: WithSecure Elements -version: 1.0.0 +version: 1.1.0 description: "WithSecure Elements (Connect API) — endpoint containment: list and read devices, isolate/release a device, trigger a malware scan, and list incidents. OAuth2 client-credentials authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get devices, isolate/release device, scan, list incidents." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none: 1 safe_write, 2 destructive. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list/get devices, isolate/release device, scan, list incidents." category: endpoint # Per-instance configuration. Client credentials are exchanged for a bearer token. @@ -46,6 +46,7 @@ commands: - id: isolate_device name: withsecure-isolate-device description: "Isolate a device from the network (containment)." + risk: destructive inputs_schema: properties: device_id: { type: string, description: "Device ID" } @@ -55,6 +56,7 @@ commands: - id: release_device name: withsecure-release-device description: "Release a device from network isolation." + risk: destructive inputs_schema: properties: device_id: { type: string, description: "Device ID" } @@ -63,6 +65,7 @@ commands: - id: scan_device name: withsecure-scan-device description: "Trigger a malware scan on a device." + risk: safe_write inputs_schema: properties: device_id: { type: string, description: "Device ID" } diff --git a/integrations/wiz/manifest.yaml b/integrations/wiz/manifest.yaml index 57011ef..49e1782 100644 --- a/integrations/wiz/manifest.yaml +++ b/integrations/wiz/manifest.yaml @@ -1,8 +1,8 @@ id: wiz name: Wiz -version: 1.0.0 +version: 1.1.0 description: "Wiz (CNAPP GraphQL API) — cloud security posture: list and read issues, update an issue's status, list vulnerability findings, and search cloud resources. OAuth2 client-credentials authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: list/get issues, update issue status, list vulnerabilities, list cloud resources." +changelog: "1.1.0 — Declare the risk tier on the 1 command that carried none: 1 safe_write. An unset risk is read as destructive by the agent approval gate, so the 1 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: list/get issues, update issue status, list vulnerabilities, list cloud resources." category: cloud # Per-instance configuration. Client credentials are exchanged at the auth URL @@ -52,6 +52,7 @@ commands: - id: update_issue_status name: wiz-update-issue-status description: "Update an issue's status (e.g. resolve or reject)." + risk: safe_write inputs_schema: properties: issue_id: { type: string, description: "Issue ID" } diff --git a/integrations/zendesk/manifest.yaml b/integrations/zendesk/manifest.yaml index e12b1bc..c538768 100644 --- a/integrations/zendesk/manifest.yaml +++ b/integrations/zendesk/manifest.yaml @@ -1,8 +1,8 @@ id: zendesk name: Zendesk -version: 1.0.0 +version: 1.1.0 description: "Zendesk Support (REST API v2) — ticketing: create, read, update and search tickets, add comments (public or internal), and list users. API-token (Basic) authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: create/get/update/search tickets, add comment, list users." +changelog: "1.1.0 — Declare the risk tier on the 3 commands that carried none: 3 safe_write. An unset risk is read as destructive by the agent approval gate, so the 3 that only annotate sat behind the same prompt as the ones that change the estate. | 1.0.0 — Initial release: create/get/update/search tickets, add comment, list users." category: ticketing # Per-instance configuration. Auth is HTTP Basic with '/token:'. @@ -27,6 +27,7 @@ commands: - id: create_ticket name: zendesk-create-ticket description: "Create a ticket." + risk: safe_write inputs_schema: properties: subject: { type: string, description: "Ticket subject" } @@ -49,6 +50,7 @@ commands: - id: update_ticket name: zendesk-update-ticket description: "Update a ticket (status, priority, or assignee)." + risk: safe_write inputs_schema: properties: ticket_id: { type: string, description: "Ticket ID" } @@ -69,6 +71,7 @@ commands: - id: add_comment name: zendesk-add-comment description: "Add a comment to a ticket (public or internal note)." + risk: safe_write inputs_schema: properties: ticket_id: { type: string, description: "Ticket ID" } diff --git a/integrations/zscaler/manifest.yaml b/integrations/zscaler/manifest.yaml index 1848be0..e7196d0 100644 --- a/integrations/zscaler/manifest.yaml +++ b/integrations/zscaler/manifest.yaml @@ -1,8 +1,8 @@ id: zscaler name: Zscaler Internet Access -version: 1.0.0 +version: 1.1.0 description: "Zscaler Internet Access (ZIA REST API) — web-layer containment: block/unblock URLs and IPs (advanced block list), manage the allow list, add URLs to custom categories, read Sandbox reports, and activate configuration changes. Session-based API-key authentication; stdlib-only, no extra Python dependencies." -changelog: "1.0.0 — Initial release: URL/IP block list add/remove, block-list and allow-list read, allow-list add, category URL add, Sandbox report, activate changes." +changelog: "1.1.0 — Declare the risk tier on the 7 commands that carried none, all of them destructive. An unset risk was already gated as destructive, so the approval prompt does not move; what changes is that the tier is a stated decision rather than a default, and a command added later cannot inherit it by omission. | 1.0.0 — Initial release: URL/IP block list add/remove, block-list and allow-list read, allow-list add, category URL add, Sandbox report, activate changes." category: network # Per-instance configuration. Authentication is session-based: each command logs @@ -38,6 +38,7 @@ commands: - id: blacklist_url name: zscaler-blacklist-url description: "Add one or more URLs to the advanced block list." + risk: destructive inputs_schema: properties: urls: { type: string, description: "Comma-separated URLs to block" } @@ -46,6 +47,7 @@ commands: - id: undo_blacklist_url name: zscaler-undo-blacklist-url description: "Remove one or more URLs from the advanced block list." + risk: destructive inputs_schema: properties: urls: { type: string, description: "Comma-separated URLs to remove" } @@ -54,6 +56,7 @@ commands: - id: blacklist_ip name: zscaler-blacklist-ip description: "Add one or more IP addresses to the advanced block list." + risk: destructive inputs_schema: properties: ips: { type: string, description: "Comma-separated IP addresses to block" } @@ -62,6 +65,7 @@ commands: - id: undo_blacklist_ip name: zscaler-undo-blacklist-ip description: "Remove one or more IP addresses from the advanced block list." + risk: destructive inputs_schema: properties: ips: { type: string, description: "Comma-separated IP addresses to remove" } @@ -78,6 +82,7 @@ commands: - id: whitelist_url name: zscaler-whitelist-url description: "Add one or more URLs to the allow list." + risk: destructive inputs_schema: properties: urls: { type: string, description: "Comma-separated URLs to allow" } @@ -94,6 +99,7 @@ commands: - id: category_add_url name: zscaler-category-add-url description: "Add one or more URLs to a custom URL category." + risk: destructive inputs_schema: properties: category_id: { type: string, description: "URL category id (from zscaler-get-categories)" } @@ -122,6 +128,7 @@ commands: - id: activate_changes name: zscaler-activate-changes description: "Activate pending configuration changes in the Zscaler session." + risk: destructive inputs_schema: properties: {} required: [] diff --git a/templates/manifest.example.yaml b/templates/manifest.example.yaml index b62eae0..0f27e46 100644 --- a/templates/manifest.example.yaml +++ b/templates/manifest.example.yaml @@ -47,10 +47,22 @@ auth: secret_field: api_key commands: + # Every command declares `risk:` — read | safe_write | destructive. It is what + # the agent approval gate reads: `read` runs unattended, `safe_write` and + # `destructive` sit behind the operator's configured threshold. An omitted + # risk is treated as `destructive`, which is the safe default but makes a + # lookup as noisy as an isolation, so declare it rather than let it default. + # read — only queries; changes nothing outside Riposte + # safe_write — additive or reversible: a comment, a ticket, a tag, a + # sandbox submission, an alert status, a collection job + # destructive — changes the estate or weakens a control: containment and + # its removal, blocklists, exclusions, deletes, identity and + # credential operations, running code on a host # --- Request-based command (recommended: declarative, no sandbox) --------- - id: lookup name: Lookup indicator description: Fetches a report for an indicator over HTTP. + risk: read # required in practice · read | safe_write | destructive inputs_schema: properties: indicator: @@ -75,6 +87,7 @@ commands: - id: example_command name: Example scripted command description: Demonstrates a Python-backed command. + risk: read inputs_schema: properties: indicator: