Whether the tooling that examines acquired software is switched on and covering the estate, and what it found: Inspector's per-account enablement state for each scanned resource type, the registry-wide ECR scanning configuration (scan type and frequency, and the repository filters that decide which repositories it applies to), Inspector's own coverage statistics, and a CycloneDX 1.4 or SPDX 2.3 SBOM exported per monitored resource — the component-level inventory of what was actually acquired.
The API supplies the facts, but a human judgement against a documented baseline turns them into evidence.
Fetch
$ aws inspector2 batch-get-account-status$ aws ecr get-registry-scanning-configuration$ aws inspector2 list-coverage-statistics --group-by SCAN_STATUS_REASON$ aws inspector2 create-sbom-export --report-format CYCLONEDX_1_4 --s3-destination bucketName=<SBOM_BUCKET>,keyPrefix=<SBOM_PREFIX>,kmsKeyArn=<KMS_KEY_ARN>$ aws inspector2 get-sbom-export --report-id <REPORT_ID>Expected output
From batch-get-account-status, accounts[] with accountId, state.status, and resourceState broken out per scanned resource type — ec2, ecr, lambda, lambdaCode and codeRepository — each with its own status and an errorCode when the service could not enable it. From get-registry-scanning-configuration, registryId and scanningConfiguration with scanType (BASIC or ENHANCED) and rules[], each rule carrying scanFrequency (SCAN_ON_PUSH, CONTINUOUS_SCAN or MANUAL) and repositoryFilters[] of {filter, filterType}; ENHANCED supports CONTINUOUS_SCAN and SCAN_ON_PUSH, BASIC supports SCAN_ON_PUSH only, and where scan-on-push is not specified the frequency defaults to MANUAL. From list-coverage-statistics, countsByGroup[] and totalCounts — the number of resources Inspector is actually covering, which is the number that decides whether an empty findings list means clean or means unscanned. From create-sbom-export, a reportId; from get-sbom-export, status (IN_PROGRESS | SUCCEEDED | FAILED | CANCELLED) with the s3Destination the JSON documents were written to. Each exported document is one resource's component inventory: CycloneDX 1.4 with components[] carrying purl and bom-ref, or SPDX 2.3 with packages[] carrying versionInfo and externalRefs. Unresolved hashes — components whose package manager used a version range or dynamic reference and which therefore cannot be scanned for vulnerabilities — are INCLUDED in the export as hashes, and are the part of the inventory a vulnerability count silently omits.
Assertions — what makes it a pass
| Field | Must be | For | Proves |
|---|---|---|---|
| batch-get-account-status.accounts[?resourceState.ecr.status!='ENABLED'] | count_eq 0Every account the call REPORTED ON has ECR scanning ENABLED. `resourceState.ecr` and its `status` are both required fields, so a never-enabled account answers DISABLED rather than omitting the key — the offender form is used here not to catch a missing key but because it names the failing rows directly, which is the shape that survives an estate this clause is later widened over. It is only half the check; the clause below is the other half. | every row | SR-05 |
| batch-get-account-status.failedAccounts | count_eq 0No account failed to enable Inspector at all. This is the sibling array, and without it the clause above is the ListResolverDnssecConfigs trap in a new costume: an account that could not be enabled — ACCESS_DENIED, BLOCKED_BY_ORGANIZATION_POLICY — is reported in failedAccounts[] and is ABSENT from accounts[], so a clause reading only accounts[] is green on precisely the account whose scanning never started. | every row | SR-05 |
| get-sbom-export.status | eq "SUCCEEDED"The SBOM export finished and wrote its documents. Poll until the status is terminal — SUCCEEDED, FAILED or CANCELLED — and assert on that. IN_PROGRESS is not a pass: it is exactly the state in which a report id exists and no inventory has been written, which is the condition this clause exists to catch, so accepting it would be a check that cannot fail. | every row | SR-05 |
Authored opinion, like the commands. Units live in the operator name — max-age-days is days, and nothing here is converted for you.
Map — what it proves
- recipe1
- recipe— an authored recipe collects evidence for this control
- KSI only— a Key Security Indicator reaches it, but no recipe is authored yet
- orphan— no Key Security Indicator reaches it — a person writes it up instead
What else these families can fetch:SR 3/14 →
GovCloud
Both services are available in AWS GovCloud (US-West) and AWS GovCloud (US-East). Two documented differences bear on this recipe and one bears on the control it proves. Inspector: Lambda CODE scanning is not available in the partition, so resourceState.lambdaCode reports its absence rather than a misconfiguration, and the Linux deep-inspection plugin is documented as not FIPS compliant — which matters to a provider whose SSP claims FIPS-validated modules end to end. ECR: pull-through cache rules work only WITHIN the same partition, ECR public registries are not available, and the ECR Public Gallery is not hosted in GovCloud though it may be reachable if the estate has external internet access. Those three are acquisition facts, not availability trivia: they change where a GovCloud estate's images can legitimately come from, which is the strategy half of SR-05. S3 and KMS ARNs in the export destination use partition arn:aws-us-gov.
Notes & assertions
SR-05 asks for acquisition strategies, contract tools and procurement methods that reduce supply-chain risk. Two halves, and AWS holds one of them completely and the other not at all. The half it holds is the TOOLING at the moment of acquisition. ECR's registry scanning configuration is the acquisition gate: scan-on-push examines an image as it enters the registry, and the rules[] with their repository filters say which repositories that applies to. Inspector monitors what has already landed and exports an SBOM per resource, which is the component-level inventory of what was actually acquired rather than what a supplier said they shipped. Both are continuous, both are machine-readable, and together they answer 'what did we take in, and what was wrong with it'. The half it does not hold is the STRATEGY the control names — the contract clauses, the approved-supplier list, the delivery method, the decision to buy this component rather than that one. No scanner stands in for procurement, and none of these five commands reads a contract. That is the whole reason for the partial rating, and the assessment reads it out of the acquisition documentation the control asks for. The enablement and coverage calls exist because of the empty-list trap, and here it is unusually sharp. A findings query against an estate with Inspector switched off returns an empty array and exits zero, and so does a clean estate. batch-get-account-status is what separates them: it reports status per resource type, so ECR ENABLED with EC2 DISABLED is visible as the partial coverage it is rather than as silence. Read BOTH of its arrays. An account that could not be enabled — access denied, or blocked by an Organizations policy — is reported in failedAccounts[] and does not appear in accounts[] at all, so a clause over accounts[] alone is green on the one account whose scanning never began. The enumeration has an edge worth stating too: accounts[] is capped at one hundred entries with no continuation token, and what the call returns when no account ids are passed is undocumented — so run it as the delegated administrator with the ids you mean, and treat the response as evidence about the accounts it names rather than about the organization. list-coverage-statistics closes the second half of the same gap — Inspector can be enabled and still not be covering a resource, and a count of covered resources is the denominator every finding count needs. Neither is decoration; without them the SBOM evidence is a claim about an unknown population. The registry configuration has its own version of the trap, and it is the reason no assertion here asserts on rules[] alone. Scan frequency defaults to MANUAL where scan-on-push was not configured, and a registry with NO rules is a registry that scans nothing on push — but it answers with a well-formed scanningConfiguration all the same, so a clause reading 'every rule has SCAN_ON_PUSH or CONTINUOUS_SCAN' is vacuously true on exactly the estate that has configured nothing. The offender form is the population of repositories no rule's filter matches, and that needs a join against describe-repositories this assertion grammar cannot express — which is why this is partial and not full even though the enablement half could be written down. On the SBOM export: it needs an S3 bucket whose policy allows Inspector to write and a KMS key whose policy allows Inspector to encrypt, both configured before the call, and it is asynchronous — create returns a reportId and get reports status. Read the unresolved-hash note in the output as evidence rather than noise. A component whose package manager used a version range cannot be mapped to a name and version, and therefore cannot be scanned for vulnerabilities at all; Inspector now includes those hashes in the export. They are the components a vulnerability count does not cover, and an SBOM read without them looks cleaner than the estate is. KSI-SCR-MON is earned directly: third-party software resources ARE automatically monitored for upstream vulnerabilities, and these commands prove the mechanism is on and covering. KSI-SCR-MIT is claimed for identify-and-review and not for mitigate — nothing here shows a risk being closed, only found.
References
- Amazon Inspector User Guide: Exporting SBOMs — CycloneDX 1.4 and SPDX 2.3, the create-sbom-export CLI form with its S3 and KMS prerequisites, and the inclusion of unresolved hashes for components that cannot be mapped to a name and version https://docs.aws.amazon.com/inspector/latest/user/sbom-export.html
- Amazon ECR API: GetRegistryScanningConfiguration — returns registryId and scanningConfiguration with scanType and rules[] of {repositoryFilters, scanFrequency} https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_GetRegistryScanningConfiguration.html
- Amazon ECR API: RegistryScanningRule — scanFrequency is SCAN_ON_PUSH | CONTINUOUS_SCAN | MANUAL; ENHANCED supports the first two, BASIC supports SCAN_ON_PUSH, and MANUAL is the default where scan-on-push is not specified https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_RegistryScanningRule.html
- Amazon Inspector API: BatchGetAccountStatus — accounts[] with state.status and resourceState per ec2, ecr, lambda, lambdaCode and codeRepository, and failedAccounts[] as a SIBLING array carrying its own resourceStatus and the errorCodes for accounts that could not be enabled https://docs.aws.amazon.com/inspector/v2/APIReference/API_BatchGetAccountStatus.html
- Amazon Inspector API: ResourceState — `ecr` is a required member and its `status` is required, so a never-enabled account reports DISABLED rather than omitting the key https://docs.aws.amazon.com/inspector/v2/APIReference/API_ResourceState.html
- AWS CLI: inspector2 get-sbom-export — status is SUCCEEDED | IN_PROGRESS | CANCELLED | FAILED; IN_PROGRESS is the state in which a report id exists and no document has been written https://docs.aws.amazon.com/cli/latest/reference/inspector2/get-sbom-export.html
- AWS GovCloud (US) User Guide: Amazon Inspector — available in both GovCloud Regions; Lambda code scanning is not available and the Linux deep-inspection plugin is not FIPS compliant https://docs.aws.amazon.com/govcloud-us/latest/UserGuide/govcloud-inspector2.html
- AWS GovCloud (US) User Guide: Amazon ECR — pull through cache rules are available only within the same partition, public registries are not available, and the ECR Public Gallery is not hosted in the partition https://docs.aws.amazon.com/govcloud-us/latest/UserGuide/govcloud-ecr.html
This AWS mapping is authored opinion (overlay v3.0.0), versioned separately from the dataset and written against ruleset 2026.07.14.01. The upstream FedRAMP dataset names none of these tools.
The Supply Chain Risk run (8)
- automatable
- partial — needs judgement
- narrative — no API proves this
Every authored recipe filed under SCR, in the order the plan works them. The mark says how much of the evidence the command produces on its own.
- partialThe machine-generated inventory of every resource an external entity can reach — IAM Access Analyzer's active ExternalAccess findings — read against the declared zone of trust, so the terms-and-conditions review has a list to work from rather than a memoryquarterlyexternal-access-inventory-and-trust-boundaryAWS IAM Access Analyzer · AWS Organizations · AWS Config
- partialThe advisories AWS itself has issued against this account — operational issues, scheduled changes and account notifications, each dated and scoped — together with the subscribers on the topic those alerts are published to and the confirmation state of each subscription, which is the difference between an address that was entered and an address that receivescontinuoussecurity-advisories-receipt-and-disseminationAWS Health · Amazon SNS
- partialWhether the tooling that examines acquired software is switched on and covering the estate, and what it found: Inspector's per-account enablement state for each scanned resource type, the registry-wide ECR scanning configuration (scan type and frequency, and the repository filters that decide which repositories it applies to), Inspector's own coverage statistics, and a CycloneDX 1.4 or SPDX 2.3 SBOM exported per monitored resource — the component-level inventory of what was actually acquired.you are herecontinuousacquisition-scanning-and-sbom-inventoryAmazon Inspector · Amazon ECR
- partialWhether Dependabot alerting is configured in this organization and which repositories it actually reaches, together with the alerts themselves — each carrying the advisory that raised it, the package, ecosystem and manifest path it was found in, the reason a human gave for closing it, and, for a remediated one, the date it was fixed. The first half is the population; the second half is what was found in it, and the second half means nothing without the first.continuousdependency-vulnerability-monitoringGitHub Dependabot · GitHub code security configurations
- partialThe organization's webhook configuration — which endpoints are subscribed to the supply-chain alert event, whether each is switched on, and where it points — together with the platform's own record of what it actually delivered to them and with what response code. Configuration says a path exists; the delivery log says the path carried something.continuoussupply-chain-alert-notification-routingGitHub webhooks · GitHub Dependabot
- partialWhether static analysis is configured in this organization and which repositories it actually reaches; for each of those repositories, which query suite ran over which languages, whether the recurring schedule is still alive, when the analysis last ran and with how many rules in the run; and what the analysis found, split into what is still open and what a person closed by hand — each closure carrying who closed it, which of four fixed reasons they chose, and whatever they wrote down. The first two halves are the population and the proof that testing happened; the third is the half an assessment asks for, and read without the other two it cannot be told apart from the output of a scanner that never ran.continuousstatic-analysis-coverage-and-flaw-dispositionGitHub code scanning · GitHub CodeQL · GitHub code security configurations
- partialThe rules that made every change to the mainline arrive through a reviewed pull request, as a signed commit, onto a history that cannot be rewritten — together with the record of when those rules themselves last changed and who changed them, and the platform's own per-push record of any change that got past them.weeklydeveloper-change-control-and-integrityGitHub repository rulesets · GitHub pull requests
- partialThe exact component-and-version inventory the boundary's repositories build from — every package the dependency graph resolved, carrying the version string that is the only thing SA-22's question can be asked about — together with whether that graph is switched on across the boundary at all, and then the open advisories for which the ecosystem offers no patched version, which is the closest thing a pipeline emits to a component nobody maintains any more. The inventory is the load-bearing half and it is why this recipe exists separately from the vulnerability one: "is this component past end of support" is a question about a name and a version, and a check that cannot produce the version has not asked it.monthlyunsupported-component-inventory-and-lifecycle-reviewGitHub dependency graph · GitHub Dependabot · GitHub code security configurations