herozion 1.1.73 → 1.1.75

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ {
2
+ "_comment": "SHA-256 hashes for each platform binary. Auto-generated in CI from release CHECKSUMS.sha256. DO NOT edit manually.",
3
+ "_version": "1.1.75",
4
+ "herozion-linux-amd64": "42e718f60c1cfd3633a04e30c000bbb5311f15dd7222396b9bb7cba530570654",
5
+ "herozion-macos-amd64": "09a8aec95ac62df1bbe6f1b4f875248ce50ca9bf02ba2664e1f32d842f273ee7",
6
+ "herozion-macos-arm64": "441a7c237e5c7fb09c598dcfc7b4e3403d8d308768a8e2302110f39efeae5dd1",
7
+ "herozion-windows-amd64.exe": "9345261a6d986b327c2f68c9d21d687a0eb6c3622de1340e34149c418afbb4e5"
8
+ }
package/install.js CHANGED
@@ -42,6 +42,13 @@ function getBinaryName() {
42
42
  const { platform, arch } = process;
43
43
 
44
44
  if (platform === "win32" && arch === "x64") return "herozion-windows-amd64.exe";
45
+ if (platform === "linux" && arch === "arm64") {
46
+ throw new Error(
47
+ "Herozion: Linux ARM64 is not supported by the npm binary installer yet.\n" +
48
+ "Use: pip install herozion OR download from:\n" +
49
+ " https://github.com/Herozion/scanner-releases/releases/latest"
50
+ );
51
+ }
45
52
  if (platform === "linux" && (arch === "x64" || arch === "ia32")) return "herozion-linux-amd64";
46
53
  if (platform === "darwin" && arch === "arm64") return "herozion-macos-arm64";
47
54
  if (platform === "darwin" && (arch === "x64" || arch === "ia32")) return "herozion-macos-amd64";
@@ -159,10 +166,22 @@ async function main() {
159
166
  // ── Load bundled checksums (primary trust anchor) ─────────────────────────
160
167
  const bundledChecksumsPath = path.join(__dirname, "bin", "checksums.json");
161
168
  let bundledHash = "";
162
- try {
163
- const bundled = JSON.parse(fs.readFileSync(bundledChecksumsPath, "utf8"));
164
- bundledHash = (bundled[binaryName] || "").toLowerCase().trim();
165
- } catch (_) {}
169
+ if (fs.existsSync(bundledChecksumsPath)) {
170
+ try {
171
+ const bundled = JSON.parse(fs.readFileSync(bundledChecksumsPath, "utf8"));
172
+ bundledHash = (bundled[binaryName] || "").toLowerCase().trim();
173
+ if (!bundledHash) {
174
+ console.warn(`herozion: WARNING — no bundled hash entry for ${binaryName}.`);
175
+ }
176
+ } catch (parseErr) {
177
+ console.warn(`herozion: WARNING — invalid checksums.json: ${parseErr.message}`);
178
+ }
179
+ } else {
180
+ console.warn(
181
+ "herozion: WARNING — bin/checksums.json missing from npm package; " +
182
+ "falling back to remote CHECKSUMS.sha256 verification."
183
+ );
184
+ }
166
185
 
167
186
  console.log(`herozion: downloading ${binaryName} v${VERSION}...`);
168
187
  try {
@@ -170,6 +189,8 @@ async function main() {
170
189
  await download(url, tmpPath);
171
190
 
172
191
  const actualHash = sha256File(tmpPath);
192
+ let bundledVerified = false;
193
+ let remoteVerified = false;
173
194
 
174
195
  // ── Primary check: bundled checksum (trust anchor inside the npm package) ─
175
196
  if (bundledHash) {
@@ -183,6 +204,7 @@ async function main() {
183
204
  "This may indicate a supply-chain attack. Aborting installation."
184
205
  );
185
206
  }
207
+ bundledVerified = true;
186
208
  }
187
209
 
188
210
  // ── Secondary check: CHECKSUMS.sha256 from GitHub Releases ────────────────
@@ -198,56 +220,62 @@ async function main() {
198
220
  }
199
221
  return "";
200
222
  })();
201
- if (remoteHash && actualHash !== remoteHash) {
202
- fs.unlinkSync(tmpPath);
203
- throw new Error(
204
- `Remote checksum mismatch for ${binaryName}.\n` +
205
- ` Expected (remote) : ${remoteHash}\n` +
206
- ` Got : ${actualHash}\n` +
207
- "The downloaded binary does not match the GitHub Releases .sha256 file."
208
- );
223
+ if (remoteHash) {
224
+ if (actualHash !== remoteHash) {
225
+ fs.unlinkSync(tmpPath);
226
+ throw new Error(
227
+ `Remote checksum mismatch for ${binaryName}.\n` +
228
+ ` Expected (remote) : ${remoteHash}\n` +
229
+ ` Got : ${actualHash}\n` +
230
+ "The downloaded binary does not match the GitHub Releases CHECKSUMS.sha256 file."
231
+ );
232
+ }
233
+ remoteVerified = true;
209
234
  }
210
235
  } catch (checksumErr) {
211
- // If we have a valid bundled hash that already passed, remote failure is non-fatal
212
- if (!bundledHash) {
236
+ // If bundled verification already passed, remote failure is non-fatal.
237
+ if (!bundledVerified) {
213
238
  throw checksumErr;
214
239
  }
215
240
  console.warn(`herozion: WARNING — could not verify remote checksum: ${checksumErr.message}`);
216
241
  console.warn("Proceeding because bundled checksum verification passed.");
217
242
  }
218
243
 
219
- // Fail closed: refuse to install if neither hash source could be verified.
220
- if (!bundledHash) {
221
- // We reach here only when bundledHash is empty AND remote check was skipped/failed.
222
- // Secondary catch block re-throws when !bundledHash, so this path is belt-and-suspenders.
244
+ // Fail closed: require at least one independent verification source.
245
+ if (!bundledVerified && !remoteVerified) {
223
246
  fs.unlinkSync(tmpPath);
224
247
  throw new Error(
225
- `Cannot verify ${binaryName}: no bundled hash found and remote checksum unavailable.\n` +
248
+ `Cannot verify ${binaryName}: no bundled hash in package and remote checksum unavailable.\n` +
226
249
  "Installation aborted to prevent supply-chain risk.\n" +
227
250
  `Download manually from: ${BASE_URL}/${binaryName}`
228
251
  );
229
252
  }
230
253
 
231
- // Both checks passed — move binary into place
254
+ // Verification passed — move binary into place
232
255
  fs.renameSync(tmpPath, destPath);
233
256
  if (!isWindows) {
234
257
  fs.chmodSync(destPath, 0o755);
235
258
  }
236
259
  // Write version marker so we don't re-download on repeated installs
237
260
  fs.writeFileSync(markerPath, VERSION, "utf8");
238
- const verifiedBy = bundledHash ? "bundled + remote SHA-256" : "remote SHA-256";
261
+ const verifiedBy = bundledVerified && remoteVerified
262
+ ? "bundled + remote SHA-256"
263
+ : bundledVerified
264
+ ? "bundled SHA-256"
265
+ : "remote SHA-256";
239
266
  console.log(`herozion: binary installed successfully (verified: ${verifiedBy}).`);
240
267
  } catch (err) {
241
268
  // Clean up temp file if it exists
242
269
  try { fs.unlinkSync(tmpPath); } catch (_) {}
243
- // Non-fatal: warn and continue — the bin shim will give a clear error at runtime
244
- console.warn(`herozion: WARNING — could not download binary: ${err.message}`);
245
- console.warn(`You can download it manually from:`);
246
- console.warn(` ${BASE_URL}/${binaryName}`);
270
+ console.error(`herozion: ERROR — could not install binary: ${err.message}`);
271
+ console.error("Try reinstalling with scripts enabled:");
272
+ console.error(" npm install herozion --foreground-scripts");
273
+ console.error(`Or download manually from: ${BASE_URL}/${binaryName}`);
274
+ process.exit(1);
247
275
  }
248
276
  }
249
277
 
250
278
  main().catch((err) => {
251
279
  console.error("herozion install error:", err.message);
252
- // Do not exit(1) — a failed postinstall breaks `npm install` entirely
280
+ process.exit(1);
253
281
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "herozion",
3
- "version": "1.1.73",
3
+ "version": "1.1.75",
4
4
  "description": "Security audit and performance analysis CLI tool for developers",
5
5
  "keywords": [
6
6
  "security",
@@ -23,6 +23,7 @@
23
23
  },
24
24
  "files": [
25
25
  "bin/herozion.js",
26
+ "bin/checksums.json",
26
27
  "install.js",
27
28
  "README.md"
28
29
  ],