# Bun Analyzer Developer Gotchas This document covers common pitfalls and considerations when working with the Bun analyzer. ## 1. Isolated Installs Are Symlink-Heavy Bun's isolated linker (`bun install --linker isolated`) creates a flat store under `node_modules/.bun/` with symlinks for package resolution. This differs from the default hoisted layout. **Implications:** - The analyzer must traverse `node_modules/.bun/**/package.json` in addition to `node_modules/**/package.json` - Symlink safety guards are critical to prevent infinite loops and out-of-root traversal - Both logical and real paths are recorded in evidence for traceability - Performance guards (`MaxSymlinkDepth=10`, `MaxFilesPerRoot=50000`) are enforced **Testing:** - Use the `IsolatedLinkerInstallIsParsedAsync` test fixture to verify `.bun/` traversal - Use the `SymlinkSafetyIsEnforcedAsync` test fixture for symlink corner cases ## 2. `node_modules/.bun/` Scanning Requirement Unlike Node.js, Bun may store packages entirely under `node_modules/.bun/` with only symlinks in the top-level `node_modules/`. If your scanner configuration excludes `.bun/` directories, you will miss dependencies. **Checklist:** - Ensure glob patterns include `.bun/` subdirectories - Do not filter out hidden directories in container scans - Verify evidence shows packages from both `node_modules/` and `node_modules/.bun/` ## 3. `bun.lockb` Policy (2025-12-09) The binary lockfile (`bun.lockb`) remains **unsupported**. We will not parse it and will keep remediation-only handling until Bun publishes a stable, documented format. **Posture:** - Treat `bun.lockb` as unsupported input; do not attempt best-effort parsing. - Emit a deterministic remediation finding instructing conversion to text. - Skip package inventory when only `bun.lockb` is present to avoid nondeterministic/partial results. **Migration command (required):** ```bash bun install --save-text-lockfile ``` This generates `bun.lock` (JSONC text format) which the analyzer parses. **WebService response when only `bun.lockb` exists:** - Scan completes with `unsupported` marker for the package manager. - Remediation guidance is included in findings. - No package inventory is generated until `bun.lock` is provided. ## 4. JSONC Lockfile Format `bun.lock` uses JSONC (JSON with Comments) format supporting: - Single-line comments (`// ...`) - Multi-line comments (`/* ... */`) - Trailing commas in arrays and objects **Parser considerations:** - The `BunLockParser` tolerates these JSONC features - Standard JSON parsers will fail on `bun.lock` files - Format may evolve with Bun releases; parser is intentionally tolerant ## 5. Multi-Stage Build Implications In multi-stage Docker builds, the final image may contain only production artifacts without the lockfile or `node_modules/.bun/` directory. **Scanning strategies:** 1. **Image scanning (recommended for production):** Scans the final image filesystem. Set `include_dev: false` to filter dev dependencies 2. **Repository scanning:** Scans `bun.lock` from source. Includes all dependencies by default (`include_dev: true`) **Best practice:** Scan both the repository (for complete visibility) and production images (for runtime accuracy). ## 6. npm Ecosystem Reuse Bun packages are npm packages. The analyzer: - Emits `pkg:npm/@` PURLs (same as Node analyzer) - Uses `ecosystem = npm` for vulnerability lookups - Adds `package_manager = bun` metadata for differentiation This means: - Vulnerability intelligence is shared with Node analyzer - VEX statements for npm packages apply to Bun - No separate Bun-specific advisory database is needed ## 7. Source Detection in Lockfile `bun.lock` entries include source information that determines package type: | Source Pattern | Type | Example | |---------------|------|---------| | No source / default registry | `registry` | `lodash@4.17.21` | | `git+https://...` or `git://...` | `git` | VCS dependency | | `file:` or `link:` | `tarball` | Local package | | `workspace:` | `workspace` | Monorepo member | The analyzer records source type in evidence for provenance tracking. ## 8. Workspace/Monorepo Handling Bun workspaces use a single `bun.lock` at the root with multiple `package.json` files in subdirectories. **Analyzer behavior:** - Discovers the root by presence of `bun.lock` + `package.json` - Traverses all `node_modules/` directories under the root - Deduplicates packages by `(name, version)` while accumulating occurrence paths - Records workspace member paths in metadata **Testing:** Use the `WorkspacesAreParsedAsync` test fixture. ## 9. Dev/Prod Dependency Filtering The `include_dev` configuration option controls whether dev dependencies are included: | Context | Default `include_dev` | Rationale | |---------|----------------------|-----------| | Repository scan (lockfile-only) | `true` | Full visibility for developers | | Image scan (installed packages) | `true` | Packages are present regardless of intent | **Override:** Set `include_dev: false` in scan configuration to exclude dev dependencies from results. ## 10. Evidence Model Each Bun package includes evidence with: - `source`: Where the package was found (`node_modules`, `bun.lock`, `node_modules/.bun`) - `locator`: File path to the evidence - `resolved`: The resolved URL from lockfile (if available) - `integrity`: SHA hash from lockfile (if available) - `sha256`: File hash for installed packages Evidence enables: - Tracing packages to their origin - Validating integrity - Explaining presence in SBOM ## CLI Reference ### Inspect local workspace ```bash stellaops-cli bun inspect --root /path/to/project ``` ### Resolve packages from scan ```bash stellaops-cli bun resolve --scan-id stellaops-cli bun resolve --digest sha256: stellaops-cli bun resolve --ref myregistry.io/myapp:latest ``` ### Output formats ```bash stellaops-cli bun inspect --format json > packages.json stellaops-cli bun inspect --format table ```