Skip to content

Level C: Build Fingerprints

Compile-time markers embedded in every production build that identify the customer, build machine, and git commit.

C1: JavaScript Bundle Fingerprint

A constant __BD_BUILD_ID__ is injected via Vite's define configuration.

Format

{timestamp_base36}.{machine_hash_8}.{git_sha_short}.{customer_hash_8}

Injection

// vite.config.ts
define: {
  '__BD_BUILD_ID__': JSON.stringify(computeBuildId())
}

Survival

The obfuscator (vite-plugin-obfuscator) encodes the string via base64 string array, but the value persists in the bundle and can be extracted forensically.

Verification

# After production build
grep -r 'BD_BUILD_ID' dist/assets/*.js  # Present but obfuscated

C2: Flutter Binary Fingerprint

A BD_BUILD_FINGERPRINT Dart define is injected at build time.

Format

sha256(customer_id:build_timestamp:git_sha)[:32]

Injection

# desktop/build.sh
flutter build "$PLATFORM" --release \
  --dart-define="BD_BUILD_FINGERPRINT=$BUILD_FINGERPRINT"

Access in Code

static const String _buildFingerprint = String.fromEnvironment(
  'BD_BUILD_FINGERPRINT',
  defaultValue: 'dev-no-fingerprint',
);

C3: Docker Image Fingerprint

A .versions.json file in the Docker image root contains per-build metadata.

Content

{
  "tool_versions": {
    "nuclei": "3.x.x",
    "httpx": "1.x.x",
    "sqlmap": "1.x.x"
  },
  "build_id": "<hash>",
  "manifest_version": "1.0",
  "customer_ref": "<customer_hash>"
}

Build

docker build \
  --build-arg BD_BUILD_HASH=$(sha256sum <<< "$CUSTOMER:$TIMESTAMP" | cut -c1-32) \
  --build-arg BD_CUSTOMER_HASH=$CUSTOMER_HASH \
  -t pentest-tools .

Files Modified

File Change
dashboard/frontend/vite.config.ts Added define with __BD_BUILD_ID__
dashboard/frontend/src/utils/buildInfo.ts Dead-code reference to prevent tree-shaking
desktop/build.sh Added BD_BUILD_FINGERPRINT dart-define
desktop/lib/services/security_service.dart Read fingerprint from environment
Dockerfile Added BD_BUILD_HASH ARG and .versions.json