> Learn how to generate Software Bill of Materials for Dart and Flutter projects. Complete guide with pubspec.lock examples and CycloneDX output.

- **Updated:** 2026-08-31

## Source vs Build SBOMs

Dart's package manager (pub) provides excellent lockfile support through `pubspec.lock`. This makes source SBOM generation reliable for both Dart and Flutter projects.

- **Source SBOMs** are generated from `pubspec.lock`
- **Build SBOMs** can be generated from the `.dart_tool/package_config.json`

For most Dart/Flutter projects, generating from `pubspec.lock` is preferred because it contains exact resolved versions and content hashes.

## Lockfile Deep Dive

### pubspec.yaml (Manifest)

The `pubspec.yaml` file declares your dependencies:

```yaml
name: my_app
description: A sample Dart/Flutter application
version: 1.0.0

environment:
  sdk: '>=3.0.0 <4.0.0'
  flutter: '>=3.16.0'

dependencies:
  flutter:
    sdk: flutter
  http: ^1.2.0
  provider: ^6.1.0
  shared_preferences: ^2.2.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^3.0.0
  build_runner: ^2.4.0
```

### pubspec.lock

The `pubspec.lock` file contains resolved dependencies:

```yaml
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
  http:
    dependency: "direct main"
    description:
      name: http
      sha256: "761a297c042deedc1ffbb156d6e2f13c3eb84c6cf7cb8dc2d5f2d5b0b8cb9c7b"
      url: "https://pub.dev"
    source: hosted
    version: "1.2.0"
  http_parser:
    dependency: transitive
    description:
      name: http_parser
      sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
      url: "https://pub.dev"
    source: hosted
    version: "4.0.2"
  provider:
    dependency: "direct main"
    description:
      name: provider
      sha256: "7e4a68b2a6e459ff1a3ce8a35c79cd2ad9b96742e5a81c8a83e1d7e3e9c27f22"
      url: "https://pub.dev"
    source: hosted
    version: "6.1.1"
sdks:
  dart: ">=3.0.0 <4.0.0"
  flutter: ">=3.16.0"
```

Key information:

- **dependency**: "direct main", "direct dev", or "transitive"
- **sha256**: Content hash for integrity verification
- **source**: "hosted" (pub.dev), "git", or "path"
- **version**: Exact resolved version

## Flutter-Specific Dependencies

Flutter projects have additional dependency types:

### Flutter SDK Dependencies

```yaml
dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
```

These are part of the Flutter SDK and typically not included in SBOMs as they're versioned with Flutter itself.

### Platform-Specific Dependencies

Flutter plugins may have native dependencies:

```yaml
dependencies:
  url_launcher: ^6.2.0  # Has iOS/Android native code
  sqflite: ^2.3.0       # SQLite bindings
```

The native code dependencies aren't captured in `pubspec.lock`. Consider documenting them separately.

## Generating an SBOM

