Files
git.stella-ops.org/docs/modules/scanner/bun-analyzer-gotchas.md
StellaOps Bot dd0067ea0b
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Refactor code structure for improved readability and maintainability
2025-12-06 21:48:12 +02:00

147 lines
5.5 KiB
Markdown

# 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` Migration Path
The binary lockfile (`bun.lockb`) format is undocumented and unstable. The analyzer treats it as **unsupported** and emits a remediation finding.
**Migration command:**
```bash
bun install --save-text-lockfile
```
This generates `bun.lock` (JSONC text format) which the analyzer can parse.
**WebService response:** When only `bun.lockb` is present:
- The scan completes but reports unsupported status
- Remediation guidance is included in findings
- No package inventory is generated
## 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/<name>@<version>` 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 <id>
stellaops-cli bun resolve --digest sha256:<hash>
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
```