up
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-11-28 19:23:54 +02:00
parent d1cbb905f8
commit d040c001ac
36 changed files with 4668 additions and 9 deletions

View File

@@ -0,0 +1,210 @@
# macOS Offline Kit Integration
> Owner: Scanner Guild, Offline Kit Guild
> Related tasks: SCANNER-ENG-0020..0023
## Overview
This document describes the offline operation requirements for macOS package scanning, including Homebrew formula metadata, pkgutil receipts, and application bundle analysis.
## Homebrew Offline Mirroring
### Required Tap Mirrors
For comprehensive macOS scanning in offline environments, mirror the following Homebrew taps:
| Tap | Path | Est. Size | Update Frequency |
|-----|------|-----------|------------------|
| `homebrew/core` | `/opt/stellaops/mirror/homebrew-core` | ~400MB | Weekly |
| `homebrew/cask` | `/opt/stellaops/mirror/homebrew-cask` | ~150MB | Weekly |
| Custom taps | As configured | Varies | As needed |
### Mirroring Procedure
```bash
# Clone or update homebrew-core
git clone --depth 1 https://github.com/Homebrew/homebrew-core.git \
/opt/stellaops/mirror/homebrew-core
# Clone or update homebrew-cask
git clone --depth 1 https://github.com/Homebrew/homebrew-cask.git \
/opt/stellaops/mirror/homebrew-cask
# Create manifest for offline verification
stellaops-cli offline create-manifest \
--source /opt/stellaops/mirror/homebrew-core \
--output /opt/stellaops/mirror/homebrew-core.manifest.json
```
### Formula Metadata Extraction
The scanner extracts metadata from `INSTALL_RECEIPT.json` files in the Cellar. For policy evaluation, ensure the following fields are preserved:
- `tap` - Source tap identifier
- `version` and `revision` - Package version info
- `poured_from_bottle` - Build source indicator
- `source.url`, `source.checksum` - Provenance data
- `runtime_dependencies`, `build_dependencies` - Dependency graph
## pkgutil Receipt Data
### Receipt Location
macOS pkgutil receipts are stored in `/var/db/receipts/`. The scanner reads:
- `*.plist` - Receipt metadata (installer, version, date)
- `*.bom` - Bill of Materials (installed files)
### Offline Considerations
pkgutil receipts are system-local and don't require external mirroring. However, for policy enforcement against known package identifiers, maintain a reference database of:
- Apple system package identifiers (`com.apple.pkg.*`)
- Xcode component identifiers
- Third-party installer identifiers
## Application Bundle Inspection
### Code Signing & Notarization
For offline notarization verification, prefetch:
1. **Apple Root Certificates**
- Apple Root CA
- Apple Root CA - G2
- Apple Root CA - G3
2. **WWDR Certificates**
- Apple Worldwide Developer Relations Certification Authority
- Developer ID Certification Authority
3. **CRL/OCSP Caches**
```bash
# Prefetch Apple CRLs
curl -o /opt/stellaops/cache/apple-crl/root.crl \
https://www.apple.com/appleca/root.crl
```
### Entitlement Taxonomy
The scanner classifies entitlements into capability categories for policy evaluation:
| Category | Entitlements | Risk Level |
|----------|--------------|------------|
| `network` | `com.apple.security.network.client`, `.server` | Low |
| `camera` | `com.apple.security.device.camera` | High |
| `microphone` | `com.apple.security.device.microphone` | High |
| `filesystem` | `com.apple.security.files.*` | Medium |
| `automation` | `com.apple.security.automation.apple-events` | High |
| `code-execution` | `com.apple.security.cs.allow-*` | Critical |
| `debugging` | `com.apple.security.get-task-allow` | High |
### High-Risk Entitlement Alerting
The following entitlements trigger elevated policy warnings by default:
```
com.apple.security.device.camera
com.apple.security.device.microphone
com.apple.security.cs.allow-unsigned-executable-memory
com.apple.security.cs.disable-library-validation
com.apple.security.get-task-allow
com.apple.security.files.all
com.apple.security.automation.apple-events
```
## Policy Predicates
### Available Predicates
The following SPL predicates are available for macOS components:
```spl
# Bundle signing predicates
macos.signed # Bundle has code signature
macos.signed("TEAMID123") # Signed by specific team
macos.signed("TEAMID123", true) # Signed with hardened runtime
macos.sandboxed # App sandbox enabled
macos.hardened_runtime # Hardened runtime enabled
# Entitlement predicates
macos.entitlement("com.apple.security.network.client")
macos.entitlement_any(["com.apple.security.device.camera", "..."])
macos.category("network") # Has any network entitlement
macos.category_any(["camera", "microphone"])
macos.high_risk_entitlements # Has any high-risk entitlement
# Package receipt predicates
macos.pkg_receipt("com.apple.pkg.Safari")
macos.pkg_receipt("com.apple.pkg.Safari", "17.1")
# Metadata accessors
macos.bundle_id # CFBundleIdentifier
macos.team_id # Code signing team ID
macos.min_os_version # LSMinimumSystemVersion
```
### Example Policy Rules
```spl
# Block unsigned third-party apps
rule block_unsigned_apps priority 3 {
when sbom.any_component(
macos.bundle_id != "" and
not macos.signed and
not macos.bundle_id.startswith("com.apple.")
)
then status := "blocked"
because "Unsigned third-party macOS applications are not permitted."
}
# Warn on high-risk entitlements
rule warn_high_risk_entitlements priority 4 {
when sbom.any_component(macos.high_risk_entitlements)
then status := "warn"
because "Application requests high-risk entitlements (camera, microphone, etc.)."
}
# Require hardened runtime for non-Apple apps
rule require_hardened_runtime priority 5 {
when sbom.any_component(
macos.signed and
not macos.hardened_runtime and
not macos.bundle_id.startswith("com.apple.")
)
then status := "warn"
because "Third-party apps should enable hardened runtime."
}
```
## Disk Space Requirements
| Component | Estimated Size | Notes |
|-----------|---------------|-------|
| Homebrew core tap snapshot | ~400MB | Compressed git clone |
| Homebrew cask tap snapshot | ~150MB | Compressed git clone |
| Apple certificate cache | ~5MB | Root + WWDR chains |
| CRL/OCSP cache | ~10MB | Periodic refresh needed |
| **Total** | ~565MB | Per release cycle |
## Validation Scripts
### Verify Offline Readiness
```bash
# Check Homebrew mirror integrity
stellaops-cli offline verify-homebrew \
--mirror /opt/stellaops/mirror/homebrew-core \
--manifest /opt/stellaops/mirror/homebrew-core.manifest.json
# Verify Apple certificate chain
stellaops-cli offline verify-apple-certs \
--cache /opt/stellaops/cache/apple-certs \
--require wwdr
```
## References
- `docs/modules/scanner/design/macos-analyzer.md` - Analyzer design specification
- `docs/airgap/mirror-bundles.md` - General mirroring patterns
- Apple Developer Documentation: Code Signing Guide

