◐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.continuousapi
static-analysis-coverage-and-flaw-dispositionGitHub code scanning · GitHub CodeQL · GitHub code security configurations
SA-11 has five limbs and this recipe reaches parts of three. The developer's security and privacy assessment plan and the depth-and-coverage determination that plan is required to state are documents; a 3PAO reads them there. What the platform contributes is that testing RAN, with a named ruleset and a live schedule, over a named set of repositories and languages, and what it found — the evidence-of-execution limb — plus the disposition of each finding, which is the flaw-correction limb seen from one side, plus one testable property of the remediation record itself: that each closure carries a written justification, which is the verifiability limb the dismissal clause is grounded in. The judgement that a flaw was corrected rather than argued away is not in this output and no amount of extra collection puts it there. That is what the disposition this recipe spends already said, and writing the commands down has not changed it.
WHAT AN EMPTY ALERT LIST IS CONSISTENT WITH, ON THIS CONTROL SPECIFICALLY. Five worlds, and only one is a pass: nothing was found; nothing was scanned; scanning is off; scanning was on and the schedule has since been disabled for inactivity; or one repository out of forty was scanned. The first six assertions exist to separate them and they are ordered deliberately — configuration intent, ownership, attachment success, repository state, schedule liveness, then rule count and freshness — because each is necessary for the next to mean anything. There is a sixth world hidden by a present, plausible-looking field: default setup analyses a SELECTED LIST of languages, and a repository can be `configured`, scheduled, fresh, rule-carrying, and completely silent about the service that carries the risk because that language was never selected. `languages` is returned by the third command, so the fact is collected; it is not asserted, because the list it must be compared against — the languages the boundary's code is written in — is not in any response here. `scan_scope` names that comparison.
WHY THERE IS NO SEVERITY THRESHOLD CLAUSE. It would be easy to add "no open alert at critical severity" and it would be the wrong control. SA-11 is about the developer performing testing and producing evidence of it, not about the estate being free of findings. The clock on how fast a detected finding must be dealt with is the dataset's own VER-TFR-EVU requirement — evaluate ALL vulnerabilities within a stated number of days of detection — which is a different measurement with a different per-class value, and a recipe that quietly turned SA-11 into a zero-criticals gate would report an authorization failure for a provider testing exactly as this control requires and holding a legitimately open medium.
A CADENCE GAP THAT BELONGS TO THE PLATFORM RATHER THAN TO THE PROVIDER, AND WHICH THE SEVEN-DAY CLAUSE DOES NOT CLOSE. The freshness clause enforces seven days because that is what `schedule: weekly` means. KSI-SCR-MIT'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 than the schedule this platform runs on default setup, and SA-11 is a class c and class d control, so this affects every reader of it. 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 it does not meet the indicator's clock. For class d the binding MUST is looser rather than tighter — read it off `classClocks[].tightestMust` rather than off the tightest clock, which is a SHOULD — so the gap is a class-c fact, 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.
HOW SEVERITY IS DERIVED, SINCE ASSESSMENTS TREAT IT AS AN OBSERVATION. GitHub documents that every code scanning alert carries a level of Error, Warning or Note, that CodeQL security alerts additionally carry Critical, High, Medium or Low, and that those levels "follow the industry-standard Common Vulnerability Scoring System (CVSS)" — derived by taking the 75th-percentile CVSS score of CVEs whose CWE tags relate to the query. So `security_severity_level` is a statistical property of a class of vulnerability, not a measurement of this instance in this codebase. It is a good prioritisation signal and it is not a risk determination for the system under assessment.
WHAT `dismissed_reason` ADMITS, AND THE ONE VALUE THAT IS A CLAIM RATHER THAN AN OBSERVATION. The documented values are `false positive`, `won't fix`, `used in tests`, `mitigated` and `null`. Three of the four strings describe the finding; `mitigated` describes the code, and nothing in the platform verifies it — a person selected it. `won't fix` is the value an assessment should read against the provider's own risk-acceptance procedure rather than against this recipe. Where `code_scanning_delegated_alert_dismissal` is `enabled` on the governing configuration, dismissals go behind a reviewer instead of being unilateral; that field is collected by the first command and is deliberately not asserted, because the control does not require delegated dismissal and a provider without it can still hold a verifiable remediation record.
THE DEFAULT-BRANCH PICTURE. GitHub states that an alert's status "only reflect[s] the state of the alert on the default branch of the repository, even if the alert exists in other branches", and the organization-scoped alerts endpoint accepts no `ref` filter at all. So this evidence is a statement about the default branch of each repository, which is also why the analyses command pins `ref` to it. For a provider that releases from the default branch that is the right population; for one that maintains long-lived release branches, the branch that is actually deployed may be carrying findings this recipe cannot see, and the repository-scoped alerts endpoint with `ref` is where that gap is closed.
ONE THING THE DOCUMENTATION DOES NOT SAY, RECORDED AS A GAP RATHER THAN FILLED IN. The reference page for alerts does not define what makes an alert `fixed` rather than `dismissed`, or what happens to an open alert when the code stops being scanned, and this recipe makes no claim about either. An alert disappearing from `alerts-open` is therefore not by itself evidence that a flaw was corrected — the same limb the dismissal clause is careful about, arriving from the other direction.
KSI-SCR-MIT is claimed because it is the ONLY in-scope indicator the dataset maps onto SA-11 — the claim is forced by an upstream mapping rather than chosen, and it is worth saying so plainly, because the fit is imperfect. The indicator asks that supply chain RISKS be persistently identified, reviewed and mitigated, and CodeQL default setup analyses the provider's own source: a first-party injection sink is a software weakness rather than a supply chain risk. What transfers cleanly are the verbs — a recurring analysis is identification and the dismissal record is review — and the noun does not. Mitigation is outside this plane in any case: whether the code changed is a fact about a commit, not about an alert list, and the `fixed` state is not documented well enough here to carry it.