BLA
BLA는 오픈소스 Blue Defense MCP와 CLI로, 소프트웨어 자산을 자동 AI 리버스 엔지니어링으로부터 보호합니다
SBOM과 컴플라이언스 문서를 생성·관리·공유하고 GitHub·GitLab 등과 연동한다
From generation to distribution. Generate, manage, and share SBOMs and compliance documents. Integrate with GitHub, GitLab, and more. CRA & NTIA compliant.
보안Python · JinjaGitHub @sbomify온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
sbomify is a product security artifact hub and a trust center.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
sbomify is a Software Bill of Materials (SBOM) and document management platform that can be self-hosted or accessed through app.sbomify.com. The platform provides a centralized location to upload and manage your SBOMs and related documentation, allowing you to share them with stakeholders or make them publicly accessible.
The sbomify backend integrates with our github actions module to automatically generate SBOMs from lock files and docker files.
For more information, see sbomify.com.README 전문 보기 ↗sbomify is a Software Bill of Materials (SBOM) and document management platform that can be self-hosted or accessed through app.sbomify.com. The platform provides a centralized location to upload and manage your SBOMs and related documentation, allowing you to share them with stakeholders or make them publicly accessible.
The sbomify backend integrates with our github actions module to automatically generate SBOMs from lock files and docker files.
For more information, see sbomify.com.
| Plugin | Type | Standard |
|---|---|---|
| NTIA Minimum Elements (2021) | Compliance | NTIA Minimum Elements for SBOM |
| CISA Minimum Elements (2026) | Compliance | 2026 Minimum Elements for an SBOM |
| CISA Minimum Elements (2025 Draft) | Compliance | CISA 2025 SBOM Minimum Elements (Public Comment Draft) |
| BSI TR-03183-2 v2.1 (EU CRA) | Compliance | BSI TR-03183-2: Cyber Resilience Requirements |
| FDA Medical Device Cybersecurity (2025) | Compliance | FDA Cybersecurity in Medical Devices |
| GitHub Artifact Attestation | Attestation | GitHub Artifact Attestations |
.well-known/tea endpointsWe use Architecture Decision Records (ADRs) to document significant architectural decisions made in this project. ADRs provide context and rationale for decisions, helping current and future contributors understand why certain approaches were chosen.
For all ADRs, see the docs/ADR folder.
For detailed information about the deployment process, including:
See docs/deployment.md.
For full production deployment instructions, see the deployment guide.
A Helm chart lives in charts/sbomify. It deploys
the application only. You provide PostgreSQL, Redis, S3-compatible storage and
Keycloak.
To try the whole stack on a local kind cluster (which also provisions throwaway versions of those four):
./bin/kind-up.sh # create the cluster and deploy
./bin/kind-up.sh --down # tear it down
For local development, authentication is handled through Django's admin interface:
# Create a superuser for local development
docker compose \
-f docker-compose.yml \
-f docker-compose.dev.yml exec \
sbomify-backend \
uv run python manage.py createsuperuser
Then access the admin interface at http://localhost:8000/admin to log in.
Note: Production environments use different authentication methods. See docs/deployment.md for production authentication setup.
curl -LsSf https://astral.sh/uv/install.sh | sh
uv --version
# Install all dependencies including development dependencies
uv sync
# Run commands using uv
uv run python manage.py --help
bun install
The API documentation is available at:
http://localhost:8000/api/v2/docshttp://localhost:8000/api/v2/openapi.jsonv2 serves the v1 operations in the product's own words, apart from the
internal routes the app uses for itself, which stay on v1 only. If you call v1
from a script, SDK or CI job, nothing breaks: v1 stays byte for byte as it is,
and its docs are still at /api/v1/docs. The main changes when you move to v2
are below; the v2 OpenAPI document at /api/v2/openapi.json is the full list.
/sboms prefix becomes /artifacts, and the /sbom/ and
/artifact/ segments under it drop away. An artifact's releases move from
/sboms/{sbom_id}/releases to /artifacts/{artifact_id}/releases, and the
access request routes move from /teams/{team_key}/access-request to
/workspaces/{workspace_key}/access-request, with their /nda and
/sign-nda children.team_key becomes workspace_key and sbom_id becomes
artifact_id. A hand-written URL keeps the same shape; a generated client's
argument names change.team_id, team_key, team_name and
is_default_team become workspace_id, workspace_key, workspace_name and
is_default_workspace, in both directions. v1 already sends
is_default_workspace beside is_default_team.NO_CURRENT_TEAM, TEAM_NOT_FOUND and TEAM_MISMATCH
become NO_CURRENT_WORKSPACE, WORKSPACE_NOT_FOUND and WORKSPACE_MISMATCH.Team in its name says Workspace
instead, for example TeamSchema becomes WorkspaceSchema and
TeamPatchSchema becomes WorkspacePatchSchema.Every v1 response carries a Deprecation header and a Link to the v2 docs.
No date for retiring v1 has been set yet. When there is one, v1 responses will
carry a Sunset header with it.
The API provides endpoints for managing:
Download aggregated SBOMs for products and releases with format selection:
# Download release SBOM in CycloneDX 1.6 (default)
curl "https://app.sbomify.com/api/v1/releases/{release_id}/download"
# Download release SBOM in SPDX 2.3
curl "https://app.sbomify.com/api/v1/releases/{release_id}/download?format=spdx"
# Download release SBOM in SPDX 3.0
curl "https://app.sbomify.com/api/v1/releases/{release_id}/download?format=spdx&version=3.0"
# Download release SBOM in CycloneDX 1.7
curl "https://app.sbomify.com/api/v1/releases/{release_id}/download?format=cyclonedx&version=1.7"
# Download product SBOM in SPDX 2.3
curl "https://app.sbomify.com/api/v1/products/{product_id}/download?format=spdx&version=2.3"
Supported formats and versions:
| Format | Versions | Default |
|---|---|---|
| CycloneDX | 1.6, 1.7 | 1.6 |
| SPDX | 2.3, 3.0 | 2.3 |
These endpoints are available when running the development server.
Configure environment variables by setting them in your shell or using Docker Compose override files.
Important: Add to /etc/hosts
For the development environment to work properly with Keycloak authentication, you must add the following entry to your /etc/hosts file:
127.0.0.1 keycloak
Start the development environment (recommended method):
./bin/developer_mode.sh build
./bin/developer_mode.sh start
Create a local admin account:
docker compose \
-f docker-compose.yml \
-f docker-compose.dev.yml exec \
-e DJANGO_SUPERUSER_USERNAME=sbomifyadmin \
-e DJANGO_SUPERUSER_PASSWORD=sbomifyadmin \
-e [email protected] \
sbomify-backend \
uv run python manage.py createsuperuser --noinput
Access the application:
http://localhost:8000/adminhttp://localhost:8000Note: For production deployment information, see docs/deployment.md.
# Start both PostgreSQL and SeaweedFS
docker compose -f docker-compose.yml -f docker-compose.dev.yml up sbomify-db sbomify-s3 -d
uv sync
bun install # for JavaScript dependencies
uv run python manage.py migrate
# In one terminal, start Django
uv run python manage.py runserver
# In another terminal, start Vite
bun run dev
The application uses Vite for JavaScript development. The following environment variables control the development servers:
# Vite development settings
DJANGO_VITE_DEV_MODE=True
DJANGO_VITE_DEV_SERVER_PORT=5170
DJANGO_VITE_DEV_SERVER_HOST=http://localhost
# Static and development server settings
STATIC_URL=/static/
DEV_JS_SERVER=http://127.0.0.1:5170
WEBSITE_BASE_URL=http://127.0.0.1:8000
VITE_API_BASE_URL=http://127.0.0.1:8000
VITE_WEBSITE_BASE_URL=http://127.0.0.1:8000
These settings can be configured using environment variables.
Keycloak is now managed as part of the Docker Compose environment. You do not need to run Keycloak manually.
Persistent storage for Keycloak is managed by Docker using a named volume (keycloak_data).
Keycloak is automatically bootstrapped using the script at bin/keycloak-bootstrap.sh when you start the development environment with Docker Compose. This script uses environment variables (such as KEYCLOAK_REALM, KEYCLOAK_CLIENT_ID, KEYCLOAK_ADMIN_USERNAME, KEYCLOAK_ADMIN_PASSWORD, KEYCLOAK_CLIENT_SECRET, etc.) to configure the realm, client, and credentials. You do not need to edit the script itself. Just set the appropriate environment variables in your Docker Compose configuration to control the bootstrap process.
When running in development mode (using docker-compose.dev.yml), the bootstrap script automatically:
jdoe, Password: foobar123, Email: [email protected]ssmith, Password: foobar123, Email: [email protected]These development-specific configurations are controlled by the KEYCLOAK_DEV_MODE environment variable and are only applied when running the development Docker Compose stack.
To start Keycloak (and all other services) in development, simply run:
docker compose -f docker-compose.yml -f docker-compose.dev.yml up
Keycloak will be available at http://keycloak:8080/.
The application uses S3-compatible storage for storing files and assets. In development, we use SeaweedFS as a local S3 replacement.
docker compose -f docker-compose.yml -f docker-compose.dev.yml up sbomify-s3 -dAWS_ENDPOINT_URL_S3=http://localhost:9000 in your environment variablessbomify-media, sbomify-sboms, and
AWS_DOCUMENTS_STORAGE_BUCKET_NAME if you set oneThe application uses separate S3 buckets for different types of content:
You can access the SeaweedFS admin UI at:
http://localhost:23646The S3 credentials for development are minioadmin/minioadmin, set in
bin/seaweedfs-s3.json. If you change the bucket names, update the anonymous
read scope in that file to match.
For production deployments, you can configure separate S3 buckets for documents:
# Optional: Configure dedicated documents bucket (recommended for production)
export AWS_DOCUMENTS_ACCESS_KEY_ID="your-documents-access-key"
export AWS_DOCUMENTS_SECRET_ACCESS_KEY="your-documents-secret-key"
export AWS_DOCUMENTS_STORAGE_BUCKET_NAME="your-documents-bucket"
export AWS_DOCUMENTS_STORAGE_BUCKET_URL="https://your-documents-bucket.s3.region.amazonaws.com"
# If not configured, documents will automatically use the SBOMs bucket
export AWS_SBOMS_ACCESS_KEY_ID="your-sboms-access-key"
export AWS_SBOMS_SECRET_ACCESS_KEY="your-sboms-secret-key"
export AWS_SBOMS_STORAGE_BUCKET_NAME="your-sboms-bucket"
export AWS_SBOMS_STORAGE_BUCKET_URL="https://your-sboms-bucket.s3.region.amazonaws.com"
Benefits of separate buckets:
sbomify supports integration with Dependency Track for advanced vulnerability management and analysis. Dependency Track integration is available for Business and Enterprise plans.
Note: Dependency Track only supports CycloneDX format SBOMs. SPDX SBOMs will automatically use OSV scanning regardless of workspace configuration.
When using a shared Dependency Track instance across multiple environments (development, staging, production), sbomify automatically prefixes project names with the environment to help differentiate them:
Examples:
https://app.sbomify.com): prod-sbomify-{component-id}https://staging.sbomify.com): staging-sbomify-{component-id}https://dev.sbomify.com): dev-sbomify-{component-id}http://localhost:8000): local-sbomify-{component-id}Custom Environment Prefix:
You can override the automatic detection by setting the DT_ENVIRONMENT_PREFIX environment variable:
export DT_ENVIRONMENT_PREFIX="my-custom-env"
# Results in: my-custom-env-sbomify-{component-id}
This makes it easy to identify which environment a project belongs to when viewing your Dependency Track dashboard.
To integrate with Dependency Track, you need to create an API token with the following permissions:
BOM_UPLOADPROJECT_CREATION_UPLOADVIEW_PORTFOLIOVIEW_VULNERABILITYYou can create a token under Administration → Access Management in your Dependency Track instance (use the workspace management interface there).
Add Dependency Track Server via Django admin:
/admin/vulnerability_scanning/dependencytrackserver/Configure Workspace Settings:
Before running tests, you need to up docker-compose.tests.yml:
docker compose -f docker-compose.tests.yml up -d
Run the tests using Django's test profile:
# Run all tests with coverage
uv run coverage run -m pytest
# Run specific test groups
uv run coverage run -m pytest core/tests/
uv run coverage run -m pytest sboms/tests/
uv run coverage run -m pytest teams/tests/
# Run with debugger on failure
uv run coverage run -m pytest --pdb -x -s
# Generate coverage report
uv run coverage report
Test coverage must be at least 80% to pass CI checks.
The project includes end-to-end snapshot tests that capture screenshots of the UI and compare them against baseline images. This helps ensure visual consistency across different screen sizes and after code changes.
Before running e2e snapshot tests, you need to:
Build JavaScript assets:
bun run build
This ensures that all static assets (JavaScript, CSS) are up-to-date before taking screenshots.
Here's an abstract example of how to write a snapshot test:
@pytest.mark.django_db
@pytest.mark.parametrize("width", [1920, 992, 576, 375])
class TestYourPageSnapshot:
def test_your_page_snapshot(
self,
authenticated_page,
your_test_fixtures, # noqa: F811
snapshot,
width: int,
) -> None:
# Navigate to the page you want to test
authenticated_page.goto("/your-page")
authenticated_page.wait_for_load_state("networkidle")
# Get or create baseline screenshot (stored in __snapshots__)
baseline = snapshot.get_or_create_baseline_screenshot(authenticated_page, width=width)
# Take current screenshot
current = snapshot.take_screenshot(authenticated_page, width=width)
# Compare screenshots
snapshot.assert_screenshot(baseline.as_posix(), current.as_posix())
Key components:
@pytest.mark.django_db to enable database access@pytest.mark.parametrize("width", [...]) to test multiple screen sizesauthenticated_page fixture for browser automationsnapshot fixture for screenshot managementget_or_create_baseline_screenshot() to get the baseline (creates it if missing)take_screenshot() to capture the current stateassert_screenshot() to compare themAfter building assets, you can use the dedicated E2E docker-compose stack to run snapshot tests:
# Start the test stack (database, chromium, and tests container)
docker compose -f docker-compose.tests.yml up -d
# Run all E2E snapshot tests inside the tests container
docker compose -f docker-compose.tests.yml exec tests uv run pytest sbomify/apps/<APP>/tests/e2e/
# Run a single E2E snapshot test (example)
docker compose -f docker-compose.tests.yml exec tests uv run pytest \
sbomify/apps/<APP>/tests/e2e/test_your_page.py::TestYourPageSnapshot::test_your_page_snapshot[1920]
New Tests
When you write a new snapshot test, it will automatically create baseline screenshots in the __snapshots__ directory (located at sbomify/apps/<APP_NAME>/tests/e2e/__snapshots__/). Simply run the test and verify that the generated screenshots look correct.
Existing Tests - Passing If the test already exists and passes, everything is working as expected. No action needed.
Existing Tests - Failing
If a test fails, check the __diffs__ directory (located at sbomify/apps/<APP_NAME>/tests/e2e/__diffs__/) to see what changed. The diff images show the differences between the baseline and current screenshots.
Updating Outdated Snapshots
If the diff screenshot in __diffs__ shows that the new visual state is correct (i.e., the baseline snapshot is outdated), you need to update the baseline:
__snapshots__Example:
# Delete outdated snapshot
rm sbomify/apps/<APP_NAME>/tests/e2e/__snapshots__/test_your_page_snapshot[1920].jpg
# Re-run the test to create new baseline
uv run pytest sbomify/apps/<APP_NAME>/tests/e2e/test_your_page.py::TestYourPageSnapshot::test_your_page_snapshot
For a real-world example, see sbomify/apps/core/tests/e2e/test_dashboard.py.
The application includes management commands to help set up and manage test data in your development environment:
# Create a test environment with sample SBOM data
# If no workspace is specified, the first workspace in the database is used
# (the management command retains the legacy --team-id flag name for compatibility)
python manage.py create_test_sbom_environment
# Create test environment for a specific workspace (still uses the legacy --team-id flag)
python manage.py create_test_sbom_environment --team-id=your_team_id
# Clean up existing test data and create fresh environment
python manage.py create_test_sbom_environment --clean
# Clean up all test data across all workspaces
python manage.py cleanup_test_sbom_environment
# Clean up test data for a specific workspace (still uses the legacy --team-id flag)
python manage.py cleanup_test_sbom_environment --team-id=your_team_id
# Preview what would be deleted (dry run)
python manage.py cleanup_test_sbom_environment --dry-run
These commands will:
The test data is grouped by source (e.g., hello-world and sbomify) rather than by format, so each component will have both SPDX and CycloneDX SBOMs attached to it.
Note: You must have at least one workspace in the database to use these commands without specifying the legacy --team-id flag.
For frontend JS work, setting up JS tooling is required.
curl -fsSL https://bun.sh/install | bash
In the project folder at the same level as package.json:
bun install
For JavaScript/TypeScript linting:
# Check for linting issues (used in CI and can be run locally)
bun lint
# Fix linting issues automatically (local development only)
bun lint-fix
bun run dev
The project uses pre-commit hooks to ensure code quality and consistency. The hooks check for:
To set up pre-commit:
uv run pre-commit install
# Check all files
uv run pre-commit run --all-files
# Check staged files only
uv run pre-commit run
A docker-compose.prod.yml file is available for production-like setups. Note: This configuration is not fully tested and is not recommended for use in real production environments as-is. The provided settings are for demonstration and staging purposes only and will be updated and improved in the future.
For production deployments, generate a secure signing salt for signed URLs:
# Generate a secure signing salt for signed URLs
export SIGNED_URL_SALT="$(openssl rand -hex 32)"
The SIGNED_URL_SALT is used to sign download URLs for private components in product SBOMs.
To try a production-like stack:
docker compose -f docker-compose.yml -f docker-compose.prod.yml build
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
You will need to set appropriate environment variables and ensure your reverse proxy, storage, and database are configured securely.
Warning: Do not use the provided production compose setup as-is for real deployments. Review and harden all settings, secrets, and network exposure before using in production.