Compliance¶
Two sources feed these tools. The rulesets shipped in cloudg/rules (CIS for each cloud, NIST 800-53, PCI DSS, ISO 27001, SOC 2, HIPAA, GDPR, AWS Foundational Security Best Practices and others) define frameworks and controls. The dataset's ComplianceResult list and each finding's compliance_frameworks say which controls fail and on what. A framework argument matches case-insensitively, either exactly or as a substring, so CIS selects CIS-AWS, CIS-Azure and CIS-GCP together.
The ruleset catalog is read from config.rulesets.rules_dir (or cloudg's default rules directory), every *.yaml except check_equivalence.yaml, and cached per directory for the life of the process.
list_frameworks¶
Category compliance · sensitivity public · capabilities none · readOnly true, destructive false, idempotent true, openWorld false · outputSchema no · timeout: layer default (300 s)
The frameworks cloudg can map findings to. Needs no dataset. Each item has framework, versions, providers, controls (distinct control ids across its files) and files. With provider, frameworks tied to other providers are dropped; provider-neutral frameworks (empty providers) always stay.
| Argument | Type | Default | Constraints | Description |
|---|---|---|---|---|
provider |
string | "" |
aws, azure or gcp. |
Called with the arguments below, list_frameworks returned this structuredContent.
{
"total": 12,
"items": [
{
"framework": "CIS-AZURE",
"versions": [
"2.0",
"5.0"
],
"providers": [
"azure"
],
"controls": 123,
"files": [
"cis_azure_v2.yaml",
"cis_5.0_azure.yaml"
]
},
{
"framework": "GDPR",
"versions": [
"2016/679"
],
"providers": [],
"controls": 5,
"files": [
"gdpr.yaml"
]
},
"... 10 more"
]
}
Without a provider the sample run listed 28 frameworks.
compliance_summary¶
Category compliance · sensitivity internal · capabilities read_state · readOnly true, destructive false, idempotent true, openWorld false · outputSchema yes · timeout: layer default (300 s)
Posture per framework, from compliance results and finding tags together. Links up to five cloudg://compliance/{framework} resources.
| Argument | Type | Default | Constraints | Description |
|---|---|---|---|---|
framework |
string | "" |
Framework name or substring (e.g. 'CIS', 'PCI'); empty = all. | |
dataset |
string | "" |
Dataset name (see list_datasets). Empty = the active dataset. |
Per framework: controls_evaluated (compliance results), controls_failing, controls_passing, controls_other (NOT_APPLICABLE, MANUAL), pass_rate (passing / evaluated * 100, one decimal, null when nothing was evaluated), open_findings (open findings linked from a result or tagged with the framework), severity_breakdown, affected_assets and uri. Frameworks are sorted by open findings, most first. When nothing matches, frameworks is empty and a hint explains that findings need framework tags.
Called with the arguments below, compliance_summary returned this structuredContent.
{
"dataset": "sample",
"frameworks": [
{
"framework": "CIS-AWS",
"controls_evaluated": 4,
"controls_failing": 3,
"controls_passing": 1,
"controls_other": 0,
"pass_rate": 25.0,
"open_findings": 6,
"severity_breakdown": {
"CRITICAL": 1,
"HIGH": 3,
"MEDIUM": 2
},
"affected_assets": 5,
"uri": "cloudg://compliance/CIS-AWS"
},
{
"framework": "PCI-DSS",
"controls_evaluated": 1,
"controls_failing": 1,
"controls_passing": 0,
"controls_other": 0,
"pass_rate": 0.0,
"open_findings": 3,
"severity_breakdown": {
"CRITICAL": 1,
"HIGH": 2
},
"affected_assets": 3,
"uri": "cloudg://compliance/PCI-DSS"
},
"... 3 more"
]
}
The result also carried these resource links in content:
[
{
"type": "resource_link",
"uri": "cloudg://compliance/CIS-AWS",
"name": "CIS-AWS compliance",
"mimeType": "application/json"
},
{
"type": "resource_link",
"uri": "cloudg://compliance/PCI-DSS",
"name": "PCI-DSS compliance",
"mimeType": "application/json"
},
{
"type": "resource_link",
"uri": "cloudg://compliance/NIST-800-53",
"name": "NIST-800-53 compliance",
"mimeType": "application/json"
},
"... 2 more"
]
Called with the arguments below, compliance_summary returned this structuredContent.
{
"dataset": "sample",
"frameworks": [],
"hint": "No compliance data matched. Findings need compliance_frameworks (run normalise_findings after ingesting scanner reports); list_frameworks shows the framework names."
}
list_controls¶
Category compliance · sensitivity internal · capabilities read_state · readOnly true, destructive false, idempotent true, openWorld false · outputSchema no · timeout: layer default (300 s)
Controls of one framework, from either source. With source: "dataset" (default) the rows are the dataset's compliance results: framework, control_id, control_title, status, findings (ids on the result), open_findings and max_severity, filtered by status and sorted worst first. With source: "ruleset" the rows are every control the matching ruleset frameworks define: framework, control_id, title, severity and checks (number of mapped scanner checks); status is ignored and the cursor does not depend on any dataset.
| Argument | Type | Default | Constraints | Description |
|---|---|---|---|---|
framework |
string | required | min length 1 | Framework name or substring. |
status |
string | "" |
one of "", PASS, FAIL, NOT_APPLICABLE, MANUAL |
Only controls with this status (dataset source only). |
source |
string | "dataset" |
one of dataset, ruleset |
dataset = controls evaluated for this dataset; ruleset = every control the framework defines. |
limit |
integer | 50 |
1..500 | Maximum items to return. |
cursor |
string | "" |
Opaque cursor from a previous call's next_cursor; empty = first page. | |
dataset |
string | "" |
Dataset name (see list_datasets). Empty = the active dataset. |
Called with the arguments below, list_controls returned this structuredContent.
{
"dataset": "sample",
"source": "dataset",
"total": 4,
"offset": 0,
"returned": 4,
"next_cursor": null,
"truncated": false,
"items": [
{
"framework": "CIS-AWS",
"control_id": "5.2",
"control_title": "No SG allows 0.0.0.0/0 to admin ports",
"status": "FAIL",
"findings": 1,
"open_findings": 1,
"max_severity": "CRITICAL"
},
{
"framework": "CIS-AWS",
"control_id": "1.16",
"control_title": "IAM trust least privilege",
"status": "FAIL",
"findings": 1,
"open_findings": 1,
"max_severity": "HIGH"
},
"... 2 more"
]
}
Called with the arguments below, list_controls returned this structuredContent.
{
"source": "ruleset",
"frameworks": [
"CIS-AWS"
],
"total": 81,
"offset": 0,
"returned": 3,
"next_cursor": "c3.a358f04c1624",
"truncated": true,
"items": [
{
"framework": "CIS-AWS",
"control_id": "CIS-1.4",
"title": "Ensure access keys are rotated every 90 days or less",
"severity": "MEDIUM",
"checks": 0
},
{
"framework": "CIS-AWS",
"control_id": "CIS-1.5",
"title": "Ensure MFA is enabled for the root user",
"severity": "CRITICAL",
"checks": 0
},
{
"framework": "CIS-AWS",
"control_id": "CIS-1.7",
"title": "Eliminate use of the root user for administrative tasks",
"severity": "HIGH",
"checks": 0
}
]
}
{
"tool": "list_controls",
"arguments": {
"framework": "FEDRAMP",
"source": "ruleset"
},
"isError": true,
"text": "No ruleset framework matches the name. Known: AWS-Foundational-Security-Best-Practices-AWS, CIS-AWS, CIS-AZURE, CIS-GCP, GDPR, GDPR-AWS, HIPAA, HIPAA-AWS, HIPAA-AZURE, HIPAA-GCP, ISO-27001, ISO27001-A...",
"_meta": {
"cloudg/error_code": -32602,
"cloudg/error_data": {
"value": "FEDRAMP",
"known": [
"AWS-Foundational-Security-Best-Practices-AWS",
"CIS-AWS",
"CIS-AZURE",
"... 25 more"
]
}
}
}
control_status¶
Category compliance · sensitivity confidential · capabilities read_state · readOnly true, destructive false, idempotent true, openWorld false · outputSchema no · timeout: layer default (300 s)
One control: its ruleset definition, its status in the dataset, the open findings that fail it and the affected assets. Dataset results match when the control id is equal to control_id or ends with it; the definition is the first matching ruleset framework that defines exactly that id. status is NOT_EVALUATED without dataset results, FAIL when a result fails and open findings remain, PASS (all findings suppressed) when it failed but every finding is suppressed, otherwise the first result's status. The response echoes framework and control_id as given, and returns definition, status, results, open_findings (count), findings and affected_assets (both capped at limit) and truncated.
| Argument | Type | Default | Constraints | Description |
|---|---|---|---|---|
framework |
string | required | min length 1 | Framework name or substring. |
control_id |
string | required | min length 1 | Control id. A dataset result also matches when its id ends with this value. |
limit |
integer | 25 |
1..200 | Cap on findings and affected_assets. |
dataset |
string | "" |
Dataset name (see list_datasets). Empty = the active dataset. |
Called with the arguments below, control_status returned this structuredContent.
{
"dataset": "sample",
"framework": "CIS-AWS",
"control_id": "5.2",
"definition": {
"framework": "CIS-AWS",
"control_id": "5.2",
"title": "Ensure no Network ACLs allow ingress from 0.0.0.0/0 to remote server administration ports",
"severity": null,
"checks": 3
},
"status": "FAIL",
"results": [
{
"framework": "CIS-AWS",
"control_id": "5.2",
"control_title": "No SG allows 0.0.0.0/0 to admin ports",
"status": "FAIL"
}
],
"open_findings": 1,
"findings": [
{
"id": "f-ssh-open",
"title": "Security group allows SSH (22) from 0.0.0.0/0",
"severity": "CRITICAL",
"risk_score": 9.5,
"source_tool": "prowler",
"resource_id": "sg-admin",
"resource_arn": "arn:aws:ec2:us-east-1:111111111111:security-group/sg-0admin",
"asset_id": "sg-admin",
"asset_name": "sg-admin",
"compliance_frameworks": [
"CIS-AWS",
"PCI-DSS"
],
"is_suppressed": false,
"cvss_score": null,
"detected_at": "2026-01-15T12:00:00+00:00",
"uri": "cloudg://findings/f-ssh-open"
}
],
"affected_assets": [
{
"id": "sg-admin",
"name": "sg-admin",
"type": "SECURITY_GROUP",
"provider": "AWS",
"region": "us-east-1",
"account_id": "111111111111",
"arn": "arn:aws:ec2:us-east-1:111111111111:security-group/sg-0admin",
"internet_exposed": false,
"open_findings": 1,
"max_severity": "CRITICAL",
"uri": "cloudg://assets/sg-admin"
}
],
"truncated": false
}
The ruleset and the dataset can disagree on titles: here the dataset result says "No SG allows 0.0.0.0/0 to admin ports" while the CIS-AWS ruleset entry with id 5.2 is the network ACL control. Both are shown so the caller can tell.
{
"tool": "control_status",
"arguments": {
"framework": "CIS-AWS",
"control_id": "9.9"
},
"isError": true,
"text": "No such control for that framework. Controls in this dataset: 1.16, 2.1.4, 3.1, 5.2",
"_meta": {
"cloudg/error_code": -32602,
"cloudg/error_data": {
"value": "9.9",
"framework": "CIS-AWS",
"known": [
"1.16",
"2.1.4",
"3.1",
"5.2"
]
}
}
}
compliance_gaps¶
Category compliance · sensitivity confidential · capabilities read_state · readOnly true, destructive false, idempotent true, openWorld false · outputSchema no · timeout: layer default (300 s)
Assets that fail compliance, worst first. A finding counts as a gap when it is open, at or above min_severity, and either carries a matching framework tag or is linked from a failing compliance result of a matching framework. Rows are asset briefs plus frameworks, failing_controls (framework:control_id, first 20), gap_findings and gap_max_severity. Findings on resources that are not mapped get a row with id: "unmapped:<resource>", name: <resource> and unmapped: true.
| Argument | Type | Default | Constraints | Description |
|---|---|---|---|---|
framework |
string | "" |
Framework name or substring; empty = all. | |
min_severity |
string | "" |
Only findings at or above this severity count as gaps. | |
limit |
integer | 50 |
1..500 | Maximum items to return. |
cursor |
string | "" |
Opaque cursor from a previous call's next_cursor; empty = first page. | |
dataset |
string | "" |
Dataset name (see list_datasets). Empty = the active dataset. |
Called with the arguments below, compliance_gaps returned this structuredContent.
{
"dataset": "sample",
"framework": "CIS",
"total": 8,
"offset": 0,
"returned": 3,
"next_cursor": "c3.50cc1e27f5ec",
"truncated": true,
"items": [
{
"id": "az-nsg",
"name": "jump-nsg",
"type": "NSG",
"provider": "AZURE",
"region": "westeurope",
"account_id": "00000000-aaaa-bbbb-cccc-000000000001",
"arn": "/subscriptions/00000000-aaaa-bbbb-cccc-000000000001/resourceGroups/rg-hub/providers/Microsoft.Network/networkSecurityGroups/jump-nsg",
"internet_exposed": false,
"open_findings": 1,
"max_severity": "CRITICAL",
"uri": "cloudg://assets/az-nsg",
"frameworks": [
"CIS-Azure"
],
"failing_controls": [
"CIS-Azure:6.1"
],
"gap_findings": 1,
"gap_max_severity": "CRITICAL"
},
{
"id": "sg-admin",
"name": "sg-admin",
"type": "SECURITY_GROUP",
"provider": "AWS",
"region": "us-east-1",
"account_id": "111111111111",
"arn": "arn:aws:ec2:us-east-1:111111111111:security-group/sg-0admin",
"internet_exposed": false,
"open_findings": 1,
"max_severity": "CRITICAL",
"uri": "cloudg://assets/sg-admin",
"frameworks": [
"CIS-AWS"
],
"failing_controls": [
"CIS-AWS:5.2"
],
"gap_findings": 1,
"gap_max_severity": "CRITICAL"
},
{
"id": "bastion",
"name": "bastion",
"type": "EC2",
"provider": "AWS",
"region": "us-east-1",
"account_id": "111111111111",
"arn": "arn:aws:ec2:us-east-1:111111111111:instance/i-0bast",
"internet_exposed": true,
"open_findings": 1,
"max_severity": "HIGH",
"uri": "cloudg://assets/bastion",
"frameworks": [
"CIS-AWS"
],
"failing_controls": [],
"gap_findings": 1,
"gap_max_severity": "HIGH"
}
]
}
bastion lists CIS-AWS with no failing control because its IMDSv1 finding is tagged CIS-AWS but no compliance result links it.
Related: the compliance_gap_analysis prompt, Recipe: compliance gap triage.