SBOM generation is the first step in the [SBOM lifecycle](https://sbomify.com/features/generate-collaborate-analyze/). After generation, you typically need to enrich your SBOM with package metadata and augment it with your organization's details.

### Using sbomify GitHub Action (Recommended)

The [sbomify action](https://sbomify.com/sbomify-action/) is a swiss army knife for SBOMs that automatically selects the best generation tool for your ecosystem, enriches the output with package metadata, and optionally augments it with your business information – all in one step. It runs on [any CI platform](https://sbomify.com/sbomify-action/runtimes/), not just GitHub, and the source is [on GitHub](https://github.com/sbomify/sbomify-action/).

For Dart/Flutter, sbomify uses **cdxgen** or **Syft** under the hood.

**Standalone (no account needed):**

```yaml
- uses: sbomify/sbomify-action@master
  env:
    LOCK_FILE: pubspec.lock
    OUTPUT_FILE: sbom.cdx.json
    COMPONENT_NAME: my-flutter-app
    COMPONENT_VERSION: ${{ github.ref_name }}
    ENRICH: true
    UPLOAD: false
```

Using `github.ref_name` automatically captures your git tag (e.g., `v1.2.3`) as the SBOM version. For rolling releases without tags, use `github.sha` instead. See our [SBOM versioning guide](https://sbomify.com/guides/how-to-version-sboms/) for best practices.

**With sbomify platform (adds augmentation and upload):**

```yaml
- uses: sbomify/sbomify-action@master
  env:
    TOKEN: ${{ secrets.SBOMIFY_TOKEN }}
    COMPONENT_ID: my-component-id
    LOCK_FILE: pubspec.lock
    OUTPUT_FILE: sbom.cdx.json
    AUGMENT: true
    ENRICH: true
```

### Alternative Tools

If you prefer to run SBOM generation tools manually:

**cdxgen (recommended for manual use):**

```bash
npm install -g @cyclonedx/cdxgen
cdxgen -t dart -o sbom.cdx.json
```

**Syft:**

```bash
syft . -o cyclonedx-json=sbom.cdx.json
```

**sbom (Dart-native, SPDX only):**

```bash
dart pub add --dev sbom
```

Note: The `sbom` Dart package currently only supports SPDX format, not CycloneDX.

Use cdxgen or Syft for CycloneDX output.

When using these tools directly, you'll need to handle enrichment and augmentation separately.

### GitLab CI

```yaml
generate-sbom:
  image: ghcr.io/sbomify/sbomify-action
  variables:
    LOCK_FILE: pubspec.lock
    OUTPUT_FILE: sbom.cdx.json
    UPLOAD: "false"
    ENRICH: "true"
  script:
    - sbomify-action
  artifacts:
    paths:
      - sbom.cdx.json
```

## Handling Special Cases

### Git Dependencies

Packages from Git repositories:

```yaml
dependencies:
  my_package:
    git:
      url: https://github.com/example/my_package.git
      ref: v1.0.0
```

In `pubspec.lock`:

```yaml
my_package:
  dependency: "direct main"
  description:
    path: "."
    ref: v1.0.0
    resolved-ref: "abc123def456..."
    url: "https://github.com/example/my_package.git"
  source: git
  version: "1.0.0"
```

### Path Dependencies

Local packages:

```yaml
dependencies:
  my_local_package:
    path: ../my_local_package
```

These won't have pub.dev metadata. Document them with `ADDITIONAL_PACKAGES` if needed.

### Hosted Dependencies (Private)

For private package servers:

```yaml
dependencies:
  my_private_package:
    hosted:
      name: my_private_package
      url: https://packages.example.com
    version: ^1.0.0
```

Ensure your CI has authentication configured:

```bash
# Set up authentication
dart pub token add https://packages.example.com
```

## Monorepo Support (Melos)

For Dart/Flutter monorepos using [Melos](https://melos.invertase.dev/):

```yaml
# melos.yaml
name: my_workspace
packages:
  - packages/*
  - apps/*
```

Generate SBOMs per package or use Melos to run across all:

```bash
melos exec -- "cdxgen -t dart -o sbom.cdx.json"
```

## pub.dev Metadata Enrichment

pub.dev provides rich metadata for packages:

- License information
- Repository URLs
- Author information
- Documentation links

When using `ENRICH: true`, this metadata is added to your SBOM automatically.

## Best Practices

1. **Always commit pubspec.lock** - Essential for reproducible builds
2. **Use caret syntax carefully** - `^1.0.0` allows minor/patch updates
3. **Pin versions for production** - Consider exact versions for releases
4. **Separate dev dependencies** - Keep test/build tools in `dev_dependencies`
5. **Document native dependencies** - Flutter plugins have native code not in pubspec
6. **Run `dart pub outdated`** - Check for updates regularly

## Security Considerations

```bash
# Check for vulnerable packages
dart pub deps --json | jq '.packages[].name' # Export for scanning

# Use Flutter's built-in checks
flutter pub outdated
```

Combine dependency checks with SBOM generation in CI:

```yaml
- name: Check dependencies
  run: dart pub outdated --json > outdated.json

- name: Generate SBOM
  uses: sbomify/sbomify-action@master
  env:
    LOCK_FILE: 'pubspec.lock'
    OUTPUT_FILE: 'sbom.cdx.json'
    ENRICH: true
```

## Further Resources

For more SBOM tools and resources, see our [SBOM Resources](https://sbomify.com/resources/) page, which includes general SBOM utilities for generation, distribution, and analysis.

---

From sbomify: https://sbomify.com/guides/dart/
