diff --git a/.claude/commands/sync-checksums.md b/.claude/commands/sync-checksums.md
index 91f52ea69..ccebd86df 100644
--- a/.claude/commands/sync-checksums.md
+++ b/.claude/commands/sync-checksums.md
@@ -1,9 +1,9 @@
-Sync SHA-256 checksums from GitHub releases to external-tools.json using the syncing-checksums skill.
+Sync SHA-256 checksums from GitHub releases to bundle-tools.json using the syncing-checksums skill.
## What it does
1. Fetches checksums.txt from GitHub releases (or computes from assets)
-2. Updates packages/cli/external-tools.json
+2. Updates packages/cli/bundle-tools.json
3. Validates JSON syntax
4. Commits changes (if any)
diff --git a/.claude/skills/_shared/security-tools.md b/.claude/skills/_shared/security-tools.md
index 9a1f02716..345ab80b1 100644
--- a/.claude/skills/_shared/security-tools.md
+++ b/.claude/skills/_shared/security-tools.md
@@ -11,7 +11,7 @@ No install step needed — available after `pnpm install`.
## Zizmor
Not an npm package. Installed via `pnpm run setup` which downloads the pinned version
-from GitHub releases with SHA256 checksum verification (see `external-tools.json`).
+from GitHub releases with SHA256 checksum verification (see `bundle-tools.json`).
The binary is cached at `.cache/external-tools/zizmor/{version}-{platform}/zizmor`.
diff --git a/.claude/skills/updating-checksums/SKILL.md b/.claude/skills/updating-checksums/SKILL.md
index 2ba0ffb56..97777b04c 100644
--- a/.claude/skills/updating-checksums/SKILL.md
+++ b/.claude/skills/updating-checksums/SKILL.md
@@ -1,7 +1,7 @@
---
name: updating-checksums
description: >
- Syncs SHA-256 checksums from GitHub releases to external-tools.json.
+ Syncs SHA-256 checksums from GitHub releases to bundle-tools.json.
Triggers when user mentions "update checksums", "sync checksums", or after
releasing new tool versions.
user-invocable: true
@@ -11,7 +11,7 @@ allowed-tools: Bash, Read, Edit
# updating-checksums
-Your task is to sync SHA-256 checksums from GitHub releases to the embedded `external-tools.json` file, ensuring SEA builds have up-to-date integrity verification.
+Your task is to sync SHA-256 checksums from GitHub releases to the embedded `bundle-tools.json` file, ensuring SEA builds have up-to-date integrity verification.
@@ -24,10 +24,10 @@ Your task is to sync SHA-256 checksums from GitHub releases to the embedded `ext
## Phases
-1. **Check Current State** - Review current checksums and tool versions in `packages/cli/external-tools.json`.
+1. **Check Current State** - Review current checksums and tool versions in `packages/cli/bundle-tools.json`.
2. **Sync Checksums** - Run `node packages/cli/scripts/sync-checksums.mjs`. Tries `checksums.txt` from the release first; falls back to downloading assets and computing SHA-256.
-3. **Verify Changes** - `git diff packages/cli/external-tools.json`; validate JSON syntax.
-4. **Commit Changes** - If updated, commit `packages/cli/external-tools.json`.
+3. **Verify Changes** - `git diff packages/cli/bundle-tools.json`; validate JSON syntax.
+4. **Commit Changes** - If updated, commit `packages/cli/bundle-tools.json`.
## Commands
diff --git a/.claude/skills/updating-checksums/reference.md b/.claude/skills/updating-checksums/reference.md
index 57e1116b7..e566666b9 100644
--- a/.claude/skills/updating-checksums/reference.md
+++ b/.claude/skills/updating-checksums/reference.md
@@ -46,7 +46,7 @@ This document provides detailed information about external tool checksums, the s
### How It Works
-1. Reads `packages/cli/external-tools.json`
+1. Reads `packages/cli/bundle-tools.json`
2. Filters tools with `type: "github-release"`
3. For each tool:
a. Fetches the GitHub release by tag
@@ -54,7 +54,7 @@ This document provides detailed information about external tool checksums, the s
c. If found: parses SHA-256 hashes from checksums.txt
d. If not found: downloads each release asset and computes SHA-256 via `crypto.createHash('sha256')`
4. Compares new checksums with existing
-5. Writes updated checksums to external-tools.json
+5. Writes updated checksums to bundle-tools.json
### Command Reference
@@ -146,7 +146,7 @@ Each tool has specific asset naming conventions:
### Checksum Storage Format
-In `external-tools.json`, checksums are stored as:
+In `bundle-tools.json`, checksums are stored as:
```json
{
@@ -192,7 +192,7 @@ stream.pipe(hash)
### Tool with Dual Configuration (sfw)
-The `sfw` tool has both a GitHub release binary (`SocketDev/sfw-free`) and an npm package (`sfw` on npmjs.com). Both are tracked in the same `external-tools.json` entry via `type: "github-release"` for the binary checksums and `npmPackage`/`npmVersion` fields for the npm component. The checksums skill only handles the GitHub release binary checksums; the npm package version is updated separately via `pnpm run update`.
+The `sfw` tool has both a GitHub release binary (`SocketDev/sfw-free`) and an npm package (`sfw` on npmjs.com). Both are tracked in the same `bundle-tools.json` entry via `type: "github-release"` for the binary checksums and `npmPackage`/`npmVersion` fields for the npm component. The checksums skill only handles the GitHub release binary checksums; the npm package version is updated separately via `pnpm run update`.
### python-build-standalone
@@ -206,11 +206,11 @@ This tool has no checksums.txt in releases. The sync script must:
Different tools use different tag formats:
- Most use `v{version}` (e.g., `v1.16.0`)
- python-build-standalone uses bare version (e.g., `3.11.14`)
-- The `githubRelease` field in external-tools.json stores the exact tag
+- The `githubRelease` field in bundle-tools.json stores the exact tag
### Stale Checksums After Version Bump
-If someone updates a tool version in external-tools.json but forgets to sync checksums:
+If someone updates a tool version in bundle-tools.json but forgets to sync checksums:
- SEA builds will fail integrity verification
- Always run checksum sync after any version change
@@ -237,7 +237,7 @@ Authenticated requests get 5,000 requests/hour vs 60 for unauthenticated.
**Symptom:** Script reports release not found for a tool.
-**Cause:** The `githubRelease` tag in external-tools.json doesn't match any release.
+**Cause:** The `githubRelease` tag in bundle-tools.json doesn't match any release.
**Solution:**
```bash
@@ -258,15 +258,15 @@ gh release list --repo --limit 5
### JSON Validation Failure
-**Symptom:** Updated external-tools.json is invalid JSON.
+**Symptom:** Updated bundle-tools.json is invalid JSON.
**Solution:**
```bash
# Validate JSON
-node -e "JSON.parse(require('fs').readFileSync('packages/cli/external-tools.json'))"
+node -e "JSON.parse(require('fs').readFileSync('packages/cli/bundle-tools.json'))"
# If corrupted, restore and retry
-git checkout packages/cli/external-tools.json
+git checkout packages/cli/bundle-tools.json
node packages/cli/scripts/sync-checksums.mjs
```
diff --git a/.claude/skills/updating/reference.md b/.claude/skills/updating/reference.md
index 7045b89ae..336c048c5 100644
--- a/.claude/skills/updating/reference.md
+++ b/.claude/skills/updating/reference.md
@@ -28,7 +28,7 @@ Updated via `pnpm run update` which runs `scripts/update.mjs`:
Updated via the `updating-checksums` skill which runs `packages/cli/scripts/sync-checksums.mjs`:
-- Syncs SHA-256 checksums from GitHub releases to `packages/cli/external-tools.json`
+- Syncs SHA-256 checksums from GitHub releases to `packages/cli/bundle-tools.json`
- Only processes tools with `type: "github-release"`
---
@@ -68,9 +68,9 @@ After update, these files may be modified:
## External Tool Checksums
-### external-tools.json Structure
+### bundle-tools.json Structure
-**Location:** `packages/cli/external-tools.json`
+**Location:** `packages/cli/bundle-tools.json`
**Tool types:**
@@ -103,10 +103,10 @@ After update, these files may be modified:
**Location:** `packages/cli/scripts/sync-checksums.mjs`
**Process:**
-1. Reads `external-tools.json` for GitHub release tools
+1. Reads `bundle-tools.json` for GitHub release tools
2. For each tool, tries to download `checksums.txt` from the release
3. If no checksums.txt, downloads each asset and computes SHA-256
-4. Updates embedded checksums in `external-tools.json`
+4. Updates embedded checksums in `bundle-tools.json`
**Options:**
- `--tool=` - Sync specific tool only
@@ -115,7 +115,7 @@ After update, these files may be modified:
### When to Sync Checksums
-- After manually updating tool versions in external-tools.json
+- After manually updating tool versions in bundle-tools.json
- After new GitHub releases are published for any tool
- As part of the full update cycle (run after npm updates)
diff --git a/docs/external-tools.md b/docs/bundle-tools.md
similarity index 95%
rename from docs/external-tools.md
rename to docs/bundle-tools.md
index 8e1f8befb..3ccf05e15 100644
--- a/docs/external-tools.md
+++ b/docs/bundle-tools.md
@@ -27,7 +27,7 @@ Socket CLI integrates with external security tools for scanning, analysis, and v
## Configuration
-All tools are defined in `packages/cli/external-tools.json`:
+All tools are defined in `packages/cli/bundle-tools.json`:
```json
{
@@ -129,7 +129,7 @@ When installed via npm, tools are downloaded at runtime.
### Checksum Verification
-All downloads are verified with SHA-256 checksums defined in `external-tools.json`:
+All downloads are verified with SHA-256 checksums defined in `bundle-tools.json`:
```json
{
@@ -168,7 +168,7 @@ Environment variables for development/testing:
| File | Purpose |
|------|---------|
-| `external-tools.json` | Tool definitions, versions, checksums |
+| `bundle-tools.json` | Tool definitions, versions, checksums |
| `src/utils/dlx/resolve-binary.mts` | Binary resolution logic |
| `src/utils/dlx/spawn.mts` | Tool spawning (VFS + dlx) |
| `src/utils/dlx/vfs-extract.mts` | VFS extraction utilities |
@@ -181,7 +181,7 @@ Environment variables for development/testing:
## Adding a New Tool
-1. Add entry to `external-tools.json` with version and checksums
+1. Add entry to `bundle-tools.json` with version and checksums
2. Create `src/env/{tool}-version.mts` version getter
3. Create `src/env/{tool}-checksums.mts` checksum getter (if applicable)
4. Add resolve function in `src/utils/dlx/resolve-binary.mts`
diff --git a/packages/cli/external-tools.json b/packages/cli/bundle-tools.json
similarity index 81%
rename from packages/cli/external-tools.json
rename to packages/cli/bundle-tools.json
index 07ab89983..98d1497e7 100644
--- a/packages/cli/external-tools.json
+++ b/packages/cli/bundle-tools.json
@@ -1,25 +1,22 @@
{
- "$schema": "External tools configuration for Socket CLI VFS bundling",
- "$comment": "Build process uses @npmcli/arborist (scripts/sea-build-utils/npm-packages.mjs) to download npm packages with full dependency trees. npm packages are bundled with node_modules/ into VFS alongside security tool binaries. For github-release types, 'githubRelease' is the release tag (any format: v1.6.1, 3.11.14, etc.).",
+ "$schema": "Bundle tools configuration for Socket CLI VFS bundling",
"@coana-tech/cli": {
"description": "Coana CLI for static analysis and reachability detection",
- "type": "npm",
- "package": "@coana-tech/cli",
"version": "14.12.165",
+ "packageManager": "npm",
"integrity": "sha512-Fs/gGzBEFl23x0Xw+eBOnyX2WUaoc82ppgZrrDN9hpB84CN8r0ZEw22IQRpiJTmhmOlbSwiArpRw45VkgJY5sw=="
},
"@cyclonedx/cdxgen": {
"description": "CycloneDX SBOM generator for software bill of materials",
- "type": "npm",
- "package": "@cyclonedx/cdxgen",
"version": "12.0.0",
+ "packageManager": "npm",
"integrity": "sha512-RRXEZ1eKHcU+Y/2AnfIg30EQRbOmlEpaJddmMVetpXeYpnxDy/yjBM67jXNKkA4iZYjZzfWe7I5GuxckRmuoqg=="
},
"opengrep": {
"description": "OpenGrep SAST/code analysis engine (fork of Semgrep)",
- "type": "github-release",
- "repository": "opengrep/opengrep",
- "githubRelease": "v1.16.0",
+ "repository": "github:opengrep/opengrep",
+ "release": "asset",
+ "version": "v1.16.0",
"checksums": {
"opengrep-core_linux_aarch64.tar.gz": "e6a92e2c465b53284ae326d20b315acbd2eb99bc9ea4b3af48db6379306f3a82",
"opengrep-core_linux_x86.tar.gz": "4d474141329983c4ddd7a6cd586759deecc7f3fa9aee6e6eeab8c55759dc816b",
@@ -30,10 +27,10 @@
},
"python": {
"description": "Python runtime from python-build-standalone",
- "type": "github-release",
- "repository": "astral-sh/python-build-standalone",
- "githubRelease": "3.11.14",
- "buildTag": "20260203",
+ "repository": "github:astral-sh/python-build-standalone",
+ "release": "asset",
+ "version": "3.11.14",
+ "tag": "20260203",
"checksums": {
"cpython-3.11.14+20260203-aarch64-apple-darwin-install_only.tar.gz": "63e3352fefd3b6494f73f46f51c6581c57a7e0d98775e6e00229d14a67ec3ce9",
"cpython-3.11.14+20260203-aarch64-pc-windows-msvc-install_only.tar.gz": "cb7828c131a005da367f7dba3a561bed91619452de870e531ee03344b2ac346f",
@@ -47,16 +44,15 @@
},
"socket-basics": {
"description": "Socket Basics - integrated SAST, secret scanning, and container analysis",
- "type": "github-source",
- "repository": "SocketDev/socket-basics",
- "githubRelease": "v2.0.2",
- "package": "socket_basics"
+ "repository": "github:SocketDev/socket-basics",
+ "release": "archive",
+ "version": "v2.0.2",
+ "packageManager": "pip"
},
"socketsecurity": {
"description": "Socket Python CLI (socket-python-cli)",
- "type": "pypi",
- "package": "socketsecurity",
"version": "2.2.70",
+ "packageManager": "pip",
"checksums": {
"socketsecurity-2.2.70-py3-none-any.whl": "8633c2a7f204cc5cec18d8ed04cfd09aa448f7e2257345596435493d2102ba5d",
"socketsecurity-2.2.70.tar.gz": "e5212fb9b6b7bee3c5d936efe439508df76a7d0d81b99f84f6eafe760f3d77b7"
@@ -64,9 +60,9 @@
},
"socket-patch": {
"description": "Socket Patch CLI for applying security patches (Rust binary)",
- "type": "github-release",
- "repository": "SocketDev/socket-patch",
- "githubRelease": "v2.0.0",
+ "repository": "github:SocketDev/socket-patch",
+ "release": "asset",
+ "version": "v2.0.0",
"checksums": {
"socket-patch-aarch64-apple-darwin.tar.gz": "dd8f778aef4db3f2c5000cd870101a31d1bb03822158d76e5bd2e773098428f0",
"socket-patch-aarch64-pc-windows-msvc.zip": "5c0bbfc12d2b6f30a0f79caf4bff85a1eac6baf9541c46d9af4b3f37b05bd574",
@@ -78,11 +74,9 @@
},
"sfw": {
"description": "Socket Firewall (sfw) - GitHub binary for SEA, npm package for CLI",
- "type": "github-release",
- "repository": "SocketDev/sfw-free",
- "githubRelease": "v1.6.1",
- "npmPackage": "sfw",
- "npmVersion": "2.0.4",
+ "repository": "github:SocketDev/sfw-free",
+ "release": "asset",
+ "version": "v1.6.1",
"checksums": {
"sfw-free-linux-arm64": "df2eedb2daf2572eee047adb8bfd81c9069edcb200fc7d3710fca98ec3ca81a1",
"sfw-free-linux-x86_64": "4a1e8b65e90fce7d5fd066cf0af6c93d512065fa4222a475c8d959a6bc14b9ff",
@@ -91,20 +85,23 @@
"sfw-free-musl-linux-arm64": "41e5ebfe84e33eb7f34846eeb1b0e0c3039b2ba8bcdb87f4a75a5ccb89c64ae1",
"sfw-free-musl-linux-x86_64": "19f26c163311d5d0b184d305304972d26c52e445659c9142cefc7d8a11e06c3a",
"sfw-free-windows-x86_64.exe": "c953e62ad7928d4d8f2302f5737884ea1a757babc26bed6a42b9b6b68a5d54af"
+ },
+ "npm": {
+ "package": "sfw",
+ "version": "2.0.4"
}
},
"synp": {
"description": "Tool for converting between yarn.lock and package-lock.json",
- "type": "npm",
- "package": "synp",
"version": "1.9.14",
+ "packageManager": "npm",
"integrity": "sha512-0e4u7KtrCrMqvuXvDN4nnHSEQbPlONtJuoolRWzut0PfuT2mEOvIFnYFHEpn5YPIOv7S5Ubher0b04jmYRQOzQ=="
},
"trivy": {
"description": "Trivy container and filesystem vulnerability scanner",
- "type": "github-release",
- "repository": "aquasecurity/trivy",
- "githubRelease": "v0.69.2",
+ "repository": "github:aquasecurity/trivy",
+ "release": "asset",
+ "version": "v0.69.2",
"checksums": {
"trivy_0.69.2_Linux-64bit.tar.gz": "affa59a1e37d86e4b8ab2cd02f0ab2e63d22f1bf9cf6a7aa326c884e25e26ce3",
"trivy_0.69.2_Linux-ARM64.tar.gz": "c73b97699c317b0d25532b3f188564b4e29d13d5472ce6f8eb078082546a6481",
@@ -115,9 +112,9 @@
},
"trufflehog": {
"description": "TruffleHog secret and credential detection",
- "type": "github-release",
- "repository": "trufflesecurity/trufflehog",
- "githubRelease": "v3.93.1",
+ "repository": "github:trufflesecurity/trufflehog",
+ "release": "asset",
+ "version": "v3.93.1",
"checksums": {
"trufflehog_3.93.1_darwin_amd64.tar.gz": "f1f4ecbda3996b88dc70cf6aef2c469c4902efb591aca86128d6305d606d8e07",
"trufflehog_3.93.1_darwin_arm64.tar.gz": "d65a2ad0f043a9d48a97176f28533890e558817e2fb7dd1e34132653b61be4a0",
diff --git a/packages/cli/scripts/environment-variables.mjs b/packages/cli/scripts/environment-variables.mjs
index 6e7a859dc..6fcec9ae6 100644
--- a/packages/cli/scripts/environment-variables.mjs
+++ b/packages/cli/scripts/environment-variables.mjs
@@ -56,9 +56,9 @@ export class EnvironmentVariables {
}).trim()
} catch {}
- // Get external tool versions from external-tools.json.
+ // Get external tool versions from bundle-tools.json.
const externalTools = JSON.parse(
- readFileSync(path.join(rootPath, 'external-tools.json'), 'utf-8'),
+ readFileSync(path.join(rootPath, 'bundle-tools.json'), 'utf-8'),
)
/**
@@ -68,13 +68,13 @@ export class EnvironmentVariables {
const tool = externalTools[key]
if (!tool) {
throw new Error(
- `External tool "${key}" not found in external-tools.json. Please add it to the configuration.`,
+ `External tool "${key}" not found in bundle-tools.json. Please add it to the configuration.`,
)
}
const value = tool[field]
if (!value) {
throw new Error(
- `External tool "${key}" is missing required field "${field}" in external-tools.json.`,
+ `External tool "${key}" is missing required field "${field}" in bundle-tools.json.`,
)
}
return value
@@ -86,16 +86,21 @@ export class EnvironmentVariables {
const synpVersion = getExternalToolVersion('synp')
// pypi packages use 'version' field.
const pyCliVersion = getExternalToolVersion('socketsecurity')
- // github-release tools use 'githubRelease' field (release tag, any format).
- const opengrepVersion = getExternalToolVersion('opengrep', 'githubRelease')
- const pythonBuildTag = getExternalToolVersion('python', 'buildTag')
- const pythonVersion = getExternalToolVersion('python', 'githubRelease')
- const socketPatchVersion = getExternalToolVersion('socket-patch', 'githubRelease')
- const trivyVersion = getExternalToolVersion('trivy', 'githubRelease')
- const trufflehogVersion = getExternalToolVersion('trufflehog', 'githubRelease')
+ // GitHub-released tools use 'version' field (release tag, any format).
+ const opengrepVersion = getExternalToolVersion('opengrep')
+ const pythonBuildTag = getExternalToolVersion('python', 'tag')
+ const pythonVersion = getExternalToolVersion('python')
+ const socketPatchVersion = getExternalToolVersion('socket-patch')
+ const trivyVersion = getExternalToolVersion('trivy')
+ const trufflehogVersion = getExternalToolVersion('trufflehog')
// sfw uses both: GitHub binary for SEA, npm package for CLI.
- const sfwVersion = getExternalToolVersion('sfw', 'githubRelease')
- const sfwNpmVersion = getExternalToolVersion('sfw', 'npmVersion')
+ const sfwVersion = getExternalToolVersion('sfw')
+ const sfwNpmVersion = externalTools['sfw']?.npm?.version
+ if (!sfwNpmVersion) {
+ throw new Error(
+ 'External tool "sfw" is missing required field "npm.version" in bundle-tools.json.',
+ )
+ }
// Build-time constants that can be overridden by environment variables.
const publishedBuild =
@@ -158,17 +163,17 @@ export class EnvironmentVariables {
static loadSafe() {
try {
const externalTools = JSON.parse(
- readFileSync(path.join(rootPath, 'external-tools.json'), 'utf-8'),
+ readFileSync(path.join(rootPath, 'bundle-tools.json'), 'utf-8'),
)
return {
INLINED_COANA_VERSION:
externalTools['@coana-tech/cli']?.version || '',
INLINED_PYCLI_VERSION:
externalTools.socketsecurity?.version || '',
- INLINED_SFW_NPM_VERSION: externalTools.sfw?.npmVersion || '',
- INLINED_SFW_VERSION: externalTools.sfw?.githubRelease || '',
+ INLINED_SFW_NPM_VERSION: externalTools.sfw?.npm?.version || '',
+ INLINED_SFW_VERSION: externalTools.sfw?.version || '',
INLINED_SOCKET_PATCH_VERSION:
- externalTools['socket-patch']?.githubRelease || '',
+ externalTools['socket-patch']?.version || '',
}
} catch {
return {}
diff --git a/packages/cli/scripts/sea-build-utils/downloads.mjs b/packages/cli/scripts/sea-build-utils/downloads.mjs
index b456eaee2..4abe81c76 100644
--- a/packages/cli/scripts/sea-build-utils/downloads.mjs
+++ b/packages/cli/scripts/sea-build-utils/downloads.mjs
@@ -35,11 +35,11 @@ import { PLATFORM_MAP_TOOLS } from '../constants/external-tools-platforms.mjs'
export const logger = getDefaultLogger()
/**
- * External tools configuration loaded from external-tools.json.
+ * External tools configuration loaded from bundle-tools.json.
* Contains version info, GitHub repos, and download metadata for security tools.
*/
const __dirname = path.dirname(fileURLToPath(import.meta.url))
-const externalToolsPath = path.join(__dirname, '../../external-tools.json')
+const externalToolsPath = path.join(__dirname, '../../bundle-tools.json')
export const externalTools = JSON.parse(readFileSync(externalToolsPath, 'utf8'))
/**
@@ -251,31 +251,28 @@ export async function downloadExternalTools(platform, arch, isMusl = false) {
}
// Security tool versions and GitHub release info.
- // Versions are read from external-tools.json for centralized management.
+ // Versions are read from bundle-tools.json for centralized management.
// Repository info is derived from the 'repository' field (format: owner/repo).
const TOOL_REPOS = {
__proto__: null,
}
- // Populate TOOL_REPOS from external-tools.json.
- // Filter by type === 'github-release' to include all GitHub-released tools.
+ // Populate TOOL_REPOS from bundle-tools.json.
+ // Filter by release === 'asset' to include all GitHub-released tools.
for (const [toolName, toolConfig] of Object.entries(externalTools)) {
- if (toolConfig.type === 'github-release') {
- const parts = toolConfig.repository.split('/')
+ if (toolConfig.release === 'asset') {
+ const repoPath = toolConfig.repository.replace(/^github:/, '')
+ const parts = repoPath.split('/')
if (parts.length !== 2 || !parts[0] || !parts[1]) {
throw new Error(
- `Invalid repository format for ${toolName}: expected 'owner/repo', got '${toolConfig.repository}'`,
+ `Invalid repository format for ${toolName}: expected 'github:owner/repo', got '${toolConfig.repository}'`,
)
}
const [owner, repo] = parts
TOOL_REPOS[toolName] = {
owner,
repo,
- // Python uses buildTag for release tag, others use githubRelease field.
- version:
- toolName === 'python'
- ? toolConfig.buildTag
- : toolConfig.githubRelease,
+ version: toolConfig.tag ?? toolConfig.version,
}
}
}
@@ -297,11 +294,11 @@ export async function downloadExternalTools(platform, arch, isMusl = false) {
for (const [toolName, assetName] of Object.entries(toolsForPlatform)) {
const config = TOOL_REPOS[toolName]
- // Validate tool exists in TOOL_REPOS (populated from external-tools.json).
+ // Validate tool exists in TOOL_REPOS (populated from bundle-tools.json).
if (!config) {
throw new Error(
`Tool "${toolName}" is defined in platform mappings but not found in TOOL_REPOS. ` +
- `Ensure "${toolName}" exists in external-tools.json with type "github-release".`,
+ `Ensure "${toolName}" exists in bundle-tools.json with release "asset".`,
)
}
@@ -327,7 +324,7 @@ export async function downloadExternalTools(platform, arch, isMusl = false) {
const tag = config.version
const url = `https://github.com/${config.owner}/${config.repo}/releases/download/${tag}/${assetName}`
- // Get SHA256 checksum from external-tools.json.
+ // Get SHA256 checksum from bundle-tools.json.
// SECURITY: Checksum verification is REQUIRED for all external tool downloads.
// If checksum is missing, the build MUST fail.
const toolConfig = externalTools[toolName]
@@ -336,7 +333,7 @@ export async function downloadExternalTools(platform, arch, isMusl = false) {
if (!sha256) {
throw new Error(
`Missing SHA-256 checksum for ${toolName} asset: ${assetName}. ` +
- 'This is a security requirement. Please update external-tools.json with the correct checksum.',
+ 'This is a security requirement. Please update bundle-tools.json with the correct checksum.',
)
}
@@ -477,7 +474,7 @@ export async function downloadExternalTools(platform, arch, isMusl = false) {
if (!wheelSha256) {
throw new Error(
`Missing SHA-256 checksum for socketsecurity wheel: ${wheelFilename}. ` +
- 'Please update external-tools.json with the correct checksum.',
+ 'Please update bundle-tools.json with the correct checksum.',
)
}
@@ -536,14 +533,15 @@ export async function downloadExternalTools(platform, arch, isMusl = false) {
// Install socket_basics from GitHub source (not on PyPI).
// socket_basics orchestrates the security tools (trivy, trufflehog, opengrep).
const socketBasicsConfig = externalTools['socket-basics']
- if (socketBasicsConfig && socketBasicsConfig.type === 'github-source') {
- const { repository, githubRelease } = socketBasicsConfig
- const version = githubRelease.replace(/^v/, '') // Remove 'v' prefix for version
+ if (socketBasicsConfig && socketBasicsConfig.release === 'archive') {
+ const repoPath = socketBasicsConfig.repository.replace(/^github:/, '')
+ const releaseVersion = socketBasicsConfig.version
+ const version = releaseVersion.replace(/^v/, '') // Remove 'v' prefix for version
logger.log(` Installing socket_basics ${version} from GitHub...`)
// Download source tarball from GitHub.
- const tarballUrl = `https://github.com/${repository}/archive/refs/tags/${githubRelease}.tar.gz`
+ const tarballUrl = `https://github.com/${repoPath}/archive/refs/tags/${releaseVersion}.tar.gz`
const tarballPath = normalizePath(
path.join(toolsDir, `socket-basics-${version}.tar.gz`),
)
diff --git a/packages/cli/scripts/sea-build-utils/npm-packages.mjs b/packages/cli/scripts/sea-build-utils/npm-packages.mjs
index 3f53c342f..6f8a58623 100644
--- a/packages/cli/scripts/sea-build-utils/npm-packages.mjs
+++ b/packages/cli/scripts/sea-build-utils/npm-packages.mjs
@@ -20,10 +20,10 @@ import { getRootPath } from './downloads.mjs'
const logger = getDefaultLogger()
/**
- * External tools configuration loaded from external-tools.json.
+ * External tools configuration loaded from bundle-tools.json.
*/
const __dirname = path.dirname(fileURLToPath(import.meta.url))
-const externalToolsPath = path.join(__dirname, '../../external-tools.json')
+const externalToolsPath = path.join(__dirname, '../../bundle-tools.json')
const externalTools = JSON.parse(readFileSync(externalToolsPath, 'utf8'))
/**
@@ -104,7 +104,7 @@ async function downloadNpmPackage(packageSpec, targetDir, expectedIntegrity) {
/**
* Download all npm packages with full dependency trees for VFS bundling.
*
- * Downloads npm packages specified in external-tools.json that have type='npm',
+ * Downloads npm packages specified in bundle-tools.json that have type='npm',
* installs them with full production dependency trees using Arborist, and packages
* them into a compressed tar.gz for VFS embedding.
*
@@ -163,21 +163,21 @@ export async function downloadNpmPackages() {
}
}
- // Collect npm packages from external-tools.json.
+ // Collect npm packages from bundle-tools.json.
const npmPackages = []
for (const [toolName, toolConfig] of Object.entries(externalTools)) {
- if (toolConfig.type === 'npm') {
+ if (toolConfig.packageManager === 'npm') {
npmPackages.push({
integrity: toolConfig.integrity,
name: toolName,
- package: toolConfig.package,
+ package: toolName,
version: toolConfig.version,
})
}
}
if (npmPackages.length === 0) {
- logger.warn('No npm packages defined in external-tools.json')
+ logger.warn('No npm packages defined in bundle-tools.json')
return null
}
diff --git a/packages/cli/scripts/sync-checksums.mjs b/packages/cli/scripts/sync-checksums.mjs
index 3da20816b..cb5e1a1d0 100644
--- a/packages/cli/scripts/sync-checksums.mjs
+++ b/packages/cli/scripts/sync-checksums.mjs
@@ -1,11 +1,11 @@
#!/usr/bin/env node
/**
- * Sync checksums from GitHub releases to external-tools.json.
+ * Sync checksums from GitHub releases to bundle-tools.json.
*
* For each GitHub-released tool, this script:
* 1. Fetches checksums.txt from the release (if available)
* 2. Or downloads each asset and computes SHA-256 checksums
- * 3. Updates external-tools.json with the new checksums
+ * 3. Updates bundle-tools.json with the new checksums
*
* Usage:
* node scripts/sync-checksums.mjs [--tool=] [--force] [--dry-run]
@@ -27,7 +27,7 @@ const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const packageRoot = path.join(__dirname, '..')
-const EXTERNAL_TOOLS_FILE = path.join(packageRoot, 'external-tools.json')
+const EXTERNAL_TOOLS_FILE = path.join(packageRoot, 'bundle-tools.json')
/**
* Compute SHA-256 hash of a file.
@@ -180,7 +180,7 @@ async function main() {
const toolArg = args.find(arg => arg.startsWith('--tool='))
const toolFilter = toolArg ? toolArg.split('=')[1] : undefined
- // Load current external-tools.json.
+ // Load current bundle-tools.json.
if (!existsSync(EXTERNAL_TOOLS_FILE)) {
console.error(`Error: ${EXTERNAL_TOOLS_FILE} not found`)
process.exitCode = 1
@@ -193,7 +193,7 @@ async function main() {
const githubTools = Object.entries(externalTools)
.filter(([key, value]) => {
if (key.startsWith('$')) return false // Skip schema keys
- return value.type === 'github-release'
+ return value.release === 'asset'
})
.map(([key, value]) => ({ key, ...value }))
@@ -216,12 +216,14 @@ async function main() {
let failed = 0
for (const tool of githubTools) {
- console.log(`[${tool.key}] ${tool.repository} @ ${tool.githubRelease}`)
+ const repoPath = tool.repository.replace(/^github:/, '')
+ const releaseTag = tool.tag ?? tool.version
+ console.log(`[${tool.key}] ${repoPath} @ ${releaseTag}`)
try {
const newChecksums = await fetchGitHubReleaseChecksums(
- tool.repository,
- tool.githubRelease,
+ repoPath,
+ releaseTag,
tool.checksums || {},
)
diff --git a/packages/cli/scripts/test-wrapper.mjs b/packages/cli/scripts/test-wrapper.mjs
index 0db2d5a39..fb7b9032f 100644
--- a/packages/cli/scripts/test-wrapper.mjs
+++ b/packages/cli/scripts/test-wrapper.mjs
@@ -6,7 +6,7 @@
* - Cross-platform compatibility (Windows/Unix)
* - Build validation before running tests
* - Environment variable loading from .env.test
- * - Inlined variable injection from external-tools.json
+ * - Inlined variable injection from bundle-tools.json
*/
import { existsSync } from 'node:fs'
diff --git a/packages/cli/src/env/checksum-utils.mts b/packages/cli/src/env/checksum-utils.mts
index 3e8fb2235..536955032 100644
--- a/packages/cli/src/env/checksum-utils.mts
+++ b/packages/cli/src/env/checksum-utils.mts
@@ -63,7 +63,7 @@ export function requireChecksum(
if (!sha256) {
throw new Error(
`Missing SHA-256 checksum for ${toolName} asset: ${assetName}. ` +
- 'This is a security requirement. Please update external-tools.json with the correct checksum.',
+ 'This is a security requirement. Please update bundle-tools.json with the correct checksum.',
)
}
return sha256
diff --git a/packages/cli/src/env/coana-version.mts b/packages/cli/src/env/coana-version.mts
index b5e507708..234305abc 100644
--- a/packages/cli/src/env/coana-version.mts
+++ b/packages/cli/src/env/coana-version.mts
@@ -12,7 +12,7 @@ export function getCoanaVersion(): string {
const version = process.env['INLINED_COANA_VERSION']
if (!version) {
throw new Error(
- 'INLINED_COANA_VERSION not found. Please ensure @coana-tech/cli is properly configured in external-tools.json.',
+ 'INLINED_COANA_VERSION not found. Please ensure @coana-tech/cli is properly configured in bundle-tools.json.',
)
}
return version
diff --git a/packages/cli/src/env/opengrep-version.mts b/packages/cli/src/env/opengrep-version.mts
index 12e766bcb..663fc9956 100644
--- a/packages/cli/src/env/opengrep-version.mts
+++ b/packages/cli/src/env/opengrep-version.mts
@@ -12,7 +12,7 @@ export function getOpengrepVersion(): string {
const version = process.env['INLINED_OPENGREP_VERSION']
if (!version) {
throw new Error(
- 'INLINED_OPENGREP_VERSION not found. Please ensure opengrep is properly configured in external-tools.json.',
+ 'INLINED_OPENGREP_VERSION not found. Please ensure opengrep is properly configured in bundle-tools.json.',
)
}
return version
diff --git a/packages/cli/src/env/pycli-version.mts b/packages/cli/src/env/pycli-version.mts
index 4f45a7c7b..0a595cc12 100644
--- a/packages/cli/src/env/pycli-version.mts
+++ b/packages/cli/src/env/pycli-version.mts
@@ -10,7 +10,7 @@ import process from 'node:process'
/**
* Get the Socket Python CLI version (socketsecurity package) that should be installed.
- * This version is inlined at build time from external-tools.json.
+ * This version is inlined at build time from bundle-tools.json.
*
* @returns Socket Python CLI version string (e.g., "0.8.0").
* @throws Error if version is not inlined at build time.
diff --git a/packages/cli/src/env/sfw-version.mts b/packages/cli/src/env/sfw-version.mts
index af23ecf4c..604a94457 100644
--- a/packages/cli/src/env/sfw-version.mts
+++ b/packages/cli/src/env/sfw-version.mts
@@ -19,7 +19,7 @@ export function getSwfVersion(): string {
const version = process.env['INLINED_SFW_VERSION']
if (!version) {
throw new Error(
- 'INLINED_SFW_VERSION not found. Please ensure sfw is properly configured in external-tools.json.',
+ 'INLINED_SFW_VERSION not found. Please ensure sfw is properly configured in bundle-tools.json.',
)
}
return version
@@ -32,7 +32,7 @@ export function getSfwNpmVersion(): string {
const version = process.env['INLINED_SFW_NPM_VERSION']
if (!version) {
throw new Error(
- 'INLINED_SFW_NPM_VERSION not found. Please ensure sfw npmVersion is configured in external-tools.json.',
+ 'INLINED_SFW_NPM_VERSION not found. Please ensure sfw npm.version is configured in bundle-tools.json.',
)
}
return version
diff --git a/packages/cli/src/env/socket-basics-version.mts b/packages/cli/src/env/socket-basics-version.mts
index 313436b4f..60a207330 100644
--- a/packages/cli/src/env/socket-basics-version.mts
+++ b/packages/cli/src/env/socket-basics-version.mts
@@ -12,7 +12,7 @@ export function getSocketBasicsVersion(): string {
const version = process.env['INLINED_SOCKET_BASICS_VERSION']
if (!version) {
throw new Error(
- 'INLINED_SOCKET_BASICS_VERSION not found. Please ensure socket-basics is properly configured in external-tools.json.',
+ 'INLINED_SOCKET_BASICS_VERSION not found. Please ensure socket-basics is properly configured in bundle-tools.json.',
)
}
return version
diff --git a/packages/cli/src/env/socket-patch-version.mts b/packages/cli/src/env/socket-patch-version.mts
index 24f954f50..673bc03bb 100644
--- a/packages/cli/src/env/socket-patch-version.mts
+++ b/packages/cli/src/env/socket-patch-version.mts
@@ -12,7 +12,7 @@ export function getSocketPatchVersion(): string {
const version = process.env['INLINED_SOCKET_PATCH_VERSION']
if (!version) {
throw new Error(
- 'INLINED_SOCKET_PATCH_VERSION not found. Please ensure socket-patch is properly configured in external-tools.json.',
+ 'INLINED_SOCKET_PATCH_VERSION not found. Please ensure socket-patch is properly configured in bundle-tools.json.',
)
}
return version
diff --git a/packages/cli/src/env/trivy-version.mts b/packages/cli/src/env/trivy-version.mts
index 5f0af42e0..4a2d2452d 100644
--- a/packages/cli/src/env/trivy-version.mts
+++ b/packages/cli/src/env/trivy-version.mts
@@ -12,7 +12,7 @@ export function getTrivyVersion(): string {
const version = process.env['INLINED_TRIVY_VERSION']
if (!version) {
throw new Error(
- 'INLINED_TRIVY_VERSION not found. Please ensure trivy is properly configured in external-tools.json.',
+ 'INLINED_TRIVY_VERSION not found. Please ensure trivy is properly configured in bundle-tools.json.',
)
}
return version
diff --git a/packages/cli/src/env/trufflehog-version.mts b/packages/cli/src/env/trufflehog-version.mts
index 3f16557e5..dec284f7a 100644
--- a/packages/cli/src/env/trufflehog-version.mts
+++ b/packages/cli/src/env/trufflehog-version.mts
@@ -12,7 +12,7 @@ export function getTrufflehogVersion(): string {
const version = process.env['INLINED_TRUFFLEHOG_VERSION']
if (!version) {
throw new Error(
- 'INLINED_TRUFFLEHOG_VERSION not found. Please ensure trufflehog is properly configured in external-tools.json.',
+ 'INLINED_TRUFFLEHOG_VERSION not found. Please ensure trufflehog is properly configured in bundle-tools.json.',
)
}
return version
diff --git a/packages/cli/src/utils/dlx/spawn.mts b/packages/cli/src/utils/dlx/spawn.mts
index e1aee4c1b..7cf7364e9 100644
--- a/packages/cli/src/utils/dlx/spawn.mts
+++ b/packages/cli/src/utils/dlx/spawn.mts
@@ -909,7 +909,7 @@ function getPythonStandaloneInfo(): { assetName: string; url: string } {
throw new InputError(`Unsupported platform: ${platform}`)
}
- // Asset name format matches checksums in external-tools.json.
+ // Asset name format matches checksums in bundle-tools.json.
const assetName = `cpython-${version}+${tag}-${platformTriple}-install_only.tar.gz`
// URL encoding for the '+' in version string.
const encodedVersion = `${version}%2B${tag}`
@@ -1338,7 +1338,7 @@ export async function ensureSocketPyCli(
const pyCliVersion = getPyCliVersion()
// Get checksum for integrity verification.
- // Checksums are keyed by wheel filename in external-tools.json.
+ // Checksums are keyed by wheel filename in bundle-tools.json.
const wheelFilename = `socketsecurity-${pyCliVersion}-py3-none-any.whl`
const checksums = getPyCliChecksums()
const sha256 = checksums[wheelFilename]
diff --git a/packages/cli/test/setup.mts b/packages/cli/test/setup.mts
index fda29ef22..92f9c103f 100644
--- a/packages/cli/test/setup.mts
+++ b/packages/cli/test/setup.mts
@@ -8,17 +8,17 @@ import { fileURLToPath } from 'node:url'
process.env.DEBUG = ''
delete process.env.NODE_DEBUG
-// Load inlined environment variables from external-tools.json.
+// Load inlined environment variables from bundle-tools.json.
// These are normally inlined at build time by esbuild, but tests run from source.
const __dirname = path.dirname(fileURLToPath(import.meta.url))
-const externalToolsPath = path.join(__dirname, '..', 'external-tools.json')
+const externalToolsPath = path.join(__dirname, '..', 'bundle-tools.json')
if (existsSync(externalToolsPath)) {
try {
const externalTools = JSON.parse(readFileSync(externalToolsPath, 'utf8'))
// Set inlined environment variables if not already set.
- // npm packages use 'version', github-release uses 'githubRelease', pypi uses 'version'.
+ // All tools now use 'version' field. GitHub-released tools also have optional 'tag'.
const toolVersions: Record = {
INLINED_CDXGEN_VERSION:
externalTools['@cyclonedx/cdxgen']?.version,
@@ -29,22 +29,22 @@ if (existsSync(externalToolsPath)) {
INLINED_HOMEPAGE: 'https://github.com/SocketDev/socket-cli',
INLINED_NAME: '@socketsecurity/cli',
INLINED_OPENGREP_VERSION:
- externalTools['opengrep']?.githubRelease,
+ externalTools['opengrep']?.version,
INLINED_PUBLISHED_BUILD: '',
INLINED_PYCLI_VERSION:
externalTools['socketsecurity']?.version,
- INLINED_PYTHON_BUILD_TAG: externalTools['python']?.buildTag,
+ INLINED_PYTHON_BUILD_TAG: externalTools['python']?.tag,
INLINED_PYTHON_VERSION:
- externalTools['python']?.githubRelease,
+ externalTools['python']?.version,
INLINED_SENTRY_BUILD: '',
- INLINED_SFW_NPM_VERSION: externalTools['sfw']?.npmVersion,
- INLINED_SFW_VERSION: externalTools['sfw']?.githubRelease,
+ INLINED_SFW_NPM_VERSION: externalTools['sfw']?.npm?.version,
+ INLINED_SFW_VERSION: externalTools['sfw']?.version,
INLINED_SOCKET_PATCH_VERSION:
- externalTools['socket-patch']?.githubRelease,
+ externalTools['socket-patch']?.version,
INLINED_SYNP_VERSION: externalTools['synp']?.version,
- INLINED_TRIVY_VERSION: externalTools['trivy']?.githubRelease,
+ INLINED_TRIVY_VERSION: externalTools['trivy']?.version,
INLINED_TRUFFLEHOG_VERSION:
- externalTools['trufflehog']?.githubRelease,
+ externalTools['trufflehog']?.version,
INLINED_VERSION: '0.0.0-test',
INLINED_VERSION_HASH: '0.0.0-test:abc1234:test',
}
@@ -55,6 +55,6 @@ if (existsSync(externalToolsPath)) {
}
}
} catch {
- // Ignore errors loading external-tools.json.
+ // Ignore errors loading bundle-tools.json.
}
}
diff --git a/scripts/validate-checksums.mjs b/scripts/validate-checksums.mjs
index 67a55c60c..8066ee92b 100644
--- a/scripts/validate-checksums.mjs
+++ b/scripts/validate-checksums.mjs
@@ -3,7 +3,7 @@
/**
* @fileoverview Build-time validation for SHA-256 checksums.
* Ensures all required platform-specific tool assets have checksums defined
- * in external-tools.json before building SEA binaries.
+ * in bundle-tools.json before building SEA binaries.
*
* This script is a security requirement - builds MUST NOT proceed if any
* checksums are missing for downloadable binaries.
@@ -28,7 +28,7 @@ const rootPath = path.join(__dirname, '..')
// Load external tools configuration.
const externalToolsPath = path.join(
rootPath,
- 'packages/cli/external-tools.json',
+ 'packages/cli/bundle-tools.json',
)
const externalTools = JSON.parse(readFileSync(externalToolsPath, 'utf8'))
@@ -64,7 +64,7 @@ function validateChecksums() {
const toolConfig = externalTools[toolName]
if (!toolConfig) {
- errors.push(`Tool "${toolName}" not found in external-tools.json`)
+ errors.push(`Tool "${toolName}" not found in bundle-tools.json`)
continue
}
@@ -128,7 +128,7 @@ function validateChecksums() {
}
console.log('')
logger.error(
- 'All external tool assets MUST have SHA-256 checksums defined in external-tools.json.',
+ 'All external tool assets MUST have SHA-256 checksums defined in bundle-tools.json.',
)
logger.error('This is a security requirement to prevent supply chain attacks.')
return false