get2knowio / get2knowio/hangar

Add a `dependency_graph` check: verify the Dependency graph feature is enabled (not just the dependency-review workflow)

Open
#110 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Python
Stars
0
Forks
0
Avg merge
22h 46m
Merged PRs (30d)
16

Description

## Summary

Hangar has **no check that verifies the GitHub *Dependency graph* feature is enabled** on a repo. The two adjacent Supply-chain checks each cover something else:

- `dep_review` ("Dependency review enabled") passes purely on the **presence of the `dependency-review-action`** in `.github/workflows/*` (see `_workflows_group` in `providers/github/detection.py`). It never checks whether the graph the action depends on is actually on.
- `dependabot_alerts` reads the `vulnerability-alerts` endpoint (204/404) — a **different** feature, and (see below) not a reliable proxy for the graph being enabled.

The result is a blind spot: a repo can show **`dep_review` ✅ and `dependabot_alerts` ✅** while the `dependency-review` workflow **fails at runtime** with *"Dependency review is not supported on this repository. Please ensure that Dependency graph is enabled."*

## Evidence this is real

- **`get2knowio/remo`**: had the `dependency-review-action` wired up (so `dep_review` would pass) and `vulnerability-alerts` returned `204` (so `dependabot_alerts` would pass), yet every PR's `dependency-review` check failed because the Dependency graph feature was disabled. Enabling *Settings → Advanced Security → Dependency graph* was the only fix.
- **Hangar's own #62** already documents the same symptom on the hangar repo:
> **Enable Dependency graph** … The workflow currently fails with "Dependency review is not supported on this repository." … Hangar's `dep_review` check passes on the workflow's presence regardless, but the workflow itself only goes green once this is on.

#62 tracks *manually remediating hangar's own repo*; this issue is the **product gap** — teaching Hangar to *detect* the state across every managed repo.

## Proposed change — add a `dependency_graph` check

**1. Check definition** — `domain/checks/supply_chain.py`, group `Supply chain`:

```python
Check(
id="dependency_graph", label="Dependency graph enabled", group=_G,
tier=RemediationTier.link, required_capabilities=caps_for_tier(RemediationTier.link),
evidence_fail="Dependency graph feature disabled (dependency-review cannot run)",
doc_url="https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-the-dependency-graph",
),
```

It complements `dep_review`: `dep_review` = the action is wired up; `dependency_graph` = the feature the action needs is actually on.

**2. Detection** — `providers/github/detection.py`, a new group gathered alongside `_dependabot_alerts_group`. The graph's enablement is **not** cleanly exposed as a per-repo `security_and_analysis` field, so probe an endpoint that only works when it's on. Two options (implementer's call, matching Hangar's "honest `unknown`, never fabricate a pass" rule):

- **SBOM** `GET /repos/{owner}/{repo}/dependency-graph/sbom` — `200` → pass; `403`/undeterminable → `unknown`. Caveat: a fresh-enabled repo can `404` briefly before the first scan, so treat bare `404` cautiously.
- **Compare** `GET /repos/{owner}/{repo}/dependency-graph/compare/{base}...{head}` — this is what the `dependency-review` action itself calls; it returns a distinct "not supported" error when the graph is off, which is the most faithful signal. Needs two refs (e.g. `default_branch~1...default_branch`).

⚠️ **Do not** piggyback on the `dependabot_alerts` (`vulnerability-alerts`) signal: on `remo` that endpoint returned `204` (alerts "enabled") while the graph was genuinely off, so it is not a reliable proxy.

**3. Remediation tier = `link`, not `settings_patch`.** There is **no reliable REST API to auto-enable the graph per repo**:
- `PATCH /repos/{o}/{r}` with `security_and_analysis.dependency_graph` is **silently ignored** (verified — no effect).
- `POST /orgs/{org}/dependency_graph/enable_all` returns `204` but is **org-scoped** and effectively a **no-op on free-plan orgs** (verified on `get2knowio`).

So it must deep-link the operator, consistent with how `secret_scanning`/`code_scanning` are handled. Add to `adapter.py`'s `deep_link`:

```python
"dependency_graph": "/settings/security_analysis",
```

(Per `_apply_settings`' own contract, a `settings_patch` that can't converge "would be a silent no-op that falsely reports success" — this check must stay `link`.)

**4. Gitea** — `providers/gitea/detection.py`: no dependency-graph feature, so mark `dependency_graph` as `unknown`/unsupported alongside `dependabot_alerts`.

**5. Tests / seed** — extend the GitHub detection tests (enabled → pass, disabled → fail, 403/no-capability → `unknown`) and add the id to any seed fixtures.

## Acceptance criteria

- [ ] `dependency_graph` check appears in the Supply-chain group.
- [ ] Detects enabled (pass) / disabled (fail) / undeterminable (unknown) on GitHub, capability-gated.
- [ ] Gitea reports it `unknown` (unsupported).
- [ ] Remediation deep-links to `…/settings/security_analysis` (link tier; no false-success settings_patch).
- [ ] Running Hangar against `get2knowio/remo` (graph now enabled) passes, and would have **failed** before it was enabled — i.e. it catches the exact state `dep_review` misses.

_Related: #62 (manual remediation checklist that first surfaced this on the hangar repo)._

Contributor guide

Open the contributing guide

Research direction

Start with the Supply chain checks in domain/checks/supply_chain.py and the adjacent detection logic in providers/github/detection.py. Review the existing GitHub detection tests, providers/gitea/detection.py, and adapter.py's deep_link handling. Done means the check reports enabled, disabled, or unknown appropriately, remains unsupported on Gitea, and links to settings/security_analysis without a false-success patch.

Written by the indexing model from the issue text.

Assessment

Tech stack
github, python
Domain
api, backend, devtools
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.