Skip to content

feat(sbom): add 'Cloud Run' deployment platform marker (#220) - #249

Open
nikhilpatidar wants to merge 2 commits into
NuGuardAI:mainfrom
nikhilpatidar:bug/gcp-cloud-run-detection
Open

feat(sbom): add 'Cloud Run' deployment platform marker (#220)#249
nikhilpatidar wants to merge 2 commits into
NuGuardAI:mainfrom
nikhilpatidar:bug/gcp-cloud-run-detection

Conversation

@nikhilpatidar

@nikhilpatidar nikhilpatidar commented Aug 10, 2026

Copy link
Copy Markdown

PR Type

  • Bug fix
  • Feature

What

Adds a more specific Cloud Run deployment-platform marker alongside
the existing coarse GCP marker. The marker fires when any of:

  • the Knative Cloud Run service API appears in a YAML manifest
    (apiVersion: serving.knative.dev/v1),
  • the official google-github-actions/deploy-cloudrun GitHub Actions
    step appears in a workflow,
  • any run.googleapis.com annotation is present,
  • a *.a.run.app runtime URL appears in the file content, or
  • a file path contains the substring cloudrun.

Why

Issue #220 reports that nuguard's GCP discovery is too coarse. The
existing GCP marker fires for any GCP-related content (gcloud, Cloud
Functions, Vertex AI, generic gcr.io references) without
distinguishing Cloud Run, which is the most common serverless
deployment target for AI apps today. Downstream analyzers and reports
that want to surface Cloud Run-specific concerns (e.g. unauthenticated
invoke URLs, IAM conditions for service-to-service calls) had no
programmatic way to tell those scans apart from generic GCP scans.

Root cause

extract_deployment_context in
nuguard/sbom/core/application_summary.py had no Cloud Run-specific
trigger. The coarse GCP marker fired on gcloud, cloud run,
cloudrun, vertex ai, etc. but those inputs are also common for
non-Cloud-Run GCP services, so a downstream consumer cannot tell which
deployment target is actually in use.

Changes

  • nuguard/sbom/core/application_summary.py — adds a second platform
    block in extract_deployment_context that appends Cloud Run to the
    platform list when any of the five triggers above fire.
  • tests/sbom/test_cloud_run_detection.py — 6 new regression tests
    pinning the contract end-to-end through
    extract_deployment_context:
    • Knative Service YAML → Cloud Run + GCP + Kubernetes
    • Deduplication when multiple triggers fire
    • GitHub Actions deploy-cloudrun step → Cloud Run + GCP +
      GitHub Actions
    • *.a.run.app URLs captured as deployment_urls
    • File path with cloudrun substring triggers the marker
    • Negative: plain Kubernetes manifest is NOT marked as
      Cloud Run (so we don't over-fire)

Tests

  • tests/sbom/test_cloud_run_detection.py: 6 new tests, all passing.
  • tests/sbom/ full suite: 188 tests passing.
  • ruff check clean.
  • mypy clean on the touched module.

Backward compatibility

  • The GCP marker continues to fire in parallel — Cloud Run is a
    strict subset of GCP, so downstream consumers reading GCP keep
    working.
  • Platforms are already deduplicated by the existing _uniq(...) call
    on the platform list, so a single scan produces at most one
    Cloud Run and one GCP entry even when multiple triggers match.
  • No public function signatures change; only the contents of one
    returned list (deployment_platforms) gain an additional possible
    entry.

What this PR does NOT do (issue #220 remains open)

This PR is the narrow, regression-pinning slice of #220 — adding the
marker and the tests. The following remain on the issue tracker for
follow-up PRs:

  • Broader cookbook validation across all three clouds (Python / JS-TS /
    Go AI apps on AWS / Azure / GCP) — the request in [Feature]: Extending AI-BOM support #220's "Possible
    Solution" list.
  • More sophisticated Cloud Run URL reconstruction from
    K_SERVICE / GOOGLE_CLOUD_PROJECT env vars (the GitHub Actions
    AWS App Service equivalent is implemented for Azure but not yet for
    Cloud Run).
  • GCP-specific configuration scanning (e.g. cloudbuild.yaml,
    app.yaml).
  • AWS and Azure parity improvements for issue [Feature]: Extending AI-BOM support #220's complaint.

This PR deliberately does not use the Closes #220 syntax,
because GitHub's auto-close behaviour does not understand the
"partial" qualification; the issue should remain open until the
broader cookbook-validation work is done.

Addresses part of #220

Issue NuGuardAI#220 reports that nuguard's GCP discovery is too coarse — the
existing 'GCP' marker fires for any GCP-related content (gcloud, Cloud
Functions, Vertex AI, generic gcr.io references) without distinguishing
Cloud Run, the most common serverless deployment target for AI apps.

This change adds a more specific 'Cloud Run' platform marker that fires
when the scan finds:

* the Knative Cloud Run service API in a YAML manifest
  (apiVersion: serving.knative.dev/v1),
* the official google-github-actions/deploy-cloudrun GitHub
  Actions step,
* any run.googleapis.com annotation,
* a *.a.run.app runtime URL inside the file content, or
* a file path containing cloudrun.

The existing 'GCP' marker continues to fire in parallel — Cloud Run is a
strict subset of GCP. Platforms are already deduplicated by _uniq,
so a single scan produces at most one 'Cloud Run' and one 'GCP' entry
even when multiple triggers match.

This is the narrow, regression-pinning slice of NuGuardAI#220 that fits in one
PR. Broader cookbook validation across all three clouds remains on the
issue tracker.

Tests: tests/sbom/test_cloud_run_detection.py (6 tests) pins the new
behaviour end-to-end through extract_deployment_context:

* Knative Service YAML → 'Cloud Run' + 'GCP' + 'Kubernetes' platforms
* Deduplication when multiple triggers fire
* GitHub Actions deploy-cloudrun step → 'Cloud Run' + 'GCP' + 'GitHub
  Actions' platforms
* *.a.run.app URLs captured as deployment URLs
* File path with 'cloudrun' substring triggers the marker
* Plain Kubernetes manifest is NOT marked as 'Cloud Run' (negative test)

All 188 tests in tests/sbom/ pass. ruff and mypy clean.
@nikhilpatidar
nikhilpatidar force-pushed the bug/gcp-cloud-run-detection branch from f096e46 to 0c6742b Compare August 10, 2026 16:48
KanishkThamman
KanishkThamman previously approved these changes Aug 11, 2026

@KanishkThamman KanishkThamman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additive, no schema impact. One nit inline on a false-positive trigger.

# GitHub Actions deploy step (issue #220 — these are the two
# most common ways an AI app ships to Cloud Run).
if (
"serving.knative.dev" in text_lower

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Knative Serving is open source and commonly self-hosted on plain GKE/EKS/AKS, so this trigger alone isn't Cloud-Run-specific and could mislabel a self-hosted Knative-on-GKE deployment as "Cloud Run". Worth a negative test case.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 20c00e3. Split the Cloud Run trigger into a weak signal (the Knative service API) and a set of strong signals (deploy-cloudrun GitHub Action, run.googleapis.com annotation, *.a.run.app URL, 'cloudrun' in path). The marker now fires only when a strong signal is present, OR when the Knative service API appears together with a run.googleapis.com / *.a.run.app co-signal.

Added two tests to test_cloud_run_detection.py:

  • test_self_hosted_knative_service_is_not_marked_as_cloud_run: bare Knative Service YAML without any co-signal must NOT be marked Cloud Run (the exact regression).
  • test_knative_service_with_run_app_url_is_marked_as_cloud_run: Knative Service + a *.a.run.app URL in a separate file IS marked Cloud Run (pins the co-signal path).

All 6 existing tests still pass — the original positive case already includes run.googleapis.com alongside serving.knative.dev, so it satisfies the new co-signal requirement.

The Cloud Run platform marker fired on any file containing
`serving.knative.dev` because that was OR'd with the strong
Cloud Run-specific signals. Knative Serving is open source and
commonly self-hosted on plain GKE/EKS/AKS, so a bare
`serving.knative.dev/v1` Service manifest is not Cloud-Run-specific.
A self-hosted Knative-on-GKE deployment would have been
mis-labelled as 'Cloud Run'.

Fix: split the trigger into a weak signal (the Knative service API)
and a set of strong signals (deploy-cloudrun GitHub Action,
`run.googleapis.com` annotation, `*.a.run.app` URL, 'cloudrun' in
path). Mark as 'Cloud Run' only when:
- a strong signal fires, OR
- the weak Knative signal fires together with a Cloud Run
  co-signal (`run.googleapis.com` annotation or `*.a.run.app` URL).

Tests:
- test_self_hosted_knative_service_is_not_marked_as_cloud_run:
  bare Knative Service YAML without co-signal must NOT be marked
  Cloud Run (the regression).
- test_knative_service_with_run_app_url_is_marked_as_cloud_run:
  Knative Service + a `*.a.run.app` URL in a separate file IS
  marked Cloud Run (pins the co-signal path).
- All 6 existing tests still pass — the existing positive case
  already includes `run.googleapis.com` alongside `serving.knative.dev`,
  so it satisfies the new requirement.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants