KSI-CNA-MATMinimizing Attack Surface
Machine-based information resources are persistently reviewed to ensure they have a minimal attack surface and that lateral movement is minimized if compromised.
Mapped NIST 800-53 controls (14)
- recipe8
- KSI only6
The mark says whether an authored AWS recipe fetches evidence for the control; the tier strip shows which Rev5 baselines also require it — where automated KSI evidence doubles as Rev5 control evidence. = in the class B, C and D baselines, left to right
- 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
- recipe · 1 recipeAC-17 (03)ACIn baseline C, D
- KSI onlyAC-18 (01)ACIn baseline C, D
- KSI onlyAC-18 (03)ACIn baseline C, D
- KSI onlyAC-20 (01)ACIn baseline C, D
- recipe · 1 recipeCA-09CAIn baseline B, C, D
- recipe · 1 recipeSC-07 (03)SCIn baseline C, D
- recipe · 1 recipeSC-07 (04)SCIn baseline C, D
- recipe · 1 recipeSC-07 (05)SCIn baseline C, D
- KSI onlySC-07 (08)SCIn baseline C, D
- recipe · 1 recipeSC-08SCIn baseline B, C, D
- KSI onlySC-10SCIn baseline C, D
- recipe · 1 recipeSI-10SIIn baseline C, D
- recipe · 1 recipeSI-11SIIn baseline C, D
- KSI onlySI-16SIIn baseline C, D
Collect evidence (3)
Authored AWS and pipeline recipes whose output is evidence for KSI-CNA-MAT. This mapping is this project’s opinion (AWS overlay v3.0.0, pipeline overlay v0.8.0), versioned separately from the dataset — the upstream FedRAMP rules name none of these tools.
- partialEvery route in or out of the boundary, named and counted — internet gateways, NAT gateways, VPC endpoints and Site-to-Site VPN tunnels — alongside what each boundary device does with traffic that matched no rule: the network ACL entries, the closed default security group, subnets that hand out public IPs, and the firewall policy's stateless and stateful default actionsweeklycliawsboundary-access-points-and-default-denyAmazon VPC · Amazon EC2 · AWS Network Firewall · AWS Config
The inventory is telemetry; the limit is policy. SC-07.03 asks that external connections be held to the minimum needed and each one routed through a managed interface — these calls enumerate every gateway, endpoint and tunnel exactly, but whether that count is the minimum is a comparison against your documented architecture, and nothing in the API tells you a gateway is unnecessary. SC-07.04 is the weakest half here: describe-vpn-connections proves the tunnels exist and are up, but the control also wants each external telecommunications interface documented with its business need and traffic-flow policy, exceptions reviewed and removed — that record is a document, not a call. This recipe also does not cover carrier links terminated outside these APIs (AWS Direct Connect connections, Transit Gateway peering to another network); enumerate those separately if you use them. SC-07.05 is the closest to full: the default-deny posture of security groups, network ACLs and the firewall policy is directly readable, and vpc-default-security-group-closed is a clean pass/fail. Read the ACL Entries yourself rather than trusting a rule verdict — an allow entry with a low rule number can shadow everything below it, and no managed rule scores ordering. Substitute your real firewall policy name; describe-firewall-policy is one policy per call. Security-group ingress is covered by the SC-07 recipe (restricted-ssh, vpc-sg-open-only-to-authorized-ports) and not repeated here.
- partialWhich taint-tracking ruleset actually ran over this repository — the query suite, the languages selected, and the threat model that decides what counts as an untrusted source — together with whether the recurring scan is still scheduled, when it last ran per analysed language, and how many rules were in the run; and then the open findings in the injection families SI-10 is about, identified by the CWE tags the queries carry. The ruleset and the freshness are the load-bearing half: a finding names a sink that exists, but only the run record says the absence of findings means anything at all.continuousapipipelineinput-validation-taint-analysis-coverageGitHub code scanning · GitHub CodeQL
SI-10 asks the provider to check the validity of organization-defined information inputs, and the defining is the half no scanner does. Taint-tracking analysis is genuine telemetry about the other half — a path from a source the ruleset models to a sink it knows is exactly what an input-validation failure looks like in code — but a clean result says "no sink the ruleset knows about, reachable from a source it models" and the control says "the inputs we defined are checked". Those are different sentences, and `scan_scope` names the second list because nothing in this output contains it. THE THREAT MODEL IS THE SHARPEST TRAP ON THIS CONTROL AND IT LOOKS LIKE A SOLVED PROBLEM. `threat_model` is a field in the response with a value of `remote` or `remote_and_local`, so it reads like a setting a provider can simply turn up. GitHub documents that "The default threat model includes remote sources of untrusted data" and that extending it to local sources — "command-line arguments, environment variables, file systems, and databases" — is "currently in public preview and subject to change" and "supported only by analysis for Java/Kotlin and C#". Two consequences follow, and both are findings rather than caveats. On a codebase in any other language, there is no local-source configuration to make: a CLI argument, an environment variable or a row read back out of the database is NOT in the model the scan used, and SI-10's information inputs frequently include exactly those. And where the language does support it, the capability is in public preview, which is a poor foundation for a control statement in a Moderate or High system. Nothing below asserts `remote_and_local`, deliberately — asserting it would fail every provider whose language cannot express it, while implying the ones that can have covered local inputs. WHY THE RULESET-COVERAGE LIMB IS COLLECTED AND NOT ASSERTED, AND WHY THAT IS WHAT KEEPS THIS RECIPE `partial`. The clause an assessment actually wants is "a query for this CWE family was in the run", because that is what makes an empty finding list meaningful. It is not writable from the documented API. `rule.tags` exists only on alerts that exist, so the CWE tags are visible precisely when something was found and invisible in the case where the claim matters. `rules_count` counts rules without naming them. The SARIF response is the closest available and GitHub documents it as "a subset of the analysis data that was uploaded" — a subset cannot establish the absence of a rule, and a recipe that asserted over it would be reading an unspecified sample as a population. What IS writable, and is now asserted, is the coarser half of the same question: that the language was selected at all. The residue — which QUERIES ran within that language — is what keeps this `partial`, and the residue is a property of the documented API rather than of this batch's effort. Two things could close it and neither is in scope here: a documented endpoint listing a run's rules, or the published per-language suite membership read against `query_suite`, which is an inference the cited pages do not license. WHAT THE QUERY SUITE CHANGES ABOUT THE WORD "CLEAN". GitHub documents the `default` suite as "highly precise" with "few false positive" results, and `security-extended` as "all the queries in the default query suite, plus additional queries with slightly lower precision and severity" that "may return a greater number of false positive code scanning results". So a clean result under `default` is a weaker statement than a clean result under `extended` — fewer queries asked fewer questions — and a provider that switched to `extended` and now has open alerts has not regressed. The value is collected and not asserted because SI-10 names no suite; treating `extended` as a requirement would be authoring a preference as a control. A CADENCE GAP WORTH STATING PLAINLY, BECAUSE IT IS THE PLATFORM FAILING THE INDICATOR RATHER THAN THE PROVIDER. The freshness clause enforces seven days because that is what `schedule: weekly` means. KSI-CNA-MAT's own class-c floor is the VDR-TFR-MVX MUST — verify and validate the status of machine-based information resources at least once every three days — which is tighter, and SI-10 is a class c and class d control, so this reaches every reader. On an actively developed repository the gap closes by itself, because default setup also scans on pushes and pull requests; on a boundary repository that is quiet, the weekly schedule is the only thing running and the schedule clause is the only reason its silence is visible at all. For class d the binding MUST is LOOSER rather than tighter — read it off `classClocks[].tightestMust`, because the tightest class-d clock is a SHOULD — so this is a class-c fact and not a monotonic one. A provider needing to close it moves to advanced setup and its own schedule, which is a different recipe against a different endpoint. The default-branch limit applies here as it does to the sibling recipe on this platform: alert status reflects the default branch, the organization-scoped alerts endpoint takes no `ref` filter, and the analyses command pins `ref` to the default branch for the same reason. This is a default-branch statement about a repository, not a repository-wide one. KSI-PIY-RSD also reaches this control and is deliberately NOT claimed. That indicator asks whether the effectiveness of building security into the SDLC is persistently reviewed, and a scan record is an input to such a review rather than the review itself — the same reason the secret-scanning recipe declined the rotation limb of its adjacent indicator. KSI-CNA-MAT is claimed because an injection sink reachable from untrusted input is attack surface in the indicator's own terms — the dataset's own glossary counts code among machine-based information resources — and a recurring analysis over a named repository set is the persistent review it asks for.
- partialWhether the queries that find information disclosure through an error message or a stack trace ran over this part of the boundary — which languages were selected, whether the recurring scan is still scheduled and when it last completed — and then the open findings those queries produced, identified by the CWE tags the queries carry rather than by their names. The run record is the load-bearing half here as it is on every scanning recipe: a finding names a leak that exists, and only the record of a scan having run over a selected language makes the absence of findings a statement about anything.continuousapipipelineerror-handling-information-exposure-scanningGitHub code scanning · GitHub CodeQL · GitHub code security configurations
SI-11 has two limbs and this plane can see one of them. Error messages must provide the information necessary for corrective actions without revealing information that could be exploited, and they must be revealed only to defined personnel. The first is code, and a query that traces an exception to a response is real telemetry about it. The second is a runtime access decision — who can read the response, who can read the log the trace landed in — and no code scan observes it. This recipe is rated `partial` for the first limb alone and claims nothing about the second, which is what the register's disposition for this control said before it was authored and remains true after. WHETHER A PARTICULAR MESSAGE REVEALS EXPLOITABLE INFORMATION IS THE JUDGEMENT NOBODY AUTOMATES, AND THE QUERY DOES NOT PRETEND OTHERWISE. `js/stack-trace-exposure` finds a stack trace reaching an HTTP response; whether that trace names an internal host, a query fragment and a framework version, or says only that something failed, is a human reading of the finding. The clause below is offender form over the alerts those queries raised, so a green result is "the queries found no such path" — a narrower sentence than the control's, and the gap between them is the rating. WHY THE CWE TAGS AND NOT THE QUERY NAMES. `rule.id` is stable per query and per language, so a clause naming `js/stack-trace-exposure` would be green on a Java service by construction. The tag array is the language-independent join: the three query help pages fetched for this recipe — JavaScript, Java and Python — each carry `external/cwe/cwe-209` and `external/cwe/cwe-497`, so one clause covers those three without naming a query per language. It covers those three and not the whole enum, which the paragraph below states as a residue rather than leaving it to be inferred from the word "regardless". CWE-497 is included beside CWE-209 because the queries themselves carry both and dropping it would narrow the clause below what the ruleset actually asserts. THE RULESET-COVERAGE RESIDUE IS THE SAME ONE THE SIBLING RECIPE DOCUMENTED AND IT IS A PROPERTY OF THE API. The clause an assessment wants is "a query for CWE-209 was in this run", and it is not writable: `rule.tags` exists only on alerts that exist, so the tags are visible exactly when something was found and invisible in the case where the claim matters, and `rules_count` counts rules without naming them. What partially closes it here and did not close it there is the query-suite membership: the three pages fetched list these queries in `javascript-code-scanning.qls`, `java-code-scanning.qls` and `python-code-scanning.qls`, which is the DEFAULT suite, so a default-setup repository in one of those languages ran them. THREE OF THE NINE LANGUAGES DEFAULT SETUP ACCEPTS, AND SIX THAT WERE NOT CHECKED. The documented `languages` enum is `actions`, `c-cpp`, `csharp`, `go`, `java-kotlin`, `javascript-typescript`, `python`, `ruby` and `swift`, and the suite-membership fact above was established for JavaScript, Java and Python only. On a c-cpp, csharp, go, ruby, swift or actions repository the run-record clauses below pass and the CWE clause is green with nothing verified about whether a CWE-209 query was in that language's default suite at all. Whether equivalent tagged queries exist there was not fetched, is not claimed, and is the first thing to close if this recipe is extended. That is a published fact about the suite rather than an inference from the response, it is cited, and it is why `query_suite` is collected and not asserted — requiring `extended` would be authoring a preference as a control, and the queries this recipe reads are in the default suite anyway. THE SEVEN-DAY FRESHNESS CLAUSE TAKES ITS NUMBER FROM THE PLATFORM AND NOT FROM THE CONTROL. Seven is what `schedule: weekly` means, asserted a clause earlier so that a gap reads as a missed scan rather than as a repository nobody pushed to; GitHub documents the weekly schedule switching itself off after six months without a push or pull request, which is how a quiet boundary repository stays `configured`, keeps a real analysis history and is no longer analysed. On an actively developed repository the gap closes by itself because default setup also scans on pushes and pull requests. THE DEFAULT-BRANCH LIMIT APPLIES AS IT DOES ACROSS THIS PLATFORM. Alert status reflects the default branch, the organization-scoped alerts endpoint takes no `ref` filter, and the analyses command pins `ref` for that reason. This is a default-branch statement about a repository, not a repository-wide one. TWO OF THE THREE INDICATORS THAT REACH THIS CONTROL ARE DELIBERATELY NOT CLAIMED. KSI-MLA-ALA — authorizing log access — is SI-11's second limb almost exactly, and it is the limb this plane cannot see at all; crediting a code scan with it would be the clearest possible case of dressing a document up as a command. KSI-PIY-RSD is declined for the reason the input-validation recipe already gave when it declined the same indicator: a scan record is an input to a review of the SDLC's effectiveness rather than the review itself. KSI-CNA-MAT is claimed because a stack trace reaching a response is attack surface in the indicator's own terms — it hands an attacker internal paths, versions and structure, which is reconnaissance for exactly the lateral movement the indicator asks to be minimized — and because a recurring analysis over a named repository set is the persistent review it asks for.
Default evidence owed by every indicator (5)
From info.default_artifacts.KSI — no indicator carries its own artifacts; requirement-specific evidence lives on /evidence.
- Explanation of measures (and their objectives) that demonstrate the Key Security Indicator, or an explanation of the reason and resulting risk to customers for not having measures available for that Key Security Indicator.
- Explanation of the cycle for any measures that are implemented persistently (if applicable).
- Verification that the measures demonstrate the Key Security Indicator, or that the reason for not having them is accepted.
- Verification that the automation in place is accurate and sufficient to demonstrate appropriate measures for the Key Security Indicator, or that automation is not necessary for each measure.
- Validation that the measures are accurately produced and are in place and working as intended, or that the reason for not having them is valid.
Defined terms used (3)
- Information Resource
- Has the meaning from 44 USC § 3502 (6): "information and related resources, such as personnel, equipment, funds, and information technology." This includes any aspect of the cloud service offering, both technical and managerial, including everything that makes up the business of the offering from non-machine-based information resources like organizational policies, procedures, employees, etc. to machine-based information resources like hardware, software, cloud services, code, etc.
- Machine-Based (Information Resources)
- Any information technology information resource—including systems, processes, software, hardware, services, cloud-native capabilities, and any other such capability, component, or resource—that relies primarily on mechanical or electronic devices (i.e. computers) for operation.
- Persistently
- Occurring in a firm, steady way that is repeated over a long period of time in spite of obstacles or difficulties. Persistent activities may vary between actors, may occur irregularly, and may include interruptions or waiting periods between cycles. These attributes of persistent activities should be intentional, understood, and documented; the status of persistent activities will always be known.
The Cloud Native Architecture run (8)
6/8 have an authored AWS recipe- 1 authored recipeKSI-CNA-DFPDefining Functionality and Privileges
- no authored recipeKSI-CNA-EISEnforcing Intended State
- 1 authored recipeKSI-CNA-IBPImplementing Best Practices
- 3 authored recipesKSI-CNA-MATMinimizing Attack Surfaceyou are here
- no authored recipeKSI-CNA-OFAOptimizing for Availability
- 2 authored recipesKSI-CNA-RNTRestricting Network Traffic
- 1 authored recipeKSI-CNA-RVPReviewing Protections
- 3 authored recipesKSI-CNA-ULNUsing Logical Networking