NuGuard AI SBOM Schema
This document describes the canonical AI-SBOM document shape used by NuGuard. The schema is defined by AiSbomDocument in the Pydantic models and enforced by the bundled JSON Schema at nuguard/sbom/schemas/aibom.schema.json.
Use this as a reference when writing code that reads or generates AI-SBOMs directly (custom tooling, CI checks, framework adapters) — for running nuguard sbom generate itself, see the Quick Start Guide instead.
Current schema version: 1.7.0
Schema URI: https://nuguard.ai/schemas/aibom/1.7.0/aibom.schema.json
The schema is language-neutral. Current extractors normalize Python, TypeScript/JavaScript, Go, C#, and Java application evidence into the same nodes, edges, dependencies, and summary fields.
Application source and manifests
│
├── framework adapters ──→ nodes + evidence
├── relationship hints ──→ edges
├── package scanners ────→ deps
└── repository signals ──→ summary
Top-Level Object
| Field |
Type |
Required |
Description |
schema_version |
string |
- |
AIBOM schema version (semver). Default: "1.7.0" |
generated_at |
string (ISO 8601) |
yes |
UTC timestamp of generation |
generator |
string |
- |
Tool that produced the document. Default: "nuguard" |
target |
string |
yes |
Repository URL or local path that was scanned |
nodes |
Node[] |
- |
Detected AI components |
edges |
Edge[] |
- |
Directed relationships between components |
deps |
PackageDep[] |
- |
Package dependencies from manifests |
summary |
ScanSummary | null |
- |
Scan-level metadata: use-case summary, frameworks, modalities, API endpoints, deployment context, security posture, and SBOM 1.5.0 enrichment metrics |
relationship_graph_md |
string | null |
- |
Mermaid flowchart plus LLM-written narrative of key component relationships. Only populated when LLM enrichment is enabled during SBOM generation. |
discovered_profile |
object | null |
- |
Cached pre-scan identity discovery result (a serialized DiscoveredProfile), persisted here after a behavior/redteam run successfully discovers the authenticated test user's real identity via a live DISCOVER conversation. Later runs against this SBOM reuse it instead of re-running discovery. Delete or regenerate the SBOM to force a fresh discovery. |
{
"schema_version": "1.7.0",
"generated_at": "2026-06-08T00:00:00Z",
"generator": "nuguard",
"target": "https://github.com/org/repo",
"nodes": [],
"edges": [],
"deps": [],
"summary": null,
"relationship_graph_md": null,
"discovered_profile": null
}
Node
A Node represents a detected AI component, service boundary, infrastructure resource, policy surface, or artifact used by the application.
Java source scanning uses the same component types as every other language. Current Java adapters recognize Spring AI, LangChain4j, Quarkus LangChain4j, OpenAI Java, Azure OpenAI Java, AWS Bedrock, Google Gen AI, and Vertex AI, plus Spring MVC/WebFlux and JAX-RS/Quarkus endpoints. Consumers do not need a Java-specific schema branch.
| Field |
Type |
Required |
Description |
id |
UUID string |
- |
Stable UUID for edge references. Generated when omitted. |
name |
string |
yes |
Display name of the component |
component_type |
ComponentType |
yes |
Component category |
confidence |
float [0, 1] |
yes |
Extraction confidence |
metadata |
NodeMetadata |
- |
Typed and adapter-specific metadata. Empty object by default. |
evidence |
Evidence[] |
- |
Detection evidence supporting this node |
ComponentType values
| Value |
What it represents |
AGENT |
An LLM-backed agent, orchestrator, sub-agent, crew member, or assistant |
GUARDRAIL |
A safety check, topic filter, output validator, or content policy — covers framework-native guardrails (OpenAI Agents SDK, guardrails-ai, Claude Agent SDK hooks/can_use_tool, LangGraph human-in-the-loop, LangChain moderation chains), cloud-native guardrail products (AWS Bedrock Guardrails, Azure AI Content Safety/Prompt Shields, GCP Model Armor and Vertex/Gemini safety settings), and third-party AI-security vendors (Palo Alto Prisma AIRS, Protect AI Guardian, Presidio, llm-guard, Rebuff, NeMo Guardrails, Lakera) |
FRAMEWORK |
The agentic framework in use, such as LangGraph, CrewAI, OpenAI Agents, ADK, or MCP |
MODEL |
An LLM, embedding model, or model artifact reference |
TOOL |
A tool/function exposed to an agent |
DATASTORE |
A database, vector store, cache, or file store accessed by the app |
AUTH |
An authentication provider, middleware, or auth service |
PRIVILEGE |
A permission scope or privilege boundary |
API_ENDPOINT |
An HTTP or MCP endpoint exposed by the application |
DEPLOYMENT |
A cloud, container, Kubernetes, CI/CD, or runtime deployment resource |
PROMPT |
A system prompt, instruction template, backstory, or prompt file |
CONTAINER_IMAGE |
A Docker or OCI container image |
IAM |
An IAM role, policy, service account, managed identity, or role binding |
DEVELOPER_TOOL_CONFIG |
An AI coding-agent or editor configuration file committed to the repository, such as .claude/settings.json, CLAUDE.md, AGENTS.md, .mcp.json, or .cursor/ configs |
LIFECYCLE_SCRIPT |
An npm postinstall/preinstall/prepare script or a Python build hook (setup.py, pyproject.toml build-system hooks) that executes at install or build time |
GITHUB_WORKFLOW |
A GitHub Actions workflow file under .github/workflows/ |
MCP_SERVER |
An MCP server reference declared in .mcp.json or another AI-agent config file |
All fields are optional unless marked otherwise. Fields are populated by whichever adapter or enricher detected the node. Unused nullable fields are omitted from generated JSON.
Common and enrichment fields
| Field |
Type |
Description |
description |
string |
Human-readable component description. For TOOL nodes, usually extracted from function docstrings; for AGENT nodes, usually extracted from purpose/role text. |
descriptive_name |
string |
SBOM 1.5.0 LLM-generated human-readable label, e.g. "User Authentication API" |
loc |
integer |
SBOM 1.5.0 total lines of source code across the files where this component is defined |
dependency_names |
string[] |
SBOM 1.5.0 package names from manifests that appear in this component's source files |
instrumentation |
InstrumentationDetail |
SBOM 1.5.0 observability and monitoring tooling detected for this component |
testing |
TestingDetail |
SBOM 1.5.0 test coverage and CI/CD posture for this component |
extras |
object |
Adapter-specific key/value pairs, such as provider, model family, version, prompt content, or confidence breakdown |
AGENT and FRAMEWORK fields
| Field |
Type |
Description |
framework |
string |
Agentic framework, e.g. "langgraph", "crewai", "mcp-server" |
system_prompt_excerpt |
string |
First 500 chars of the agent's system prompt, instructions, or backstory. Used by red-team scenario generation. |
injection_risk_score |
float [0, 1] |
Pre-computed injection risk score set by the graph enricher. Derived from privileged tools, unauthenticated paths, reachable sensitive datastores, and unguarded HITL triggers. |
model_name |
string |
LLM or embedding model name, e.g. "gpt-4o", "gemini-2.0-flash" |
asm_summary |
AsmSummary |
Summarized, credential-redacted Agentic Surface Model facts from the live red-team surface prober. Written onto AGENT nodes only by nuguard redteam; absent from a plain sbom generate |
MODEL fields
| Field |
Type |
Description |
model_name |
string |
LLM, embedding model, or artifact name |
source_url |
string |
SBOM 1.5.0 model artifact origin URL, such as a Hugging Face repo, local path, or API base endpoint |
integrity_hash |
string |
SBOM 1.5.0 model artifact SHA-256 or git revision hash for supply-chain verification |
checksum |
string |
SBOM 1.5.0 model artifact checksum, such as md5, sha1, or sha256 |
| Field |
Type |
Description |
parameters |
ToolParameter[] |
Parameters accepted by this tool, from signatures and docstrings. Used by TOOL_ABUSE red-team scenarios. |
no_auth_required |
boolean |
True when the tool or endpoint is invocable without authentication |
high_privilege |
boolean |
True when the tool has access to administrative or cross-tenant resources |
sql_injectable |
boolean |
True when the tool constructs SQL from agent-provided string parameters |
ssrf_possible |
boolean |
True when the tool accepts URL parameters fetched server-side |
accepts_external_url |
boolean |
True when the tool has a URL or endpoint parameter passed to an outbound request |
reads_external_content |
boolean |
True when the tool fetches content from an external source, such as web, email, or GitHub |
mcp_server_url |
string |
URL of the MCP server this tool belongs to |
trust_level |
string |
MCP server trust: "trusted", "untrusted", or "n/a". External MCP servers are untrusted unless listed in redteam.mcp_trusted_servers in nuguard.yaml. |
GUARDRAIL fields
| Field |
Type |
Description |
rules_excerpt |
string |
Short description of the guardrail's rules, validator class, or blocking logic |
blocked_topics |
string[] |
Topics this guardrail is known to block |
blocked_actions |
string[] |
Actions this guardrail is known to block |
refusal_style |
string |
How this guardrail normally refuses, e.g. "hard_block", "redirect", "warn" |
In addition to the typed fields above, extras carries adapter-set identification fields for every GUARDRAIL node: extras.guardrail_type (e.g. "bedrock_guardrails", "content_safety", "prompt_shields", "model_armor", "vertex_safety_settings", "hooks", "can_use_tool", "human_in_the_loop", "moderation_chain", "prisma_airs", "protect_ai_guardian", "presidio", "llm_guard", "rebuff", "nemo_guardrails", "lakera_guard"), extras.vendor (e.g. "aws", "azure", "gcp") when the guardrail is a cloud product, and extras.detection_kind — "framework_native" for a real SDK class/method/import match, or "heuristic" for a lower-confidence match such as a REST-endpoint string (Prompt Shields, Lakera) or a kwarg-presence check (Vertex/Gemini safety_settings).
A GUARDRAIL node is connected to the AGENT node(s) it protects via a PROTECTS edge — see RelationshipType values below. Most frameworks bind a guardrail to an agent explicitly (e.g. OpenAI Agents SDK's input_guardrails=/output_guardrails=, Claude Agent SDK's hooks=/can_use_tool=); when no explicit binding exists in source, a structural fallback wires the GUARDRAIL node to AGENT node(s) detected in the same file, directory, or sharing a name token, at derivation: "fallback_heuristic".
PROMPT fields
| Field |
Type |
Description |
role |
string |
Prompt role, e.g. "system", "user" |
content |
string |
Full prompt/instructions text |
char_count |
integer |
Character count of content |
is_template |
boolean |
True when content contains {variable} placeholders |
template_variables |
string[] |
Template variable names found in content, e.g. ["user_name"] |
prompt_type |
string |
Prompt kind set by some adapters, e.g. "instructions", "agent_input" |
For backward compatibility, adapters also mirror these same values into extras (extras.role, extras.content, extras.char_count, extras.is_template, extras.template_variables) — new consumers should prefer the typed fields above.
A PROMPT node is connected to its owning AGENT or GUARDRAIL through a USES edge when the adapter identifies that relationship. For independently detected prompts, the extractor infers AGENT --USES--> PROMPT when the nodes share a source file with one identifiable agent, the prompt name identifies one agent in a multi-agent file, or that agent's file imports and uses the prompt constant. A guardrail that protects the agent also receives a derived GUARDRAIL --PROTECTS--> PROMPT edge when the guardrail binding is explicit or it shares the prompt's source file. Ambiguous prompts remain unlinked rather than being assigned to unrelated agents.
API_ENDPOINT fields
The name shown in the AIBOM uses the detected handler name when it is unique. If several endpoints have the same handler name, the extractor adds a short resource label from the route, such as Delete Notes and Delete Documents. The exact HTTP method and route remain in metadata.method and metadata.endpoint.
| Field |
Type |
Description |
endpoint |
string |
Endpoint address, e.g. "/chat" or "0.0.0.0:8080 (sse)" |
method |
string |
HTTP method: "GET", "POST", etc. |
transport |
string |
Transport protocol: "sse", "streamable-http", "stdio" |
server_name |
string |
Server display name, such as FastMCP name kwarg or inferred service name |
auth_required |
boolean |
True when this endpoint requires authentication |
auth_scope |
string |
OAuth2 scope or role required, e.g. "user", "admin", "none" |
accepts_user_input |
boolean |
True when user-controlled input is accepted in body or query params |
returns_sensitive_data |
boolean |
True when this endpoint returns PII, PHI, PFI, or other sensitive data |
rate_limited |
boolean |
True when rate limiting is configured |
rate_limit_detail |
RateLimitDetail |
SBOM 1.5.0 structured rate-limit configuration extracted from code or IaC |
operational |
boolean | null |
SBOM 1.5.0 liveness probe result: true when a live authenticated ping returned a reachable response (including a correctly-enforced 401/403); false when it hit a rotation-trigger 4xx (404/405/400/422) or a network failure; null when never probed |
liveness_checked_at |
string (ISO 8601) |
SBOM 1.5.0 timestamp of the last liveness probe |
liveness_notes |
string[] |
SBOM 1.5.0 notes from the last liveness probe (status codes, timeouts, rotation) |
security_headers_detail |
SecurityHeaderDetail |
SBOM 1.5.0 HTTP security-header posture extracted from code or IaC |
cors_policy |
CorsPolicyDetail |
SBOM 1.5.0 CORS configuration extracted from code or IaC |
debug_error_leak |
boolean |
SBOM 1.5.0 true when the app runs in a debug/verbose-error mode that leaks stack traces |
idor_surface |
boolean |
True when the endpoint has user- or tenant-scoped path params, e.g. {user_id} |
path_params |
string[] |
Path parameter names extracted from the URL template |
request_body_schema |
object |
Pydantic/dataclass field map: {field_name: type_string} |
request_schema |
object |
SBOM 1.5.0 request body JSON schema for API endpoints, keyed by Pydantic model class name |
response_schema |
object |
SBOM 1.5.0 response body JSON schema for API endpoints, keyed by Pydantic model class name |
chat_payload_key |
string |
Inferred primary prompt field in the request body, e.g. "message" or "query" |
chat_payload_list |
boolean |
True when the chat payload key is typed as a list |
response_text_key |
string |
Inferred primary response text field in the response body |
login_token_response_key |
string |
Dotted field path used to locate an authentication token in a login endpoint response, e.g. "access_token" or "tokens.accessToken". This stores only the field name, never the token value. extras.login_token_response_key_source records whether it came from static DTO extraction or LLM inference. |
context_payload_fields |
object |
Non-chat context fields detected in POST body schemas. Values are "identity" for static user/tenant/account identifiers or "session" for per-conversation identifiers. |
path_param_sources |
object |
Maps each entry in path_params to the API_ENDPOINT path that creates the identified resource, e.g. {"id": "/chat/conversations"} for /chat/conversations/:id/messages |
no_auth_required |
boolean |
True when the endpoint is invocable without authentication |
http_request.parameters[].identity_role |
string | null |
Identity-field tag on an HTTP input parameter: "subject_id" (caller/user identifier), "tenant_id" (tenant/org scope), "role_hint" (role/permission field), or "none". Null when not identity-related. Consumed by the red-team trust-context matrix |
http_request.parameters[].identity_role_evidence |
string | null |
How identity_role was derived: "name_match" (parameter-name heuristic) or "path_context" (a bare id path parameter under a users/accounts/tenants-style segment). Null when identity_role is unset |
http_request.parameters[].mass_assignment_risk |
boolean | null |
True when a client-supplied role_hint parameter is accepted on a write method (POST/PUT/PATCH) |
identity_binding |
string | null |
Where the caller's identity comes from: "client_supplied" (an identity parameter the caller controls), "credential_bound" (the handler resolves it from the credential, e.g. Depends(get_current_user)), or "mixed" |
object_id_semantics |
ObjectIdSemantics |
Object-ID format and enumerability facts for authorization-replay testing |
mutation_semantics |
MutationSemantics |
State-effect facts (mutation kind, idempotency, confirmation, rollback, audit) used to gate destructive pentest scenarios |
response_echoes_input |
boolean | null |
True when the framework's validation errors echo the submitted input (framework-level fact; FastAPI 422 responses) |
session_cookie_semantics |
SessionCookieSemantics |
Whether handler code is expected to issue session cookies. Only set for frameworks whose handlers are analyzed (Python, NestJS, Spring, ASP.NET) |
| Field |
Type |
Description |
hosted_by |
string |
SBOM 1.7.0 name of the workload (or workloads, comma-separated) whose source directory contains this component, from a HOSTS edge |
network_exposure |
string |
SBOM 1.7.0 API_ENDPOINT, AGENT and MCP_SERVER only: "public" (an internet-reachable port or ingress), "internal" (VNet/private ingress or loopback publish), "cluster" (cluster/compose-network only) or "unknown". The most exposed hosting workload wins; extras.exposure_by_host keeps the per-workload value |
DATASTORE fields
| Field |
Type |
Description |
datastore_type |
string |
Technology, e.g. "redis", "postgres", "pinecone" |
data_classification |
string[] |
PII/PHI/PFI classification labels detected in schemas |
classified_tables |
string[] |
SQL table or Python model names that carry sensitive fields |
classified_fields |
object |
Per-table mapping of sensitive field names to classification labels, e.g. {"patients": ["name", "dob"]} |
pii_fields |
string[] |
Flat list of general PII field names, e.g. ["name", "email", "phone"] |
phi_fields |
string[] |
Flat list of HIPAA-regulated PHI field names, e.g. ["diagnosis", "medication"] |
pfi_fields |
string[] |
Flat list of Personal Financial Information field names, e.g. ["card_number", "ssn", "account_balance"] |
access_type |
string |
Datastore access mode from the ACCESSES edge: "read", "write", or "readwrite" |
encryption_detail |
EncryptionDetail |
SBOM 1.5.0 encryption and redaction posture. New consumers should prefer this over the legacy encryption_at_rest boolean. |
data_handling |
DataHandlingDetail |
SBOM 1.5.0 retention, backup, anonymization, and consent posture |
AUTH fields
| Field |
Type |
Description |
auth_type |
string |
Authentication mechanism, e.g. "oauth2", "bearer", "api_key", "jwt" |
auth_class |
string |
Auth provider class name, e.g. "BearerAuthProvider" |
auth_detail |
AuthDetail |
SBOM 1.5.0 detailed authentication and authorization posture |
no_auth_required |
boolean |
True when this component allows unauthenticated access |
PRIVILEGE fields
| Field |
Type |
Description |
privilege_scope |
string |
Permission scope label, e.g. "db_write", "filesystem_read" |
DEPLOYMENT fields
| Field |
Type |
Description |
deployment_target |
string |
Cloud or container deployment target, e.g. "aws", "gcp", "kubernetes" |
cloud_region |
string |
Cloud region, e.g. "us-east-1", "eastus", "us-central1" |
availability_zones |
string[] |
Availability zones configured, e.g. ["us-east-1a", "us-east-1b"] |
secret_store |
string |
Secret management service, e.g. "aws_secrets_manager", "azure_key_vault", "gcp_secret_manager", "hashicorp_vault", "k8s_secret" |
encryption_at_rest |
boolean |
Legacy boolean: true when encryption-at-rest is explicitly configured in IaC |
encryption_key_ref |
string |
KMS key ARN, Key Vault URI, or CMEK resource reference |
encryption_detail |
EncryptionDetail |
SBOM 1.5.0 structured encryption and redaction posture |
ha_mode |
string |
High-availability topology: "multi-az", "replicated", "single" |
has_network_policy |
boolean |
SBOM 1.5.0 Kubernetes workload flag. True when covered by a NetworkPolicy resource in the same namespace. |
ingresses |
IngressDetail[] |
Externally reachable ingresses declared in IaC: reverse proxy/gateway, a backend exposed directly, or a static frontend. A gateway plus a direct entry across the document means one logical surface with an origin-bypass path |
workload |
WorkloadDetail |
SBOM 1.7.0 runtime shape of one deployed service: compose service, Kubernetes workload, container app, ECS service, Lambda, Cloud Run service, App Service. Present on per-workload DEPLOYMENT nodes; the per-file node keeps provider, region and posture |
cloud_provider |
string |
SBOM 1.7.0 provider of the workload: "aws", "azure", "gcp", "kubernetes" |
CONTAINER_IMAGE fields
| Field |
Type |
Description |
image_name |
string |
Container image name, e.g. "python" |
image_tag |
string |
Image tag, e.g. "3.12-slim" |
image_digest |
string |
Image digest, e.g. "sha256:abc..." |
registry |
string |
Registry host, e.g. "docker.io", "gcr.io" |
base_image |
string |
Full base image reference, e.g. "python:3.12-slim" |
runs_as_root |
boolean |
True when the container is configured to run as root (UID 0) |
has_health_check |
boolean |
True when a HEALTHCHECK instruction or liveness/readiness probe is present |
has_resource_limits |
boolean |
True when Kubernetes resource limits are defined for the container |
image_role |
string |
SBOM 1.7.0. "base" for a FROM/image: reference, "app" for the image a Dockerfile builds (one per Dockerfile, final stage) |
os_name / os_version / os_family |
string |
SBOM 1.7.0 operating system of the image, e.g. debian / 12 / debian. Inferred from the base image reference, or read from syft when --scan-images is on |
os_evidence |
string |
How the OS was determined: "tag" (the tag names it), "image_default" (the image's documented default distro; version may be unknown) or "syft" |
stage_alias |
string |
Final build stage alias (AS name) |
entrypoint / cmd / workdir |
string |
Final-stage ENTRYPOINT, CMD and WORKDIR as written, truncated; key=value secrets are redacted |
image_packages |
ImagePackage[] |
Packages installed in the image: parsed from RUN apt/apk/yum/pip/npm (names and pinned versions only), or the full list from syft. Capped by max_image_packages |
dependency_manifests |
string[] |
Dependency manifests COPY'd into the image, e.g. requirements.txt |
has_dockerignore |
boolean |
True when a .dockerignore sits beside the Dockerfile |
exposed_ports |
PortDetail[] |
Ports declared with EXPOSE |
IAM fields
| Field |
Type |
Description |
iam_type |
string |
IAM entity kind: "role", "policy", "service_account", "managed_identity", "role_binding" |
principal |
string |
ARN, email, or object ID of the IAM principal |
permissions |
string[] |
Actions or scopes granted by this IAM entity, up to 20 entries |
iam_scope |
string |
Scope of the IAM binding: "project", "subscription", "cluster", "namespace", "resource" |
trust_principals |
string[] |
Principals trusted to assume this role |
Populated by the supply-chain second pass for AI coding-agent and editor configs committed to the repository.
| Field |
Type |
Description |
tool_config_type |
string |
Config format: "claude-settings", "claude-instructions", "mcp-config", "cursor-config", "vscode-config", "gemini-config", "codex-config", "smithery-config" |
permissions_granted |
string[] |
Explicit allow-list entries from the config, e.g. ["Bash(*:*)", "Read", "Write"] |
permissions_denied |
string[] |
Explicit deny-list entries from the config, e.g. ["Bash(rm:*)"] |
auto_execute |
boolean |
True when the config enables auto-run or auto-approve mode |
permission_scope |
string |
Scope of the config file: "repo", "user", or "global" |
file_size_bytes |
integer |
Raw file size in bytes of this config file (for NGA-SC-017 large-file detection) |
content_entropy |
float |
Shannon entropy (bits/byte) of the file content at extraction time (for NGA-SC-018 high-entropy blob detection). Typical text is ~4–5; encrypted/base64 content is >6.5 |
LIFECYCLE_SCRIPT fields
| Field |
Type |
Description |
script_phase |
string |
Script lifecycle hook: "preinstall", "install", "postinstall", "prepare", "prepack", "postpack", "build-backend" |
script_body |
string |
First 500 characters of the script body |
invokes_network |
boolean |
True when the script body references curl, wget, node-fetch, axios, or similar network-fetch primitives |
invokes_shell |
boolean |
True when the script pipes output to a shell (| bash, | sh, | node) |
downloads_binary |
boolean |
True when the script downloads and executes a binary (e.g. npx bun, install.sh) |
references_credentials |
boolean |
True when the script references credential paths such as .npmrc, AWS_SECRET_ACCESS_KEY, GITHUB_TOKEN, or /proc/*/environ |
GITHUB_WORKFLOW fields
| Field |
Type |
Description |
workflow_triggers |
string[] |
Trigger event keys from the on: block, e.g. ["push", "pull_request_target"] |
workflow_permissions |
object |
Top-level or job-level permissions: block, e.g. {"id-token": "write", "contents": "read"} |
publishes_to |
string[] |
Publish targets detected in workflow steps: "pypi", "npm", "smithery" |
uses_oidc |
boolean |
True when any job has permissions.id-token: write |
action_refs |
string[] |
All uses: owner/action@ref strings in the workflow, used to detect unpinned mutable refs |
workflow_has_unpinned_global_install |
boolean |
True when any step runs an unpinned global npm install or npx |
workflow_has_cred_access |
boolean |
True when any step accesses credential paths or env vars |
MCP_SERVER fields
| Field |
Type |
Description |
mcp_server_url |
string |
URL of the MCP server (for HTTP/SSE transports) |
mcp_server_trusted |
boolean |
False by default; true when the server is listed in redteam.mcp_trusted_servers in nuguard.yaml |
mcp_transport |
string |
Transport protocol: "stdio", "http", or "sse" |
SBOM 1.5.0 Detail Objects
RateLimitDetail
| Field |
Type |
Description |
requests_per_minute |
integer |
Maximum requests allowed per minute |
requests_per_hour |
integer |
Maximum requests allowed per hour |
requests_per_day |
integer |
Maximum requests allowed per day |
burst_size |
integer |
Burst/concurrency limit above the steady-state rate |
window_seconds |
integer |
Duration of the rate-limit window in seconds |
enforcement_type |
string |
How the rate limit is enforced, e.g. "decorator", "middleware", "api_gateway" |
| Field |
Type |
Description |
csp |
boolean |
True when a Content-Security-Policy header is set |
x_frame_options |
boolean |
True when an X-Frame-Options header is set |
hsts |
boolean |
True when a Strict-Transport-Security header is set |
missing |
string[] |
Security headers confirmed absent, e.g. ["csp", "x_frame_options", "hsts"] |
CorsPolicyDetail
| Field |
Type |
Description |
origin |
string |
Configured allowed origin(s), e.g. "*" or "https://example.com" |
allow_credentials |
boolean |
True when the CORS policy allows credentialed cross-origin requests |
wildcard_with_credentials |
boolean |
True when origin is wildcarded AND credentials are allowed — the dangerous combination |
AuthDetail
| Field |
Type |
Description |
protocols |
string[] |
Auth protocols in use, e.g. ["oauth2", "bearer", "api_key"] |
token_expiry_seconds |
integer |
Token TTL in seconds when detectable |
mfa_required |
boolean |
True when MFA is required for access |
credential_rotation_policy |
string |
Rotation policy description, e.g. "90-day" or "on-demand" |
enforcement_strict |
boolean |
True when auth is enforced on every request with no opt-out |
auth_roles |
string[] |
Roles or scopes required for access, e.g. ["admin", "read:users"] |
jwt_algorithm_restricted |
boolean | null |
True when a JWT verification call site pins an explicit expected algorithm (e.g. algorithms: ["HS256"]); false when a verify call was found with no such restriction, which admits alg-confusion attacks (a forged token can switch the algorithm, e.g. to none, and be accepted); null when no verification call site was found |
AsmSummary
Booleans and counts only. The full probed surface (URLs, headers, status codes) is a runtime artifact of nuguard redteam and is never written to the SBOM.
| Field |
Type |
Description |
sibling_endpoint_count |
integer | null |
Number of endpoints discovered beyond the primary chat route |
unauthenticated_inventory_exposed |
boolean | null |
True when a tool/agent inventory endpoint (e.g. /api/tools) is reachable without auth |
observation_channel_unauthenticated |
boolean | null |
True when a WebSocket/SSE observation channel accepted a connection without auth |
cors_wildcard_with_credentials_live |
boolean | null |
True when a live OPTIONS probe reflected an attacker Origin with credentials allowed |
direct_tool_endpoint_path |
string | null |
Path of a confirmed directly-invocable tool endpoint, when one was found |
ObjectIdSemantics
Static and best-effort. Whether adjacent IDs actually exist is a runtime fact and is never recorded.
| Field |
Type |
Description |
param_name |
string |
Path/query/body parameter that carries the object ID |
id_format |
string | null |
"int", "uuid", "ulid" when the name or declared type shows it; otherwise null (never guessed) |
sequential |
boolean | null |
True for integer IDs, false for UUID/ULID, null when unknown |
enumerability |
string |
"high" (sequential), "low" (random), or "unknown" |
sibling_read_paths |
string[] |
Other read endpoints of the same object family |
MutationSemantics
unknown is the default and never blocks a scan; it only limits destructive-test eligibility.
| Field |
Type |
Description |
mutation_kind |
string |
"none", "create", "update", "delete", "payment", "auth_state", or "unknown". A state-changing GET (e.g. GET /transfer) is "unknown", never "none" |
idempotency |
string |
"idempotent" (HTTP semantics or an idempotency-key parameter), "non_idempotent", or "unknown" |
confirmation_required |
boolean | null |
True when a confirm token/field or a sibling …/confirm route exists; false for a payment/delete whose inputs were fully resolved and show none (the absence is the signal); null otherwise |
reversible |
boolean | null |
True when a compensating route exists in the endpoint set |
compensating_action |
CompensatingAction | null |
Rollback recipe: {method, path} of the opposite-verb route (freeze↔unfreeze) or the DELETE of a created resource family. Payments never get one |
audit_logged |
boolean | null |
True when the handler writes an audit-log record; null when the handler body was not analyzed |
evidence |
string[] |
Signals used, e.g. ["http_method:POST", "path_verb:transfer"] |
IngressDetail
| Field |
Type |
Description |
role |
string |
"gateway", "direct", or "static_frontend" |
url |
string | null |
Public host when statically declared (e.g. an nginx server_name); never a secret |
evidence |
string |
What proved it: "nginx proxy_pass", "ACA ingress", "k8s Ingress", "k8s Service LoadBalancer", "SWA config", "API Management", … |
WorkloadDetail
SBOM 1.7.0. One deployed service. Only names are recorded for environment variables and secrets, never values.
| Field |
Type |
Description |
service_name |
string |
Service or resource name |
workload_kind |
string |
"compose_service", "k8s_deployment" (also k8s_statefulset, k8s_daemonset, k8s_job, k8s_cronjob), "helm_chart", "container_app", "app_service", "aks_cluster", "container_instance", "ecs_service", "ecs_task_definition", "lambda", "cloud_run", "k8s_cluster" |
cloud_service |
string |
Managed service, e.g. "azure_container_apps", "aws_ecs", "aws_lambda", "gcp_cloud_run" |
namespace |
string |
Kubernetes namespace |
image_refs |
string[] |
Image references the workload runs. Placeholder images (for example the azd hello-world image) are left out |
build_context / dockerfile |
string |
Compose build context and Dockerfile path, repo-relative |
source_dir |
string |
Directory holding the code the workload runs. Resolved from the build context, an azure.yaml project, or (heuristically) a matching Dockerfile directory |
ports |
PortDetail[] |
Container/service ports and how far each is exposed |
scaling |
ScalingDetail |
Replica count and autoscaling bounds |
resources |
ResourceDetail |
CPU and memory requests/limits as written |
identity_ref |
string |
Service account or managed identity ("system-assigned" or a name) |
depends_on |
string[] |
Names of workloads this one depends on (compose depends_on, service names referenced from env values) |
env_var_names |
string[] |
Environment variable names only |
secret_refs |
string[] |
Secret / Key Vault reference names only |
probes |
string[] |
Health probes, e.g. "liveness:/healthz" |
internal_only |
boolean |
True when no public ingress or published port reaches the workload |
source_format |
string |
"compose", "k8s", "helm_values", "bicep", "terraform", "cloudformation", "cloud-run-yaml", "ecs-task-definition" |
PortDetail
| Field |
Type |
Description |
container_port |
integer |
Port the process listens on |
service_port |
integer |
Port a Service or load balancer exposes, when different |
host_port |
integer |
Published host port (compose, ECS) |
protocol |
string |
"tcp" or "udp" |
exposure |
string |
"public", "internal", "cluster" or "unknown" |
source |
string |
What declared it: "EXPOSE", "compose ports", "k8s Service", "aca ingress", "ecs portMappings", ... |
ScalingDetail
| Field |
Type |
Description |
replicas |
integer |
Static or desired replica count |
min_replicas / max_replicas |
integer |
Autoscaler bounds (HPA, KEDA, ACA scale rules, ECS autoscaling, Cloud Run) |
autoscaler |
string |
"hpa", "keda", "aca_rule", "ecs_autoscaling", "cloud_run" or "none" |
metric / target |
string |
Scaling metric and target, e.g. "cpu" / "70%" |
ResourceDetail
| Field |
Type |
Description |
cpu_request / cpu_limit |
string |
As written, e.g. "500m", "0.5" |
memory_request / memory_limit |
string |
As written, e.g. "512Mi", "1Gi" |
ImagePackage
| Field |
Type |
Description |
name |
string |
Package name |
version |
string | null |
Pinned version when known |
manager |
string |
"apt", "apk", "yum", "pip", "npm" or "syft:<type>" |
source |
string |
"dockerfile_run" or "syft" |
SessionCookieSemantics
| Field |
Type |
Description |
set_cookie_expected |
boolean |
True when handler code sets a cookie or uses a server-side session anywhere in the analyzed app. False together with identity carried in the request body means server-side session binding is impossible |
EncryptionDetail
| Field |
Type |
Description |
in_transit |
boolean |
True when data is encrypted in transit |
at_rest |
boolean |
True when data is encrypted at rest |
algorithm |
string |
Encryption algorithm, e.g. "AES256", "aws:kms", "RSA-4096" |
tls_min_version |
string |
Minimum TLS version enforced, e.g. "TLS1.2", "TLS1.3" |
redacted_fields |
string[] |
Field names whose values are redacted before logging or storage |
log_redaction_enabled |
boolean |
True when sensitive fields are masked/redacted in logs |
key_management |
string |
Key management service, e.g. "aws_kms", "gcp_cmek", "azure_key_vault" |
DataHandlingDetail
| Field |
Type |
Description |
retention_days |
integer |
Data retention period in days |
purge_schedule |
string |
Schedule or trigger for data purge, e.g. "weekly" or "on-account-deletion" |
backup_frequency |
string |
Backup frequency, e.g. "daily", "hourly", "7-day-retention" |
backup_encrypted |
boolean |
True when backups are encrypted |
anonymization_method |
string |
Anonymization or pseudonymization technique |
consent_required |
boolean |
True when user consent is required before processing data |
cross_border_transfer |
boolean |
True when data is transferred across jurisdictional borders |
InstrumentationDetail
| Field |
Type |
Description |
tools |
string[] |
Observability tools detected, e.g. ["opentelemetry", "datadog", "prometheus", "sentry"] |
log_level |
string |
Configured log level, e.g. "DEBUG", "INFO" |
tracing_enabled |
boolean |
True when distributed tracing is configured |
metrics_enabled |
boolean |
True when metrics collection is configured |
sampling_rate |
float |
Trace or log sampling rate in [0.0, 1.0] when detectable |
TestingDetail
| Field |
Type |
Description |
has_unit_tests |
boolean |
True when unit test files are detected |
has_integration_tests |
boolean |
True when integration test files or suites are detected |
test_frameworks |
string[] |
Test frameworks detected, e.g. ["pytest", "jest", "vitest"] |
ci_cd_pipeline |
string |
CI/CD platform detected, e.g. "github_actions", "gitlab_ci", "jenkins" |
quality_gates |
string[] |
Quality gate tools detected, e.g. ["codecov", "sonarqube", "snyk"] |
test_coverage_tool |
string |
Coverage measurement tool detected, e.g. "coverage.py", "istanbul" |
Schema for a single parameter accepted by a TOOL node. Captured from function signatures and docstrings; used by the red-team test generator for TOOL_ABUSE scenarios.
| Field |
Type |
Required |
Description |
name |
string |
yes |
Parameter name as it appears in the function signature |
type |
string | null |
- |
Python/TypeScript type annotation, e.g. "str", "int", "dict" |
description |
string | null |
- |
Parameter description from the function docstring |
required |
boolean |
- |
True when the parameter has no default value. Default: true |
{
"name": "query",
"type": "str",
"description": "The search query to send to the web search API",
"required": true
}
Evidence
A single piece of detection evidence supporting a Node.
| Field |
Type |
Required |
Description |
kind |
string |
yes |
Detection method. See EvidenceKind values below. |
confidence |
float [0, 1] |
yes |
Evidence-level confidence |
detail |
string |
yes |
For PROMPT nodes: "<adapter>: <evidence_kind>" with full content in metadata.content (also mirrored to metadata.extras.content). For all other nodes: "<adapter>: <snippet>" up to 500 chars. |
location |
SourceLocation |
yes |
File and line pointer |
EvidenceKind values
| Value |
Meaning |
ast |
Generic AST evidence |
ast_instantiation |
Class or object instantiation evidence |
ast_import |
Import statement evidence |
ast_call |
Function call evidence |
ast_method_call |
Method call evidence |
ast_decorator |
Decorator evidence |
ast_constant |
Constant or literal assignment evidence |
ast_string_literal |
String literal evidence |
regex |
Regex match evidence |
config |
Configuration file evidence |
iac |
Infrastructure-as-code evidence |
yaml |
YAML evidence |
dockerfile |
Dockerfile evidence |
nginx |
NGINX configuration evidence |
prompt_file |
Prompt file evidence |
inferred |
Inferred evidence derived from other detections |
llm_discovery |
LLM-assisted discovery evidence |
SourceLocation
| Field |
Type |
Required |
Description |
path |
string |
yes |
Relative path to the source file |
line |
integer | null |
- |
1-based line number, if known |
Edge
A directed relationship between two nodes.
| Field |
Type |
Required |
Description |
source |
UUID string |
yes |
ID of the source Node |
target |
UUID string |
yes |
ID of the target Node |
relationship_type |
RelationshipType |
yes |
One of the values listed below |
access_type |
AccessType | null |
- |
Access direction for ACCESSES edges |
derivation |
"hint" | "fallback_heuristic" |
- |
hint: backed by an adapter-emitted evidence hint. fallback_heuristic: synthesized by structural fallback rules with no direct evidence. Default: "hint" |
confidence |
float [0, 1] | null |
- |
Set only for fallback_heuristic edges — a rough strength score for the guess. null for hint edges. |
RelationshipType values
| Value |
Meaning |
CALLS |
Agent calls a tool or sub-agent |
ACCESSES |
Agent or tool reads from or writes to a datastore |
USES |
Component depends on a framework, model, auth provider, or other component |
PROTECTS |
A GUARDRAIL protects an AGENT or its prompt, or an AUTH provider protects an API_ENDPOINT |
DEPLOYS |
A deployment resource hosts a container or service |
DELEGATES_TO |
An agent hands off a conversation or task to another agent |
CONTAINS |
A parent component contains a child component; used for DEVELOPER_TOOL_CONFIG → MCP_SERVER and DEVELOPER_TOOL_CONFIG → LIFECYCLE_SCRIPT relationships |
RUNS |
SBOM 1.7.0. A workload runs a container image (DEPLOYMENT → CONTAINER_IMAGE): from its image:/containers[].image, or from its build context to the Dockerfile's app image |
BUILT_FROM |
SBOM 1.7.0. A Dockerfile's app image is built from a base image (CONTAINER_IMAGE → CONTAINER_IMAGE) |
HOSTS |
SBOM 1.7.0. A workload hosts a component found in its source directory (DEPLOYMENT → AGENT / API_ENDPOINT / MCP_SERVER / TOOL). Declared by a compose build context or azure.yaml project (derivation: "hint"); otherwise a name/path guess (fallback_heuristic) |
EXPOSES |
SBOM 1.7.0. A workload with a public port exposes a hosted API_ENDPOINT or MCP_SERVER |
ROUTES_TO |
SBOM 1.7.0. A gateway (K8s Ingress, nginx proxy_pass) routes to a backend workload |
DEPENDS_ON |
SBOM 1.7.0. A workload depends on another workload (compose depends_on, service names referenced from environment values) |
AGENT --ACCESSES--> DATASTORE is inferred when an agent calls a tool that accesses the datastore, when a single agent and datastore are detected in the same source file, or when a single agent's Python file imports and uses a detected datastore client. These inferred edges carry derivation: "fallback_heuristic" and a confidence score.
AccessType values
| Value |
Meaning |
read |
Read-only access |
write |
Write-only access |
readwrite |
Both read and write access |
PackageDep
A single declared package dependency from a manifest file. The scanner reads declarations without executing package managers or build tools and does not resolve the full transitive dependency graph.
| Field |
Type |
Required |
Description |
name |
string |
yes |
Ecosystem package name. Python names are PEP 503-normalized; Java uses groupId:artifactId; other ecosystems retain their native package spelling. |
version_spec |
string |
yes |
Version specifier as declared, e.g. ">=1.70,<2.0", "^18.0.0", or "" |
purl |
string |
yes |
Package URL using the ecosystem type, such as pkg:pypi, pkg:npm, pkg:nuget, pkg:maven, or pkg:golang |
group |
string |
yes |
Normalized dependency group: "runtime", "dev", or an ecosystem-specific "optional:<name>" value such as optional:peer, optional:maven, optional:gradle, or optional:indirect |
source_file |
string |
yes |
Repository-relative manifest file from which the dependency was extracted |
Supported dependency manifests
| Ecosystem |
Manifests |
Notes |
| Python |
pyproject.toml, requirements*.txt, setup.cfg |
Supports PEP 621, Poetry, Hatch, uv, and legacy install_requires declarations |
| JavaScript/TypeScript |
package.json |
Reads runtime, development, optional, and peer dependency sections |
| C#/.NET |
*.csproj, packages.config, Directory.Packages.props |
Emits NuGet PURLs and honors centrally managed package versions |
| Java |
pom.xml, build.gradle, build.gradle.kts, gradle/libs.versions.toml |
Resolves common Maven properties, dependency management, Gradle variables, and version-catalog references without invoking Maven or Gradle |
| Go |
go.mod, go.sum |
Emits Go PURLs; indirect modules use the optional:indirect group |
For Java dependencies, a resolved declaration such as org.springframework.ai:spring-ai-openai-spring-boot-starter:1.0.1 is represented as:
{
"name": "org.springframework.ai:spring-ai-openai-spring-boot-starter",
"version_spec": "==1.0.1",
"purl": "pkg:maven/org.springframework.ai/spring-ai-openai-spring-boot-starter@1.0.1",
"group": "runtime",
"source_file": "pom.xml"
}
ScanSummary
Scan-level metadata derived during extraction. Populated when nuguard sbom generate runs.
| Field |
Type |
Description |
use_case |
string |
Human-readable description of the application's AI use cases |
frameworks |
string[] |
Agentic framework names detected, e.g. ["langgraph", "crewai"] |
modalities |
string[] |
Supported I/O modalities in upper-case, e.g. ["TEXT", "VOICE"] |
modality_support |
object |
Detailed modality flags: {"text": true, "voice": false} |
node_counts |
object |
Count of nodes per ComponentType, e.g. {"AGENT": 3, "MODEL": 2} |
node_counts_soft_rejected |
object |
Per-component counts for deterministic nodes retained for audit after LLM verification rejected them. These nodes are excluded from node_counts and red-team scenario generation. |
total_loc |
integer |
SBOM 1.5.0 total lines of source code scanned across all files in the repository |
uses_streaming |
boolean |
True when the app exposes streaming output endpoints. The behavior engine reads this to use streaming-aware turn execution. |
streaming_endpoints |
string[] |
Endpoint paths confirmed to serve streaming output, e.g. ["/run_sse", "/chat/stream"] |
API and network
| Field |
Type |
Description |
api_endpoints |
string[] |
API route paths extracted from source, e.g. ["/chat", "/health"] |
local_url |
string | null |
Inferred local dev URL, e.g. "http://localhost:8000" |
staging_urls |
string[] |
Staging/QA deployment URLs |
production_urls |
string[] |
Production deployment URLs |
deployment_urls |
string[] |
Canonical deployment URLs found in IaC/workflow files |
Deployment and infrastructure
| Field |
Type |
Description |
deployment_platforms |
string[] |
Cloud/CI platforms inferred from IaC files, e.g. ["AWS", "GCP"] |
regions |
string[] |
Cloud regions referenced in IaC/config, e.g. ["us-east-1"] |
environments |
string[] |
Deployment environments inferred from config, e.g. ["prod", "staging"] |
iac_accounts |
string[] |
Cloud account IDs, subscription IDs, or project IDs found in IaC |
availability_zones |
string[] |
All cloud availability zones referenced in IaC files |
secret_stores |
string[] |
Deduped secret management services referenced across IaC files |
encryption_at_rest_coverage |
boolean |
True when at least one IaC resource has encryption-at-rest configured |
k8s_network_policy_namespaces |
string[] |
SBOM 1.5.0 Kubernetes namespaces with at least one NetworkPolicy resource detected. Used by NGA-013 to assert cross-file coverage. |
Security posture and static analysis evidence
| Field |
Type |
Description |
security_findings |
string[] |
Notable security/resilience findings across IaC and container config, e.g. ["container_runs_as_root", "missing_health_check", "secrets_in_env_vars"] |
iam_principals |
string[] |
IAM role ARNs, GCP service account emails, and Azure managed identity names |
service_accounts |
string[] |
K8s ServiceAccount names and GCP/Azure service account identifiers |
iac_security_summary |
string | null |
LLM-generated security briefing covering deployment posture, IAM configuration, secret management, encryption, HA, and CI/CD risks. Only populated when LLM enrichment is enabled. |
github_actions_content |
string |
SBOM 1.5.0 raw concatenation of detected GitHub Actions workflow YAML files. Used by NGA-010, NGA-011, and NGA-014 regex rules as a fallback when structured workflow findings are not available. |
workflow_security_findings |
object[] |
SBOM 1.5.0 structured findings emitted by the GitHub Actions adapter. Each object uses {rule_signal, path, line, snippet, confidence}. |
Data classification
| Field |
Type |
Description |
data_classification |
string[] |
Union of all classification labels detected across the repo, e.g. ["PHI", "PII", "PFI"] |
classified_tables |
string[] |
Names of SQL tables or Python models that contain classified data fields |
Supply-chain repository signals
| Field |
Type |
Description |
has_package_json |
boolean | null |
True when a package.json file was found at the repo root. Used by NGA-SC-024 lockfile-coverage checks without requiring a live filesystem. |
has_lockfile |
boolean | null |
True when an npm lockfile (package-lock.json, pnpm-lock.yaml, or yarn.lock) was found at the repo root. Used by NGA-SC-024. |
minified_js_files |
string[] |
Relative paths to JavaScript files containing a single line exceeding 5000 characters — a reliable indicator of minified/bundled code. Used by NGA-SC-019. |
Runtime environment
| Field |
Type |
Description |
startup_commands |
object[] |
Startup commands from package.json, Makefile, Procfile, pyproject.toml, or inferred entry points. Each entry is {command, source, label} where label is "dev" or "start". |
env_files |
string[] |
Relative paths to .env/dotenv files found in the repo |
env_var_keys |
string[] |
Sorted list of environment variable keys across dotenv files. Values are intentionally omitted from the SBOM. |
log_paths |
string[] |
Log file paths discovered during scanning, relative to app root |
LLM enrichment usage
| Field |
Type |
Description |
tokens_used_for_enrichment |
integer |
SBOM 1.5.0 total LLM tokens consumed during SBOM enrichment |
input_tokens_used |
integer |
SBOM 1.5.0 prompt/input tokens consumed during SBOM enrichment |
output_tokens_used |
integer |
SBOM 1.5.0 completion/output tokens consumed during SBOM enrichment |
llm_model_used |
string |
SBOM 1.5.0 LLM model string used for SBOM enrichment, e.g. "gemini/gemini-2.0-flash" |
App-wide posture summaries
| Field |
Type |
Description |
instrumentation |
InstrumentationDetail |
SBOM 1.5.0 app-wide observability and monitoring tooling summary |
testing |
TestingDetail |
SBOM 1.5.0 app-wide testing and CI/CD posture summary |
The SBOM does not store nuguard analyze findings directly. nuguard analyze consumes the SBOM and emits NGA, supply-chain, and ATLAS findings. SBOM 1.5.0 adds structured evidence fields so most rules reason over the generated SBOM without re-scanning source.
NGA-001–NGA-018 evidence fields
| Rule area |
SBOM evidence fields used |
| Sensitive data to external LLMs |
MODEL nodes (model_name, source_url, extras), DATASTORE nodes (data_classification, pii_fields, phi_fields, pfi_fields), and USES/ACCESSES edges |
| Insufficient guardrails and missing HITL |
GUARDRAIL nodes, PROTECTS edges, AGENT nodes, TOOL risk fields, and injection_risk_score |
| Secrets and workflow injection |
summary.env_var_keys, summary.security_findings, summary.github_actions_content, and summary.workflow_security_findings |
| Container hardening |
CONTAINER_IMAGE fields: runs_as_root, has_health_check, has_resource_limits, image_tag, base_image, registry |
| Datastore encryption and isolation |
DATASTORE fields, encryption_detail, encryption_at_rest, data_handling, IAM nodes, and ACCESSES edges |
| Missing endpoint auth and IDOR |
API_ENDPOINT fields: auth_required, no_auth_required, auth_scope, idor_surface, path_params, context_payload_fields, request_schema, and response_schema |
| Overly permissive IAM |
IAM fields: iam_type, principal, permissions, iam_scope, trust_principals, plus summary.iam_principals and summary.service_accounts |
| Untrusted model registry and model integrity |
MODEL fields: source_url, integrity_hash, checksum, dependency_names, and extras |
| Audit logging and observability |
Node and summary instrumentation, summary.log_paths, and summary.security_findings |
| Kubernetes network policy |
DEPLOYMENT.has_network_policy and summary.k8s_network_policy_namespaces |
Supply Chain Threat Pack evidence fields
When the SBOM includes supply-chain node types (populated by the second pass during nuguard sbom generate), the supply-chain scanner uses them directly. When SBOM nodes are absent, the scanner falls back to scanning source files at --source.
| Rule family |
SBOM node types used |
| GitHub Actions risks (NGA-SC-001–006) |
GITHUB_WORKFLOW nodes: workflow_triggers, uses_oidc, publishes_to, action_refs, workflow_permissions |
| AI-agent config poisoning (NGA-SC-007–010) |
DEVELOPER_TOOL_CONFIG nodes: permissions_granted, auto_execute, permission_scope; MCP_SERVER nodes: mcp_server_trusted, mcp_server_url |
| Lifecycle scripts (NGA-SC-011–016) |
LIFECYCLE_SCRIPT nodes: script_phase, script_body, invokes_network, invokes_shell, downloads_binary, references_credentials |
| Oversized/high-entropy/minified payloads (NGA-SC-017–019) |
DEVELOPER_TOOL_CONFIG nodes: file_size_bytes, content_entropy; summary.minified_js_files |
| Dependency integrity (NGA-SC-023–025) |
deps array: name, version_spec, purl; summary.has_package_json, summary.has_lockfile; threat-intel feeds matched against name |
| Workflow governance (NGA-SC-026–027) |
Read directly from .github/workflows/*.yml at --source — no SBOM node fields yet; requires a local source_path |
MITRE ATLAS annotations and supply-chain findings are produced by nuguard analyze. They appear on analysis findings, not on the SBOM document itself. Every NGA-SC-* finding also carries an owasp_cicd_ref (OWASP Top 10 CI/CD Security Risks category, e.g. CICD-SEC-4) via nuguard.common.control_mappings.cicd. See docs/static-analysis-guide.md for the full rule reference.
Validation
# Validate an SBOM file against the bundled schema
nuguard sbom validate --file ./app.sbom.json
# Print the bundled JSON Schema to stdout
nuguard sbom schema
The test_committed_schema_matches_models test enforces that the committed aibom.schema.json always matches AiSbomDocument.model_json_schema().
Example
Generated SBOM examples are available under tests/apps/*/*.sbom.json. The committed docs/sample-sbom.json may lag behind the current schema until regenerated, so prefer nuguard sbom schema or nuguard/sbom/schemas/aibom.schema.json as the source of truth for validation.