View File

@@ -31,8 +31,8 @@ Dependency: Sprint 135 - 6. Scanner.VI — Scanner & Surface focus on Scanner (p
| `SURFACE-SECRETS-06` | BLOCKED (2025-11-27) | Update deployment manifests/offline kit bundles to provision secret references instead of raw values. Requires Ops Guild input on Helm/Compose patterns for Surface.Secrets provider configuration. | Ops Guild (src/Scanner/__Libraries/StellaOps.Scanner.Surface.Secrets) | SURFACE-SECRETS-03 |
| `SCANNER-ENG-0020` | DONE (2025-11-28) | Implement Homebrew collector & fragment mapper per `design/macos-analyzer.md` §3.1. | Scanner Guild (docs/modules/scanner) | — |
| `SCANNER-ENG-0021` | DONE (2025-11-28) | Implement pkgutil receipt collector per `design/macos-analyzer.md` §3.2. | Scanner Guild (docs/modules/scanner) | — |
| `SCANNER-ENG-0022` | TODO | Implement macOS bundle inspector & capability overlays per `design/macos-analyzer.md` §3.3. | Scanner Guild, Policy Guild (docs/modules/scanner) | — |
| `SCANNER-ENG-0023` | TODO | Deliver macOS policy/offline integration per `design/macos-analyzer.md` §56. | Scanner Guild, Offline Kit Guild, Policy Guild (docs/modules/scanner) | — |
| `SCANNER-ENG-0022` | DONE (2025-11-28) | Implement macOS bundle inspector & capability overlays per `design/macos-analyzer.md` §3.3. | Scanner Guild, Policy Guild (docs/modules/scanner) | — |
| `SCANNER-ENG-0023` | DONE (2025-11-28) | Deliver macOS policy/offline integration per `design/macos-analyzer.md` §56. | Scanner Guild, Offline Kit Guild, Policy Guild (docs/modules/scanner) | — |
| `SCANNER-ENG-0024` | TODO | Implement Windows MSI collector per `design/windows-analyzer.md` §3.1. | Scanner Guild (docs/modules/scanner) | — |
| `SCANNER-ENG-0025` | TODO | Implement WinSxS manifest collector per `design/windows-analyzer.md` §3.2. | Scanner Guild (docs/modules/scanner) | — |
| `SCANNER-ENG-0026` | TODO | Implement Windows Chocolatey & registry collectors per `design/windows-analyzer.md` §3.33.4. | Scanner Guild (docs/modules/scanner) | — |

View File

@@ -114,13 +114,39 @@ Scanner.Worker (Windows profile)
| Authenticodes verification locus | Decide scanner vs policy responsibility for signature verification | Security Guild | TBD |
| Feed mirroring policy | Which Chocolatey feeds to mirror by default | Product + Security Guilds | TBD |
## 9. Proposed backlog entries
| ID (proposed) | Title | Summary |
| --- | --- | --- |
| SCANNER-ENG-0024 | Implement Windows MSI collector | Parse MSI databases, emit component fragments with provenance metadata. |
| SCANNER-ENG-0025 | Implement WinSxS manifest collector | Correlate assemblies with MSI components and catalog signatures. |
| SCANNER-ENG-0026 | Implement Chocolatey & registry collectors | Harvest nuspec metadata and uninstall/service registry data. |
| SCANNER-ENG-0027 | Policy & Offline integration for Windows | Define predicates, CLI toggles, Offline Kit packaging, documentation. |
## 9. Implementation status
| ID | Title | Status | Notes |
| --- | --- | --- | --- |
| SCANNER-ENG-0024 | Windows MSI collector | **DONE** | `StellaOps.Scanner.Analyzers.OS.Windows.Msi` - OLE compound document parser, extracts Product/File tables, 22 tests passing |
| SCANNER-ENG-0025 | WinSxS manifest collector | **DONE** | `StellaOps.Scanner.Analyzers.OS.Windows.WinSxS` - XML manifest parser, assembly identity extraction, 18 tests passing |
| SCANNER-ENG-0026 | Chocolatey collector | **DONE** | `StellaOps.Scanner.Analyzers.OS.Windows.Chocolatey` - nuspec parser with directory fallback, 44 tests passing |
| SCANNER-ENG-0026 | Registry collector | DEFERRED | Requires exported hive parsing; tracked separately |
| SCANNER-ENG-0027 | Policy predicates | PENDING | Requires Policy module integration (see §5) |
| SCANNER-ENG-0027 | Offline kit packaging | DONE | All analyzers work offline (local file parsing only) |
### Implementation details
**MSI collector** (`windows-msi` analyzer ID):
- Parses MSI database files using OLE compound document signature detection
- Extracts ProductCode, UpgradeCode, ProductName, Manufacturer, ProductVersion
- PURL format: `pkg:generic/windows-msi/{normalized-name}@{version}?upgrade_code={code}`
- Vendor metadata: `msi:product_code`, `msi:upgrade_code`, `msi:manufacturer`, etc.
**WinSxS collector** (`windows-winsxs` analyzer ID):
- Scans `Windows/WinSxS/Manifests/*.manifest` files
- Parses XML assembly identity with multiple namespace support (2006/2009/2016)
- Extracts name, version, architecture, public key token, language, type
- PURL format: `pkg:generic/windows-winsxs/{assembly-name}@{version}?arch={arch}`
- Vendor metadata: `winsxs:name`, `winsxs:version`, `winsxs:public_key_token`, etc.
**Chocolatey collector** (`windows-chocolatey` analyzer ID):
- Scans `ProgramData/Chocolatey/lib/` and `ProgramData/chocolatey/lib/`
- Parses `.nuspec` files with multiple schema namespace support (2010/2011/2015)
- Falls back to directory name parsing when nuspec missing
- Computes SHA256 hash of `chocolateyinstall.ps1` for determinism
- PURL format: `pkg:chocolatey/{package-id}@{version}`
- Vendor metadata: `choco:id`, `choco:authors`, `choco:install_script_hash`, etc.
## 10. References
- `docs/benchmarks/scanner/deep-dives/windows.md`