From 4356c823d64bcb210dbfd344fa8e401a2bc08453 Mon Sep 17 00:00:00 2001 From: bgard68 <30295154+bgard68@users.noreply.github.com> Date: Mon, 24 Aug 2026 11:34:14 -0500 Subject: [PATCH] feat: scan any public repository by name, anonymously MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Type owner/repository, get per-file deterministic findings. The demo asked a visitor to paste YAML; this asks for a name and nothing else — the same fetch path the 564-workflow field scan already proved, now a product surface. The quota is the design constraint. GitHub allows 60 unauthenticated API calls per hour per source address, shared by every visitor this host serves. So the directory listing is the only metered call — file bodies come from raw.githubusercontent.com, which is not counted — and every outcome is cached, failures included: a repository that does not exist is an answer worth remembering, or one stranger retrying a typo drains the hour for everyone. Exhaustion is reported as exhaustion, not as a missing repository. The trust boundary widens by one stated step and no more. The middleware's justification for anonymous access was "no outbound call"; this endpoint makes one, so the amended boundary is written down where the old one was: only api.github.com and raw.githubusercontent.com, no credential attached, read-only by construction. Owner and repository names are validated against GitHub's own shape before they touch a URL. Private repositories cannot appear — an anonymous request cannot see them, which is why this needs no allowlist while the GitHub App integration does. Limits are counted, not silent: files beyond the 30-file cap or the 100k character cap are reported as skipped. The UI grows a third tab beside Simulation and GitHub Sandbox. Its tests caught a real race on the way in: the scenario-loading effect's promise could resolve after a tab switch and wipe newer results via resetResults(). The effect now cancels on cleanup, so a stale response is a no-op. 218 backend tests and 22 frontend tests pass. Co-Authored-By: Claude Opus 5 --- Directory.Packages.props | 1 + .../Endpoints/PublicScanEndpoints.cs | 74 ++++++ src/DevSecOpsSentinel.Api/Program.cs | 16 ++ .../PublicScanContracts.cs | 69 ++++++ .../DevSecOpsSentinel.Infrastructure.csproj | 1 + .../GitHub/PublicRepositoryScanner.cs | 227 ++++++++++++++++++ src/devsecops-sentinel-web/src/App.tsx | 60 ++++- .../src/PublicScan.test.tsx | 147 ++++++++++++ src/devsecops-sentinel-web/src/api.ts | 24 ++ src/devsecops-sentinel-web/src/models.ts | 17 ++ .../PublicScanEndpointTests.cs | 118 +++++++++ .../PublicRepositoryScannerTests.cs | 220 +++++++++++++++++ 12 files changed, 966 insertions(+), 8 deletions(-) create mode 100644 src/DevSecOpsSentinel.Api/Endpoints/PublicScanEndpoints.cs create mode 100644 src/DevSecOpsSentinel.Application/PublicScanContracts.cs create mode 100644 src/DevSecOpsSentinel.Infrastructure/GitHub/PublicRepositoryScanner.cs create mode 100644 src/devsecops-sentinel-web/src/PublicScan.test.tsx create mode 100644 tests/DevSecOpsSentinel.Api.Integration.Tests/PublicScanEndpointTests.cs create mode 100644 tests/DevSecOpsSentinel.Infrastructure.Tests/PublicRepositoryScannerTests.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index 107a44a..8d0c91f 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -8,6 +8,7 @@ +