The 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.
The API supplies the facts, but a human judgement against a documented baseline turns them into evidence.
Fetch
$ gh api --paginate "/orgs/<ORG>/code-security/configurations"$ gh api --paginate "/orgs/<ORG>/code-security/configurations/<CONFIGURATION_ID>/repositories?status=attached,enforced&per_page=100"$ gh api --paginate "/orgs/<ORG>/code-security/configurations/<CONFIGURATION_ID>/repositories?per_page=100"$ gh api "/repos/<ORG>/<REPO>/dependency-graph/sbom"$ gh api --paginate "/orgs/<ORG>/dependabot/alerts?state=open&per_page=100"$ gh api --paginate "/orgs/<ORG>/dependabot/alerts?state=dismissed&per_page=100"Expected output
Report names used below, and the command each comes from: `configurations` is the first, `configuration-repositories` the second, `configuration-repositories-all` the third, `sbom` the fourth, `alerts-open` the fifth and `alerts-dismissed` the sixth. The second and third call the SAME endpoint and the difference between them is the point rather than a duplication: the second narrows `status` to `attached,enforced` so the enumeration holds only repositories the configuration actually reached, and the third leaves `status` at its documented default of `all` so the `failed` rows are visible at all. A recipe carrying only the narrowed call cannot fail a clause about `failed`, because the row it is looking for was filtered out before the report was written. RUN COMMAND 4 ONCE PER REPOSITORY. The SBOM export is documented at `GET /repos/{owner}/{repo}/dependency-graph/sbom` and has no organization-scoped form, so the component inventory is assembled one repository at a time from the list command 2 returns; the two alert commands are organization-scoped and each alert carries its owning `repository`, so the advisory half arrives in one walk. From `configurations`, the fields this recipe reads and their documented defaults, which are not the same for the two settings it depends on: `dependency_graph` is `enabled | disabled | not_set` and defaults to `enabled`, while `dependabot_alerts` is the same enum and defaults to `disabled`. `target_type` is `global | organization | enterprise` and `enforcement` is `enforced | unenforced`. From `configuration-repositories`, the association `status`, whose documented values are `all, attached, attaching, detached, removed, enforced, failed, updating, removed_by_enterprise` and whose documented DEFAULT is `all` — the second command narrows it to `attached,enforced` so the enumeration holds only repositories the configuration actually reached, and the third leaves it unnarrowed so the `failed` rows a clause of its own reads below are present in a report at all. From `sbom`, an SPDX document under a required `sbom` key carrying `SPDXID`, `spdxVersion`, `creationInfo`, `name`, `dataLicense`, `documentNamespace`, a required `packages` array and a `relationships` array. Each package entry is documented with `SPDXID`, `name`, `versionInfo`, `downloadLocation`, `filesAnalyzed`, `licenseConcluded`, `licenseDeclared`, `supplier`, `copyrightText` and `externalRefs`, the last an array of `{referenceCategory, referenceLocator, referenceType}` — the purl that identifies the component precisely enough to look its support dates up. `versionInfo` is the field this recipe turns on, and the documented behaviour behind it is the opposite of the one an earlier draft of this recipe assumed. It is REQUIRED on every package entry — the schema's required list is `SPDXID, name, versionInfo, downloadLocation, filesAnalyzed` — so a component never arrives without the field, and a clause counting the entries that lack one could never fire. What the page documents instead is the real failing case: "The version of the package. If the package does not have an exact version specified, a version range is given." An unpinned component is present, carries the field, and carries a RANGE, which is the shape the clause below enumerates. From `alerts-open` and `alerts-dismissed`, `dependency` (`package.ecosystem`, `package.name`, `manifest_path`, `scope`, `relationship`), `state` (`open | dismissed | fixed | auto_dismissed`), `dismissed_reason` (`fix_started | inaccurate | no_bandwidth | not_used | tolerable_risk`), `dismissed_comment` (documented required, string or null, capped at 280 characters), `auto_dismissed_at`, and `security_advisory` with `ghsa_id`, `cve_id`, `severity`, `classification` (`general | malware`), `cwes`, `published_at`, `updated_at`, `withdrawn_at` and a `vulnerabilities` array whose entries carry `vulnerable_version_range` and a `first_patched_version` documented "object or null". Beside `security_advisory`, and not to be confused with it, each alert carries a required `security_vulnerability` object of its own — `package`, `severity`, `vulnerable_version_range` and its own `first_patched_version`, same "object or null" — and THAT is the entry pertaining to the alerted component, where `security_advisory.vulnerabilities[]` enumerates every affected range across every ecosystem the advisory covers. The no-patch clause below reads the former for that reason. The `has` filter is documented as supporting only `patch` on the REPOSITORY form and is left unenumerated on the organization form this recipe calls, so on neither form is there a documented way to select the alerts that lack a fix; the no-patch narrowing is therefore a client-side filter over a full paginated walk, and a collector that reads one page of thirty has produced a smaller answer rather than a filtered one.
Assertions — what makes it a pass
| Field | Must be | For | Proves |
|---|---|---|---|
| configurations[?target_type=='organization' && dependency_graph=='enabled'] | [0].id | existsAt least one code security configuration the organization itself owns sets `dependency_graph` to `enabled`. Every other clause in this recipe is an offender count, and an organization that has never created a configuration returns an empty list for all of them: no configuration is enumerated, no repository is walked, no SBOM is exported, no alert is raised, and six `count_eq 0` clauses go green on a boundary where nothing was ever switched on. This is the positive clause that makes that state fail, and it is the same guard the three sibling recipes reading this report already carry — its absence here was the defect, not its presence there. The field is three-state and the middle value is the trap: `not_set` is neither on nor off, and a clause written against `disabled` passes an organization that never decided. It says a configuration exists and decided; it does not say which repositories it reaches, and repository-level enablement bypasses configurations entirely. | every row | SA-22 |
| configurations[?target_type=='organization' && dependency_graph!='enabled'] | count_eq 0No configuration the organization ITSELF OWNS leaves the dependency graph unenabled. The `target_type` narrowing is deliberate and matches the sibling code-scanning recipe: a provider cannot edit a global or enterprise-owned configuration, so failing it for one would be failing it for a decision it has no permission to make. This is the negative half of the clause above and is not the precondition on its own: an offender count over an empty configuration list is green, which is exactly why the existence clause precedes it. What it adds is the case where a configuration DOES exist and leaves the graph off — there are then no packages to export, `sbom` is empty rather than wrong, and every clause below would be vacuously green. | every row | SA-22 |
| configurations[?target_type=='organization' && dependabot_alerts!='enabled'] | count_eq 0No organization-owned configuration leaves Dependabot alerts unenabled. Asserted separately from the graph clause above because the two settings have DIFFERENT documented defaults — `dependency_graph` defaults to `enabled` and `dependabot_alerts` to `disabled` — so the common state is a repository whose components are resolved and whose advisories are never raised. That repository appears complete in the inventory half of this recipe and contributes nothing to the alert half, which is the quietest way this evidence can be half-true. | every row | SA-22 |
| configuration-repositories-all[?status=='failed'] | count_eq 0No repository the configuration was applied to failed to receive it. `failed` is the status that produces silence rather than an error: the repository is attached in intent, resolves no dependency graph, exports no packages and raises no alerts, so the boundary's inventory is short by exactly that repository's components and nothing in the totals says so. It reads `configuration-repositories-all` and NOT the enumeration report, and that is a correction rather than a detail — the enumeration command narrows `status` to `attached,enforced`, which filters out the very row this clause exists to count, and a clause pointed at it would be unfailable by construction. The documented default for `status` is `all`, which is what the third command relies on. | every row | SA-22 |
| sbom.sbom.packages[?contains(versionInfo,'>') || contains(versionInfo,'<') || contains(versionInfo,'^') || contains(versionInfo,'~') || contains(versionInfo,'*') || contains(versionInfo,',') || contains(versionInfo,' ')] | count_eq 0No component in this repository's exported inventory arrives with a version RANGE instead of a pinned version. This is the clause SA-22 turns on and it took two corrections to write. The first is the path, and it is the one that mattered most: the root token is the REPORT name and the response's own top-level key is `sbom` again, because the SPDX document arrives nested under a required `sbom` key, so the clause reads `sbom.sbom.packages`. Written at `sbom.packages` it resolved to nothing, and an offender count over nothing is zero, which is green — the recipe's own centre-of-gravity clause was unfailable on every estate. The second is the field: an earlier form counted packages whose `versionInfo` was null, which could never fire, because GitHub documents `versionInfo` in the package object's required list. The documented failing case is the other one — "If the package does not have an exact version specified, a version range is given" — so the unpinned component is PRESENT, carries the field, and carries a range, and a null-counting clause read it as green. A range cannot be looked up against a vendor's lifecycle policy, which is the whole question SA-22 asks, so it is the failing row. State plainly what this form costs: the assertion grammar has no "is not an exact version" operator, so the clause enumerates the characters a range spelling uses and a range spelled some other way passes. That residue is a property of the grammar and is named here rather than hidden, which is the difference between a heuristic and an over-claim. | every row | SA-22 |
| alerts-open[?security_vulnerability.first_patched_version==`null`] | count_eq 0No open alert names a component for which the ecosystem has published no fixed version. The alert carries its OWN required `security_vulnerability` object — `package`, `severity`, `vulnerable_version_range` and a `first_patched_version` documented "object or null" — and that object is the entry pertaining to the alerted component. An earlier form of this clause read `security_advisory.vulnerabilities[]` instead and counted an alert whose ANY entry lacked a patch: that array enumerates every affected range across every ecosystem the advisory covers, so an advisory patched for this component and unpatched for some other one fired it. The clause over-fired rather than under-fired, which is the safe direction and is why it is listed third of three corrections rather than first, but it was not asking the question the description claimed. Offender form over a list built to hold offenders, and evaluated client-side: the `has` filter is documented as supporting only `patch` on the repository form and is left unenumerated on the organization form this recipe calls, so there is no documented way to select the alerts WITHOUT a fix and the narrowing needs the full paginated walk the command performs. Read the result as a hint that a lifecycle review is owed on those packages, never as the finding that they are past end of support; `scan_scope` names the list that decides that and it is not in this output. | every row | SA-22 |
| alerts-dismissed[?(dismissed_reason=='no_bandwidth' || dismissed_reason=='tolerable_risk') && dismissed_comment==`null`] | count_eq 0No alert was dismissed for lack of capacity or as tolerable risk without a written justification. These are the two documented reasons that mean the component STAYS, so this clause marks the population that was knowingly not replaced — which is the set SA-22's second limb then has to answer for. `dismissed_comment` is documented required, string or null, capped at 280 characters, so the literal-null comparison catches both an explicit null and an absent key and the failing row is present-and-false rather than dropped. What this establishes is narrow and the note says so: a typed comment records that somebody chose to keep the component, and it is evidence of neither replacement nor of an alternative support source having been arranged, which is what the control actually asks for. | every row | SA-22 |
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:SA 4/25 →
Outside the boundaryGitHub Enterprise Cloud
The dependency resolver, the component inventory it produces and the advisory database the alerts are drawn from are all held and operated by a third party, so reading them brings the platform into the assessment as an information resource under SA-09 and CA-03 and into the external-system inventory AC-20 covers. SA-22 makes that dependency unusually pointed, because the control is ABOUT depending on components somebody else does or does not still maintain, and this evidence answers it by depending on a component somebody else maintains: what counts as a known weakness in a package is decided by an advisory database the provider does not write or version, and a re-review or a withdrawal there changes what this output says without anything in the provider's system changing. SA-22 sits in the class b, class c and class d baselines, so it reaches every reader of this product including Low systems, and the impact level a platform's Marketplace listing carries is not necessarily the one a given system needs — that is the SA-09 question, it is answered by reading the cited listing rather than by this sentence, and no value for it is written here because it is a dated fact that changes. This recipe was authored against GitHub Enterprise Cloud; github.com and the data-residency offering are different deployments on different infrastructure.
Notes & assertions
SA-22 asks two things: that unsupported components are replaced, and that alternative sources of continued support are provided for the ones that are not — in-house support, or an external provider the organization names. This plane can see the population and cannot see either answer, which is what `partial` records. An earlier draft of this note said the second limb was documented justification and approval; that is the shape of legacy baseline supplemental guidance rather than of the control, this repo's own dataset carries no guidance for SA-22 at all, and the difference matters here because the platform DOES hold a justification artifact and holds nothing whatsoever about an alternative support arrangement. Getting that wrong would have made the dismissal clause below look like it closed a limb it does not touch. WHY THIS IS A DIFFERENT RECIPE FROM THE DEPENDENCY-VULNERABILITY ONE AND NOT A SECOND VIEW OF IT. `dependency-vulnerability-monitoring` asks whether known-vulnerable components are found and fixed; this asks whether the provider knows what it ships and whether any of it has been abandoned. The two questions overlap in their telemetry and diverge in their failure cases, and the divergence is the point: a component with no advisories at all is clean by the first question and is precisely the profile of an unmaintained package by the second, because an advisory exists when somebody researches a package and nobody researches a dead one. That is why the inventory clause rather than the alert clauses is the centre of this recipe. THE NO-PATCH CLAUSE IS A HINT AND IS DELIBERATELY NOT WRITTEN AS A VERDICT. An open alert whose advisory carries no `first_patched_version` on any entry is the strongest end-of-support signal the documented API emits — nobody shipped a fix — and it is still not the control's finding. It is equally the shape of an advisory published hours ago, of a dispute upstream, and of a maintainer who fixed the issue without cutting a release. It is asserted because a growing set of them is a real and readable finding about the boundary, and it is described here as a hint because reading it as "these components are past end of support" would be authoring the reconciliation `scan_scope` says nobody has done. WHAT THE DISMISSAL CLAUSE DOES AND DOES NOT ESTABLISH. `dismissed_reason` of `no_bandwidth` or `tolerable_risk` on an alert nobody can patch is the platform's record that a component was knowingly KEPT, and that is its whole value: it enumerates the components SA-22's second limb is about, which is a real service and is not the limb itself. Nothing in this output says whether in-house support was arranged for any of them or whether an external provider was named, and no field on this endpoint could. The clause is worth asserting because a dismissal carrying an empty comment is unambiguously worse than one carrying a reason, and it is worth saying plainly that passing it establishes neither replacement nor alternative support. THE `withdrawn_at` FIELD IS COLLECTED AND NOT ASSERTED, AND THE REASON IS THE SAME ONE THAT KEEPS THE EXTERNAL-SYSTEM NOTE SHARP. An advisory can be withdrawn after this evidence was collected, which retroactively changes what a dated report meant. Nothing in the provider's system moved. It is read so a human comparing two months of this report can tell a fixed component from a withdrawn advisory, and it is not asserted because a recipe that failed on withdrawn advisories would be failing the provider for the database's corrections. CADENCE IS `monthly` RATHER THAN `continuous`, AND THAT IS A CLAIM ABOUT THE HUMAN STEP RATHER THAN ABOUT THE PLATFORM. The alert stream underneath is continuous and the sibling recipe on SR-06 collects it that way. What SA-22 asks for is a review of an inventory against published lifecycle dates, and that reconciliation is an act somebody performs on a schedule; exporting the SBOM is the same kind of act. A provider running it continuously has not done anything wrong, and one collecting the alerts continuously while never exporting the inventory has met the sibling recipe and not this one. KSI-SCR-MIT is the only indicator that reaches this control, and it is claimed for the identification limb of its own statement — persistently identify, review and mitigate potential supply chain risks — with the review and mitigation limbs left to the human step `scan_scope` names.
Scanned population
Three lists, all held OUTSIDE the platform, and this control needs all three. First, the repositories inside the authorization boundary, from the component inventory the provider maintains for CM-08. The first command returns one organization's view of itself, and a boundary repository owned by a second organization, hosted elsewhere or mirrored in is absent from that response rather than false — and `dependency_graph` defaults to `enabled` while `dependabot_alerts` defaults to `disabled`, so the common failure here is a repository whose components ARE resolved and whose advisories are not raised. Second, and specific to SA-22, THE PUBLISHED SUPPORT-LIFECYCLE STATEMENTS for the components the SBOM names. Nothing in any response here carries an end-of-support date. The advisory database says a version has a known weakness; it does not say the vendor stopped issuing fixes for the branch, and the two are different facts that come apart in both directions — a supported component can carry a critical advisory, and an abandoned one can carry none at all because nobody is looking. The reconciliation between `packages[].name` plus `versionInfo` and each vendor's own lifecycle policy is the step that produces SA-22's verdict, and it is a step no command in this recipe performs. Third, the parts of the boundary that never appear in a manifest at all. The dependency graph is manifest- and lock-file-driven per ecosystem, and the components SA-22 is most often about are exactly the ones outside that: the operating-system packages baked into a base image, an appliance's firmware, the engine version of a managed database, a vendored source drop, a binary committed to the repository, and any ecosystem the graph does not support. They are absent from `packages[]` rather than reported unsupported, and an SBOM read as a boundary inventory is the single most likely way this recipe is misused. The ecosystem coverage is uneven in a second way that matters for the version question specifically. GitHub's supported-ecosystems page recommends, per ecosystem, the files that "explicitly define which versions are used for all direct and all indirect dependencies", and it recommends a lock file for most of them — including OpenTofu, whose recommended file is `.terraform.lock.hcl`. Gradle is the one row in that table with no recommended file at all unless dependencies are submitted through the automatic-submission action, and a project resolving from a bare `Gemfile` or an unpinned manifest is the same case a row down. On those the indirect components arrive with a version RANGE rather than a pinned version, which is exactly what the version clause below is written to make visible instead of silent.
- configurations
- configuration-repositories
- sbom
References
- GitHub REST: export a software bill of materials for a repository — GET /repos/{owner}/{repo}/dependency-graph/sbom, returning an SPDX document under a required `sbom` key with required `SPDXID`, `spdxVersion`, `creationInfo`, `name`, `dataLicense`, `documentNamespace` and `packages`; each package documented with `name`, `versionInfo`, `downloadLocation`, `filesAnalyzed`, `licenseConcluded`, `licenseDeclared`, `supplier`, `copyrightText` and `externalRefs` entries of `{referenceCategory, referenceLocator, referenceType}`. Read access to the repository is what the endpoint requires, and there is no organization-scoped form https://docs.github.com/en/rest/dependency-graph/sboms
- GitHub REST: Dependabot alerts — GET /orgs/{org}/dependabot/alerts and the repository form; `state` open | dismissed | fixed | auto_dismissed, `dismissed_reason` fix_started | inaccurate | no_bandwidth | not_used | tolerable_risk, `dismissed_comment` documented required, string or null, max 280 characters, and `security_advisory.vulnerabilities[]` carrying `vulnerable_version_range` and a `first_patched_version` documented "object or null". The `has` filter is documented as supporting only `patch` on the repository form and is left unenumerated on the organization form this recipe calls, which is why the no-patch narrowing is client-side on either. Organization owner or security manager, `security_events` scope https://docs.github.com/en/rest/dependabot/alerts
- GitHub REST: code security configurations — `dependency_graph` enabled | disabled | not_set defaulting to ENABLED and `dependabot_alerts` the same enum defaulting to DISABLED, the asymmetry two clauses in this recipe are written around; `target_type` global | organization | enterprise, `enforcement` enforced | unenforced, and the repositories endpoint whose `status` accepts all | attached | attaching | detached | removed | enforced | failed | updating | removed_by_enterprise and defaults to `all` https://docs.github.com/en/rest/code-security/configurations
- GitHub: dependency graph supported package ecosystems — the per-ecosystem manifest and lock files the graph recognises, and its own statement that the recommended files "explicitly define which versions are used for all direct and all indirect dependencies". Read for what it does NOT recommend: Gradle carries no recommended file unless dependencies arrive through automatic submission, and a project resolving from an unpinned manifest is the case where an indirect component reaches the SBOM as a version range rather than a pinned version https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/dependency-graph-supported-package-ecosystems
- GitHub: exporting a software bill of materials for your repository — the SBOM as "an inventory of a project's dependencies and associated information such as versions, package identifiers, licenses, transitive paths, and copyright information", and its documented exclusion that "SBOMs do not include dependents (other projects that rely on your project)" https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/exporting-a-software-bill-of-materials-for-your-repository
- FedRAMP Marketplace: GitHub Enterprise Cloud — the listing to re-read rather than quote, and the place to check the impact level against the system this recipe is being run for; SA-22 reaches class b, c and d, so the gap between a product's listed level and a reader's own is the SA-09 question this recipe's external-system note raises and does not answer https://www.fedramp.gov/marketplace/products/FR1812058188/
This pipeline mapping is authored opinion (overlay v0.8.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.continuousacquisition-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.you are heremonthlyunsupported-component-inventory-and-lifecycle-reviewGitHub dependency graph · GitHub Dependabot · GitHub code security configurations