Repository navigation
v0.6.1 - Documentation and bug fix
A security fix for report.html, a round of fixes found while documenting every command and API, and the new docs site. Upgrade if you open reports built from scanner output you did not produce yourself. Several commands now behave the way their help text always said, so check the Changed list if you script cloudg report, cloudg scan or the exit codes.
Security:
- report.html no longer runs markup or script that arrives in scanner output. Finding titles, descriptions, evidence, resource IDs, asset names and compliance framework names are escaped wherever the page writes them, the page header is autoescaped, and data embedded in the page's script can no longer close the script element.
- A package can no longer take over a built-in scanner (such as
prowler) by registering acloudg.scannersentry point with the same name. Built-in names always win and the duplicate is ignored with a warning.
Fixed:
- report.html works offline. Chart.js 4.4.0 and D3 7.9.0 ship with cloudg and are embedded in the page when
report.inline_jsis true (the default). Withinline_js: falsethe page loads the same pinned builds from cdn.jsdelivr.net with Subresource Integrity. Clicking a row in a filtered findings table now opens that finding. - Config keys that were accepted but ignored now take effect:
graph.persist_graphml,graph.export_cytoscape,graph.max_nodes_warn,rag.chunk_strategy,rag.max_chunk_tokens,report.formats,report.inline_js,report.output_dir(as the default of theCloudGEnginemethods),rulesets.load_externalandontology.include_raw_metadata. A misspelt key in any section is logged asUnknown config key <section>.<key> is ignored, not only underratelimit.rulesets.rules_dir: nullloads the packaged rulesets instead of failing validation. cloudg deps --jsonwrites only JSON to stdout. Whenever--jsonis used, and forcloudg mcp, the banner and logs go to stderr.cloudg report -ikeeps the scan ID, timestamps, compliance results and edges of a findings.json, rebuilds edges for older files that lack them, and accepts raw-findings.json.scanners.timeout_secondslimits each scanner process incloudg run,cloudg scanandCloudGEngine.scan(). Before, the limits were hard-coded at 3600 and 1800 seconds. A scanner that times out is reported as failed and its partial findings are kept.cloudg scanreads-c config.yaml, no longer scans the current directory unless asked, runs the IAM linter when given--assets, and exits 1 when no requested scanner could run.cloudg collectuses the credentials and regions in config.yaml.cloudg map --sweepfollowsinventory.tagging_sweepunless the flag is given.- Prowler and ScoutSuite get the credentials cloudg was given: session token, the assumed
role_arn, web identity andaws.profilefrom the config, and real regions.AWS_DEFAULT_REGION=ALLis no longer set. Region discovery for--regions alluses the same credentials, and falls back to the 17 regions enabled by default in every account when discovery fails. cloudg runexits 3 when collection failed for every target, including a run with no credentials at all where every service fails on its own, and lists the targets that failed. Partial collection still exits 0, with a warning.--accountswithout--role-name(oraws.role_name) is an error instead of mapping the caller's own account once per listed ID.aws.role_arnis assumed first and the member role from there, instead of replacing the member role. An--outhat matches nothing is an error that lists the organization's OUs.- Scanner plugins registered under
cloudg.scannersrun fromscanners.enabledand--scanners, and unknown scanner names produce a warning. The IAM linter followsscanners.enabledand--scannerstoo. CloudGEngine.run_pipeline()passesaws.profileto the scanners,PipelineResult.errorslists collection, scanner and analysis failures as well,on_findingfires as each scanner finishes and receives copies normalisation does not change, and the*_syncwrappers raise a clear error inside a running event loop.CloudGEngine.scan()falls back to a Trivy filesystem scan when no images are set, like the CLI.- Prowler compliance control IDs name the check (
CIS/iam_root_hardware_mfa_enabled) instead of including the account ID, so one check across several accounts is one control. When findings from two scanners are merged, both scanners' check-ID mappings are kept. - Compliance results are no longer all FAIL. A control fails when a finding maps to it and passes when only Prowler passing checks (ASFF
PASSED, OCSFPASS) map to it; controls nothing assessed are left out.FindingsNormaliser.normalise()takespassed_checks=, and the Prowler parser returns them on the list it gives back. - Prowler OCSF output (
*.ocsf.json, the Prowler 4 default) is parsed: status, severity, resource, check ID, compliance and muted findings. Before, every record became an "Unknown Prowler Finding", passing checks included. The MCP loaders accept OCSF instead of refusing it. ScoutSuite documentation URLs no longer show up as compliance frameworks. build_asset_map()andbuild_compliance_map()match findings to assets the way the ontology and RAG exports do, so a finding no longer attaches to every asset that shares its name.CloudGEngine.map_inventory(findings=...)applies the overlay withoutoutput_dirtoo (result.asset_map,result.compliance_map).- GraphML export (
cloudg run,InventoryResult.export(), the MCP export) no longer fails on assets without an ARN.RelationshipLinker.link()can be called more than once.inventory-map.jsonsaves the collection coverage records andInventoryResult.load()restores them. - Each ontology format gets its own file (
.ttl,.jsonld,.rdf,.nt). N-Triples no longer overwrite the Turtle file, and spellings such asjsonldno longer land inontology.ttl.AnalysisResult.rag_chunk_countis filled in. CloudOntology.query_asset_neighbourhood()works withhopsabove 1 and with IDs containing:or/, andquery()returns None for unbound variables.NACL_RULEedges get the same ontology relations asSECURITY_GROUP_RULEedges.ReachabilityAnalyzer.compute_blast_radius()stops at the internet placeholder instead of following an egress rule out to everything the internet reaches.- findings.json metadata timestamps are ISO 8601, and an unset
completed_atisnullrather than"None".
Changed:
cloudg reportrefuses to write findings.json over its own input; pass-oto write elsewhere, or--overwrite. findings.json now has anedgeslist.cloudg scan --scannersdefaults toscanners.enabledinstead ofprowler,checkov, andcloudg scan -paccepts only aws, azure and gcp.- The Terraform recreation goes to
<output>/terraform, following-o, unlessterraform.output_diris set to another path. The old default./reports/terraformcounts as unset. cloudg runwritestopology-cytoscape.jsononly withgraph.export_cytoscape: true, and skipstopology.graphmlwithgraph.persist_graphml: false.run_pipeline()writes the formats inreport.formatsand now includestopology.svg.- RAG chunks are sized by
rag.max_chunk_tokens(about 4 characters per token) instead of fixed caps of 30 relations, 10 findings and 50 triples. Long lists end with an "... and N more" line, and community chunks are bounded too. - report.html is about 485 KB larger with the libraries embedded.
query_asset_neighbourhood()rows for more than one hop are{neighbour, neighbourName, hops}. D3 graph JSON has"arn": ""instead ofnullfor assets without an ARN.cloudg.mcp.state.check_prowler_inputwas removed.ProwlerScannertakes its newer settings (aws_session_token,aws_regions,timeout_seconds,env) and the access keys as keyword arguments; calls that pass them by keyword work as before.aws_regionis now the fifth positional argument.- Parts of three large modules moved into their own: the engine result types and collection checks to
cloudg.api_results, the rate-limit models tocloudg.config_ratelimit, and the RAG chunk text builders tocloudg.graph.rag_text. Everything public is still importable fromcloudg.api,cloudg.configandcloudg.graph.rag_export.
Documentation:
- The handbook at morpheuslord.github.io/cloudg is now a site of separate pages instead of one long
docs/index.html. Guides, the CLI, the Python API, the MCP server, the reference documents and this changelog each have their own tab and sidebar.site/build.pybuilds it: the CLI options tables come from the click definitions, the API pages from the docstrings, the config pages fromconfig.yamland theCloudGConfigmodels, and the longdocs/*.mdreferences are split into one page per section. Writing rules for new pages are insite/AUTHORING.md. - New guides cover installation, the pipeline phase by phase, authentication for each provider, AWS Organizations, scanners and ingest input formats, compliance mapping, reports, the graph, ontology and RAG exports, rate limits, Docker, CI and Python recipes. Code samples are complete scripts, and processes are drawn as diagrams.
- Search (Ctrl K or /), a dark theme, linked code tabs and copy buttons work without a server. Links to the old
index.html#anchorsections redirect to the new pages.