From 03f97349b0933960a2877d4321da3b03f32ca87f Mon Sep 17 00:00:00 2001 From: Patrick Erichsen Date: Sun, 14 Jun 2026 18:56:31 -0700 Subject: [PATCH] fix: preserve legacy package ZIP hashes (#2636) * test: fix indexed row helper lint * fix: preserve legacy package zip hashes --- convex/_generated/api.d.ts | 4 + convex/httpApiV1.handlers.test.ts | 5 +- convex/httpApiV1/packagesV1.ts | 10 +- convex/lib/packageArtifacts.test.ts | 32 ++ convex/lib/packageArtifacts.ts | 15 + convex/packageLegacyZipHashBackfill.test.ts | 318 ++++++++++++++++++ convex/packageLegacyZipHashBackfill.ts | 225 +++++++++++++ convex/packages.public.test.ts | 157 +++++++-- convex/packages.ts | 41 ++- convex/publishers.test.ts | 2 +- convex/schema.ts | 1 + convex/securityDataset.ts | 3 +- convex/vt.test.ts | 50 ++- convex/vt.ts | 14 +- docs/http-api.md | 7 +- packages/clawhub/src/schema/packages.ts | 1 + packages/schema/dist/packages.js | 1 + packages/schema/dist/packages.js.map | 2 +- packages/schema/src/packages.ts | 1 + scripts/security-dataset/convexExport.test.ts | 7 +- scripts/security-dataset/convexExport.ts | 9 +- .../plugin-security-audit-route.test.tsx | 18 + src/lib/packageApi.ts | 1 + src/routes/plugins/$name/security-audit.tsx | 2 +- 24 files changed, 843 insertions(+), 83 deletions(-) create mode 100644 convex/lib/packageArtifacts.test.ts create mode 100644 convex/lib/packageArtifacts.ts create mode 100644 convex/packageLegacyZipHashBackfill.test.ts create mode 100644 convex/packageLegacyZipHashBackfill.ts diff --git a/convex/_generated/api.d.ts b/convex/_generated/api.d.ts index 261e964a..58bb8363 100644 --- a/convex/_generated/api.d.ts +++ b/convex/_generated/api.d.ts @@ -76,6 +76,7 @@ import type * as lib_moderationReasonCodes from "../lib/moderationReasonCodes.js import type * as lib_observabilityEvents from "../lib/observabilityEvents.js"; import type * as lib_officialPublishers from "../lib/officialPublishers.js"; import type * as lib_openaiResponse from "../lib/openaiResponse.js"; +import type * as lib_packageArtifacts from "../lib/packageArtifacts.js"; import type * as lib_packageRegistry from "../lib/packageRegistry.js"; import type * as lib_packageSearchDigest from "../lib/packageSearchDigest.js"; import type * as lib_packageSecurity from "../lib/packageSecurity.js"; @@ -118,6 +119,7 @@ import type * as maintenance from "../maintenance.js"; import type * as managementDevSeed from "../managementDevSeed.js"; import type * as packageInspectorHttp from "../packageInspectorHttp.js"; import type * as packageInspectorNode from "../packageInspectorNode.js"; +import type * as packageLegacyZipHashBackfill from "../packageLegacyZipHashBackfill.js"; import type * as packagePublishTokens from "../packagePublishTokens.js"; import type * as packages from "../packages.js"; import type * as publisherAbuse from "../publisherAbuse.js"; @@ -220,6 +222,7 @@ declare const fullApi: ApiFromModules<{ "lib/observabilityEvents": typeof lib_observabilityEvents; "lib/officialPublishers": typeof lib_officialPublishers; "lib/openaiResponse": typeof lib_openaiResponse; + "lib/packageArtifacts": typeof lib_packageArtifacts; "lib/packageRegistry": typeof lib_packageRegistry; "lib/packageSearchDigest": typeof lib_packageSearchDigest; "lib/packageSecurity": typeof lib_packageSecurity; @@ -262,6 +265,7 @@ declare const fullApi: ApiFromModules<{ managementDevSeed: typeof managementDevSeed; packageInspectorHttp: typeof packageInspectorHttp; packageInspectorNode: typeof packageInspectorNode; + packageLegacyZipHashBackfill: typeof packageLegacyZipHashBackfill; packagePublishTokens: typeof packagePublishTokens; packages: typeof packages; publisherAbuse: typeof publisherAbuse; diff --git a/convex/httpApiV1.handlers.test.ts b/convex/httpApiV1.handlers.test.ts index 17032457..a612961c 100644 --- a/convex/httpApiV1.handlers.test.ts +++ b/convex/httpApiV1.handlers.test.ts @@ -9081,7 +9081,7 @@ describe("httpApiV1 handlers", () => { }); }); - it("package security endpoint returns exact release trust and blocked reasons", async () => { + it("package security endpoint uses the canonical npm artifact hash", async () => { const runQuery = vi.fn(async (_query: unknown, args: Record) => { if ("name" in args && !("version" in args)) { return { @@ -9161,7 +9161,7 @@ describe("httpApiV1 handlers", () => { releaseId: "packageReleases:1", version: "1.0.0", artifactKind: "npm-pack", - artifactSha256: "c".repeat(64), + artifactSha256: "e".repeat(64), npmIntegrity: "sha512-demo", npmShasum: "d".repeat(40), npmTarballName: "demo-plugin-1.0.0.tgz", @@ -9248,6 +9248,7 @@ describe("httpApiV1 handlers", () => { files: [], artifactKind: "npm-pack", integritySha256: "a".repeat(64), + sha256hash: "b".repeat(64), npmIntegrity: "sha512-demo", npmShasum: "d".repeat(40), npmTarballName: "demo-plugin-1.0.0.tgz", diff --git a/convex/httpApiV1/packagesV1.ts b/convex/httpApiV1/packagesV1.ts index fe5136d6..15313338 100644 --- a/convex/httpApiV1/packagesV1.ts +++ b/convex/httpApiV1/packagesV1.ts @@ -36,6 +36,7 @@ import { } from "../lib/githubActionsOidc"; import { corsHeaders, mergeHeaders } from "../lib/httpHeaders"; import { applyRateLimit } from "../lib/httpRateLimit"; +import { getPackageReleaseArtifactSha256 } from "../lib/packageArtifacts"; import { tryNormalizePackageName } from "../lib/packageRegistry"; import { getPackageDownloadSecurityBlock, @@ -612,19 +613,12 @@ function toReleaseArtifact(release: ReleaseLike, packageName?: string) { }; } -function packageReleaseArtifactSha256(release: ReleaseLike) { - if (release.artifactKind === "npm-pack") { - return release.sha256hash ?? release.clawpackSha256 ?? null; - } - return release.sha256hash ?? null; -} - function toPackageReleaseSecurityResponse(params: { pkg: PublicPackageDocLike; release: ReleaseLike; }) { const scanStatus = resolvePackageReleaseScanStatus(params.release); - const artifactSha256 = packageReleaseArtifactSha256(params.release); + const artifactSha256 = getPackageReleaseArtifactSha256(params.release); const packageBlockedFromDownload = params.pkg.publicDownloadBlocked === true; const reasons = getPackageTrustReasons(params.release, scanStatus); if (packageBlockedFromDownload) reasons.push("package:malicious"); diff --git a/convex/lib/packageArtifacts.test.ts b/convex/lib/packageArtifacts.test.ts new file mode 100644 index 00000000..e0704b24 --- /dev/null +++ b/convex/lib/packageArtifacts.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from "vitest"; +import { getPackageReleaseArtifactSha256 } from "./packageArtifacts"; + +describe("getPackageReleaseArtifactSha256", () => { + it("uses the exact npm-pack artifact hash instead of the legacy ZIP hash", () => { + expect( + getPackageReleaseArtifactSha256({ + artifactKind: "npm-pack", + clawpackSha256: "tgz-sha", + sha256hash: "legacy-zip-sha", + }), + ).toBe("tgz-sha"); + }); + + it("does not fall back to the legacy ZIP hash for npm-pack releases", () => { + expect( + getPackageReleaseArtifactSha256({ + artifactKind: "npm-pack", + sha256hash: "legacy-zip-sha", + }), + ).toBeNull(); + }); + + it("uses the ZIP hash for legacy releases", () => { + expect( + getPackageReleaseArtifactSha256({ + artifactKind: "legacy-zip", + sha256hash: "legacy-zip-sha", + }), + ).toBe("legacy-zip-sha"); + }); +}); diff --git a/convex/lib/packageArtifacts.ts b/convex/lib/packageArtifacts.ts new file mode 100644 index 00000000..aa7e89df --- /dev/null +++ b/convex/lib/packageArtifacts.ts @@ -0,0 +1,15 @@ +import type { Doc } from "../_generated/dataModel"; + +type PackageReleaseArtifactHashFields = Pick< + Doc<"packageReleases">, + "artifactKind" | "clawpackSha256" | "sha256hash" +>; + +export function getPackageReleaseArtifactSha256( + release: PackageReleaseArtifactHashFields, +): string | null { + if (release.artifactKind === "npm-pack") { + return release.clawpackSha256 ?? null; + } + return release.sha256hash ?? null; +} diff --git a/convex/packageLegacyZipHashBackfill.test.ts b/convex/packageLegacyZipHashBackfill.test.ts new file mode 100644 index 00000000..e21e7ea1 --- /dev/null +++ b/convex/packageLegacyZipHashBackfill.test.ts @@ -0,0 +1,318 @@ +/* @vitest-environment node */ + +import { describe, expect, it, vi } from "vitest"; +import { sha256Hex } from "./lib/clawpack"; +import { buildDeterministicPackageZip } from "./lib/skillZip"; +import { + applyLegacyPackageZipHashBackfillInternal, + backfillLegacyPackageZipHashesInternal, + getLegacyPackageZipHashBackfillBatchInternal, +} from "./packageLegacyZipHashBackfill"; + +type WrappedHandler = { + _handler: (ctx: unknown, args: TArgs) => Promise; +}; + +type BackfillResult = { + dryRun: boolean; + done: boolean; + cursor: string | null; + scanned: number; + candidates: number; + matched: number; + wouldPatch: number; + patched: number; + skipped: number; + errors: number; + samples: Array<{ + releaseId: string; + packageName: string; + version: string; + currentSha256hash: string | null; + expectedSha256hash?: string; + action: string; + }>; +}; + +const backfillHandler = ( + backfillLegacyPackageZipHashesInternal as unknown as WrappedHandler< + { + dryRun: boolean; + batchSize?: number; + cursor?: string | null; + confirmationToken?: string; + }, + BackfillResult + > +)._handler; + +const applyHandler = ( + applyLegacyPackageZipHashBackfillInternal as unknown as WrappedHandler< + { + releaseId: string; + expectedCurrentSha256hash?: string; + sha256hash: string; + confirmationToken: string; + }, + { status: "patched" | "matched" | "stale" | "skipped" } + > +)._handler; + +const getBatchHandler = ( + getLegacyPackageZipHashBackfillBatchInternal as unknown as WrappedHandler< + { batchSize?: number; cursor?: string | null }, + { + page: Array<{ + releaseId: string; + packageName: string; + version: string; + currentSha256hash: string | null; + }>; + scanned: number; + continueCursor: string; + isDone: boolean; + } + > +)._handler; + +const packageJson = '{"name":"demo-plugin"}'; +const pluginManifest = '{"id":"demo.plugin"}'; + +function batch(currentSha256hash = "old-tgz-hash") { + return { + page: [ + { + releaseId: "packageReleases:demo", + packageName: "demo-plugin", + version: "1.0.0", + currentSha256hash, + files: [ + { path: "package.json", storageId: "storage:package" }, + { path: "openclaw.plugin.json", storageId: "storage:manifest" }, + ], + }, + ], + scanned: 1, + continueCursor: "next-page", + isDone: false, + }; +} + +function storage() { + return { + get: vi.fn(async (storageId: string) => { + if (storageId === "storage:package") return new Blob([packageJson]); + if (storageId === "storage:manifest") return new Blob([pluginManifest]); + return null; + }), + }; +} + +async function expectedLegacyZipSha256() { + return await sha256Hex( + buildDeterministicPackageZip([ + { path: "package.json", bytes: new TextEncoder().encode(packageJson) }, + { path: "openclaw.plugin.json", bytes: new TextEncoder().encode(pluginManifest) }, + ]), + ); +} + +describe("legacy package ZIP hash backfill", () => { + it("reads a bounded resumable page and selects only npm-pack releases", async () => { + const paginate = vi.fn().mockResolvedValue({ + page: [ + { + _id: "packageReleases:npm", + packageId: "packages:npm", + version: "1.0.0", + artifactKind: "npm-pack", + files: [], + sha256hash: "old-tgz-hash", + }, + { + _id: "packageReleases:soft-deleted-npm", + packageId: "packages:soft-deleted-npm", + version: "2.0.0", + artifactKind: "npm-pack", + files: [], + sha256hash: "old-soft-deleted-tgz-hash", + softDeletedAt: 123, + }, + { + _id: "packageReleases:legacy", + packageId: "packages:legacy", + version: "1.0.0", + artifactKind: "legacy-zip", + files: [], + }, + ], + continueCursor: "next-page", + isDone: false, + }); + const order = vi.fn(() => ({ paginate })); + + const result = await getBatchHandler( + { + db: { + query: vi.fn(() => ({ order })), + get: vi.fn().mockResolvedValue({ name: "demo-plugin" }), + }, + }, + { batchSize: 999, cursor: "current-page" }, + ); + + expect(order).toHaveBeenCalledWith("asc"); + expect(paginate).toHaveBeenCalledWith({ cursor: "current-page", numItems: 10 }); + expect(result).toMatchObject({ + scanned: 3, + continueCursor: "next-page", + isDone: false, + page: [ + { + releaseId: "packageReleases:npm", + packageName: "demo-plugin", + currentSha256hash: "old-tgz-hash", + }, + { + releaseId: "packageReleases:soft-deleted-npm", + packageName: "demo-plugin", + currentSha256hash: "old-soft-deleted-tgz-hash", + }, + ], + }); + }); + + it("dry-runs a resumable batch without writing", async () => { + const runMutation = vi.fn(); + const result = await backfillHandler( + { + runQuery: vi.fn().mockResolvedValue(batch()), + runMutation, + storage: storage(), + }, + { dryRun: true, batchSize: 1 }, + ); + + expect(result).toMatchObject({ + dryRun: true, + done: false, + cursor: "next-page", + scanned: 1, + candidates: 1, + matched: 0, + wouldPatch: 1, + patched: 0, + errors: 0, + }); + expect(result.samples).toContainEqual( + expect.objectContaining({ + releaseId: "packageReleases:demo", + currentSha256hash: "old-tgz-hash", + expectedSha256hash: await expectedLegacyZipSha256(), + action: "would-patch", + }), + ); + expect(runMutation).not.toHaveBeenCalled(); + }); + + it("requires an explicit confirmation token before apply", async () => { + const ctx = { + runQuery: vi.fn(), + runMutation: vi.fn(), + storage: storage(), + }; + + await expect(backfillHandler(ctx, { dryRun: false })).rejects.toThrow("confirmationToken"); + expect(ctx.runQuery).not.toHaveBeenCalled(); + expect(ctx.runMutation).not.toHaveBeenCalled(); + }); + + it("applies a mismatched hash through the guarded mutation", async () => { + const expectedSha256hash = await expectedLegacyZipSha256(); + const runMutation = vi.fn().mockResolvedValue({ status: "patched" }); + const result = await backfillHandler( + { + runQuery: vi.fn().mockResolvedValue(batch()), + runMutation, + storage: storage(), + }, + { + dryRun: false, + batchSize: 1, + confirmationToken: "BACKFILL_LEGACY_PACKAGE_ZIP_HASHES", + }, + ); + + expect(runMutation).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ + releaseId: "packageReleases:demo", + expectedCurrentSha256hash: "old-tgz-hash", + sha256hash: expectedSha256hash, + confirmationToken: "BACKFILL_LEGACY_PACKAGE_ZIP_HASHES", + }), + ); + expect(result).toMatchObject({ + dryRun: false, + wouldPatch: 0, + patched: 1, + errors: 0, + }); + }); + + it("does not overwrite a release that changed after the batch read", async () => { + const patch = vi.fn(); + const result = await applyHandler( + { + db: { + get: vi.fn().mockResolvedValue({ + _id: "packageReleases:demo", + artifactKind: "npm-pack", + sha256hash: "newer-value", + }), + query: vi.fn(), + normalizeId: vi.fn(() => null), + patch, + }, + }, + { + releaseId: "packageReleases:demo", + expectedCurrentSha256hash: "old-tgz-hash", + sha256hash: await expectedLegacyZipSha256(), + confirmationToken: "BACKFILL_LEGACY_PACKAGE_ZIP_HASHES", + }, + ); + + expect(result).toEqual({ status: "stale" }); + expect(patch).not.toHaveBeenCalled(); + }); + + it("patches soft-deleted npm-pack releases so restored downloads stay compatible", async () => { + const patch = vi.fn(); + const sha256hash = await expectedLegacyZipSha256(); + const result = await applyHandler( + { + db: { + get: vi.fn().mockResolvedValue({ + _id: "packageReleases:demo", + artifactKind: "npm-pack", + sha256hash: "old-tgz-hash", + softDeletedAt: 123, + }), + query: vi.fn(), + normalizeId: vi.fn(() => null), + patch, + }, + }, + { + releaseId: "packageReleases:demo", + expectedCurrentSha256hash: "old-tgz-hash", + sha256hash, + confirmationToken: "BACKFILL_LEGACY_PACKAGE_ZIP_HASHES", + }, + ); + + expect(result).toEqual({ status: "patched" }); + expect(patch).toHaveBeenCalledWith("packageReleases:demo", { sha256hash }); + }); +}); diff --git a/convex/packageLegacyZipHashBackfill.ts b/convex/packageLegacyZipHashBackfill.ts new file mode 100644 index 00000000..de5585df --- /dev/null +++ b/convex/packageLegacyZipHashBackfill.ts @@ -0,0 +1,225 @@ +import { v } from "convex/values"; +import { internal } from "./_generated/api"; +import type { Id } from "./_generated/dataModel"; +import { internalAction, internalMutation, internalQuery } from "./functions"; +import { sha256Hex } from "./lib/clawpack"; +import { buildDeterministicPackageZip } from "./lib/skillZip"; + +// Temporary migration exception: computing the compatibility hash requires storage reads and +// deterministic ZIP construction in an action, which @convex-dev/migrations mutations cannot do. +const APPLY_CONFIRMATION_TOKEN = "BACKFILL_LEGACY_PACKAGE_ZIP_HASHES"; +const DEFAULT_BATCH_SIZE = 5; +const MAX_BATCH_SIZE = 10; +const MAX_SAMPLES = 25; + +const internalRefs = internal as unknown as { + packageLegacyZipHashBackfill: { + getLegacyPackageZipHashBackfillBatchInternal: unknown; + applyLegacyPackageZipHashBackfillInternal: unknown; + }; +}; + +type BackfillTarget = { + releaseId: Id<"packageReleases">; + packageName: string; + version: string; + currentSha256hash: string | null; + files: Array<{ path: string; storageId: Id<"_storage"> }>; +}; + +type BackfillBatch = { + page: BackfillTarget[]; + scanned: number; + continueCursor: string; + isDone: boolean; +}; + +function effectiveBatchSize(batchSize?: number) { + return Math.max(1, Math.min(Math.floor(batchSize ?? DEFAULT_BATCH_SIZE), MAX_BATCH_SIZE)); +} + +export const getLegacyPackageZipHashBackfillBatchInternal = internalQuery({ + args: { + batchSize: v.optional(v.number()), + cursor: v.optional(v.union(v.string(), v.null())), + }, + handler: async (ctx, args): Promise => { + const page = await ctx.db + .query("packageReleases") + .order("asc") + .paginate({ + cursor: args.cursor ?? null, + numItems: effectiveBatchSize(args.batchSize), + }); + + const targets: BackfillTarget[] = []; + for (const release of page.page) { + if (release.artifactKind !== "npm-pack") continue; + const pkg = await ctx.db.get(release.packageId); + targets.push({ + releaseId: release._id, + packageName: pkg?.name ?? ``, + version: release.version, + currentSha256hash: release.sha256hash ?? null, + files: release.files.map((file) => ({ + path: file.path, + storageId: file.storageId, + })), + }); + } + + return { + page: targets, + scanned: page.page.length, + continueCursor: page.continueCursor, + isDone: page.isDone, + }; + }, +}); + +export const applyLegacyPackageZipHashBackfillInternal = internalMutation({ + args: { + releaseId: v.id("packageReleases"), + expectedCurrentSha256hash: v.optional(v.string()), + sha256hash: v.string(), + confirmationToken: v.string(), + }, + handler: async (ctx, args) => { + if (args.confirmationToken !== APPLY_CONFIRMATION_TOKEN) { + throw new Error(`Apply requires confirmationToken=${APPLY_CONFIRMATION_TOKEN}`); + } + + const release = await ctx.db.get(args.releaseId); + if (!release || release.artifactKind !== "npm-pack") { + return { status: "skipped" as const }; + } + if (release.sha256hash === args.sha256hash) { + return { status: "matched" as const }; + } + if ((release.sha256hash ?? null) !== (args.expectedCurrentSha256hash ?? null)) { + return { status: "stale" as const }; + } + + await ctx.db.patch(args.releaseId, { sha256hash: args.sha256hash }); + return { status: "patched" as const }; + }, +}); + +export const backfillLegacyPackageZipHashesInternal = internalAction({ + args: { + dryRun: v.boolean(), + batchSize: v.optional(v.number()), + cursor: v.optional(v.union(v.string(), v.null())), + confirmationToken: v.optional(v.string()), + }, + handler: async (ctx, args) => { + if (!args.dryRun && args.confirmationToken !== APPLY_CONFIRMATION_TOKEN) { + throw new Error(`Apply requires confirmationToken=${APPLY_CONFIRMATION_TOKEN}`); + } + + const batch = (await ctx.runQuery( + internalRefs.packageLegacyZipHashBackfill + .getLegacyPackageZipHashBackfillBatchInternal as never, + { + batchSize: effectiveBatchSize(args.batchSize), + cursor: args.cursor ?? null, + } as never, + )) as BackfillBatch; + const result = { + dryRun: args.dryRun, + done: batch.isDone, + cursor: batch.isDone ? null : batch.continueCursor, + scanned: batch.scanned, + candidates: batch.page.length, + matched: 0, + wouldPatch: 0, + patched: 0, + skipped: 0, + errors: 0, + samples: [] as Array<{ + releaseId: string; + packageName: string; + version: string; + currentSha256hash: string | null; + expectedSha256hash?: string; + action: "matched" | "would-patch" | "patched" | "stale" | "skipped" | "error"; + message?: string; + }>, + }; + + for (const target of batch.page) { + const sampleBase = { + releaseId: target.releaseId, + packageName: target.packageName, + version: target.version, + currentSha256hash: target.currentSha256hash, + }; + const entries: Array<{ path: string; bytes: Uint8Array }> = []; + const missingPaths: string[] = []; + for (const file of target.files) { + const blob = await ctx.storage.get(file.storageId); + if (!blob) { + missingPaths.push(file.path); + continue; + } + entries.push({ + path: file.path, + bytes: new Uint8Array(await blob.arrayBuffer()), + }); + } + if (target.files.length === 0 || missingPaths.length > 0) { + result.errors += 1; + if (result.samples.length < MAX_SAMPLES) { + result.samples.push({ + ...sampleBase, + action: "error", + message: + target.files.length === 0 + ? "Release has no stored files" + : `Missing stored files: ${missingPaths.join(", ")}`, + }); + } + continue; + } + + const expectedSha256hash = await sha256Hex(buildDeterministicPackageZip(entries)); + if (target.currentSha256hash === expectedSha256hash) { + result.matched += 1; + if (result.samples.length < MAX_SAMPLES) { + result.samples.push({ ...sampleBase, expectedSha256hash, action: "matched" }); + } + continue; + } + if (args.dryRun) { + result.wouldPatch += 1; + if (result.samples.length < MAX_SAMPLES) { + result.samples.push({ ...sampleBase, expectedSha256hash, action: "would-patch" }); + } + continue; + } + + const mutationResult = (await ctx.runMutation( + internalRefs.packageLegacyZipHashBackfill + .applyLegacyPackageZipHashBackfillInternal as never, + { + releaseId: target.releaseId, + ...(target.currentSha256hash + ? { expectedCurrentSha256hash: target.currentSha256hash } + : {}), + sha256hash: expectedSha256hash, + confirmationToken: APPLY_CONFIRMATION_TOKEN, + } as never, + )) as { status: "patched" | "matched" | "stale" | "skipped" }; + result[mutationResult.status === "stale" ? "skipped" : mutationResult.status] += 1; + if (result.samples.length < MAX_SAMPLES) { + result.samples.push({ + ...sampleBase, + expectedSha256hash, + action: mutationResult.status, + }); + } + } + + return result; + }, +}); diff --git a/convex/packages.public.test.ts b/convex/packages.public.test.ts index 36705287..ead70ecd 100644 --- a/convex/packages.public.test.ts +++ b/convex/packages.public.test.ts @@ -2,11 +2,13 @@ import { getAuthUserId } from "@convex-dev/auth/server"; import { afterEach, describe, expect, it, vi } from "vitest"; +import { sha256Hex } from "./lib/clawpack"; import { MAX_PUBLISH_FILE_BYTES } from "./lib/publishLimits"; import { computeRecommendationScore, RECOMMENDATION_SCORE_VERSION, } from "./lib/recommendationScore"; +import { buildDeterministicPackageZip } from "./lib/skillZip"; import { backfillLatestPackageScanStatusInternal, backfillPackageReleaseScansInternal, @@ -217,6 +219,7 @@ const insertReleaseInternalHandler = ( contentType?: string; }>; integritySha256: string; + sha256hash?: string; sourceRepo?: string; runtimeId?: string; channel?: "official" | "community" | "private"; @@ -5623,6 +5626,7 @@ describe("packages public queries", () => { summary: "demo", files: [], integritySha256: "abc123", + sha256hash: "legacy-zip-sha", artifactKind: "npm-pack", clawpackStorageId: "storage:clawpack", clawpackSha256: "a".repeat(64), @@ -5651,6 +5655,7 @@ describe("packages public queries", () => { capabilities: expect.objectContaining({ capabilityTags: expectedTags }), artifact: expect.objectContaining({ kind: "npm-pack", + sha256: "a".repeat(64), npmIntegrity: "sha512-demo", npmShasum: "b".repeat(40), }), @@ -5659,6 +5664,45 @@ describe("packages public queries", () => { ); }); + it("uses the exact legacy ZIP hash in promoted legacy artifact summaries", async () => { + const ctx = makeInsertReleaseCtx( + makePackageDoc({ + tags: { latest: "packageReleases:demo-1" }, + latestReleaseId: "packageReleases:demo-1", + stats: { downloads: 0, installs: 0, stars: 0, versions: 1 }, + }), + ); + + await insertReleaseInternalHandler(ctx, { + actorUserId: "users:owner", + ownerUserId: "users:owner", + name: "demo-plugin", + displayName: "Demo Plugin", + family: "code-plugin", + version: "1.1.0", + changelog: "legacy zip", + tags: ["latest"], + summary: "demo", + files: [], + integritySha256: "file-set-sha", + sha256hash: "legacy-zip-sha", + artifactKind: "legacy-zip", + }); + + expect(ctx.patch).toHaveBeenCalledWith( + "packages:demo", + expect.objectContaining({ + latestVersionSummary: expect.objectContaining({ + artifact: { + kind: "legacy-zip", + sha256: "legacy-zip-sha", + format: "zip", + }, + }), + }), + ); + }); + it("keeps package summary pinned to the promoted release for non-latest publishes", async () => { const ctx = makeInsertReleaseCtx( makePackageDoc({ @@ -6481,6 +6525,33 @@ describe("packages public queries", () => { it("scans plugin publishes and forwards scan status to insertReleaseInternal", async () => { const runMutation = vi.fn(async (_ref: unknown, args: unknown) => args); + const storedFiles = new Map([ + [ + "storage:package", + JSON.stringify({ + name: "demo-plugin", + openclaw: { + extensions: ["./dist/index.js"], + hostTargets: ["darwin-arm64", "linux-x64"], + environment: {}, + compat: { pluginApi: "^1.0.0" }, + build: { openclawVersion: "2026.3.14" }, + configSchema: { type: "object" }, + }, + }), + ], + [ + "storage:manifest", + JSON.stringify({ + id: "demo.plugin", + tools: [{ name: "demoTool" }], + }), + ], + [ + "storage:code", + "import { execSync } from 'node:child_process';\nexecSync('curl http://x');\n", + ], + ]); const ctx = { runQuery: vi .fn() @@ -6500,34 +6571,7 @@ describe("packages public queries", () => { }, storage: { get: vi.fn(async (storageId: string) => { - const files = new Map([ - [ - "storage:package", - JSON.stringify({ - name: "demo-plugin", - openclaw: { - extensions: ["./dist/index.js"], - hostTargets: ["darwin-arm64", "linux-x64"], - environment: {}, - compat: { pluginApi: "^1.0.0" }, - build: { openclawVersion: "2026.3.14" }, - configSchema: { type: "object" }, - }, - }), - ], - [ - "storage:manifest", - JSON.stringify({ - id: "demo.plugin", - tools: [{ name: "demoTool" }], - }), - ], - [ - "storage:code", - "import { execSync } from 'node:child_process';\nexecSync('curl http://x');\n", - ], - ]); - const content = files.get(storageId); + const content = storedFiles.get(storageId); return content ? new Blob([content]) : null; }), }, @@ -6585,8 +6629,25 @@ describe("packages public queries", () => { ], }, })) as Record; + const expectedLegacyZipSha256 = await sha256Hex( + buildDeterministicPackageZip([ + { + path: "package.json", + bytes: new TextEncoder().encode(storedFiles.get("storage:package")), + }, + { + path: "openclaw.plugin.json", + bytes: new TextEncoder().encode(storedFiles.get("storage:manifest")), + }, + { + path: "dist/index.js", + bytes: new TextEncoder().encode(storedFiles.get("storage:code")), + }, + ]), + ); expect(runMutation).toHaveBeenCalled(); + expect(result.sha256hash).toBe(expectedLegacyZipSha256); expect(result.verification).toEqual(expect.objectContaining({ scanStatus: "pending" })); expect(result.staticScan).toEqual( expect.objectContaining({ @@ -10171,6 +10232,46 @@ describe("package scan backfill", () => { ]); }); + it("does not repeatedly rescan a release solely because its artifact hash is missing", async () => { + const result = await getPackageReleaseScanBackfillBatchInternalHandler( + { + db: { + query: vi.fn((table: string) => { + if (table !== "packageReleases") throw new Error(`Unexpected table ${table}`); + return { + order: vi.fn(() => ({ + take: vi.fn().mockResolvedValue([]), + })), + withIndex: vi.fn(() => ({ + order: vi.fn(() => ({ + take: vi.fn().mockResolvedValue([ + { + _id: "packageReleases:npm-missing-artifact-hash", + _creationTime: 10, + packageId: "packages:demo", + artifactKind: "npm-pack", + sha256hash: "legacy-zip-hash", + vtAnalysis: { status: "clean" }, + llmAnalysis: { status: "clean" }, + staticScan: { status: "clean" }, + }, + ]), + })), + })), + }; + }), + get: vi.fn(async (id: string) => { + if (id === "packages:demo") return makePackageDoc(); + return null; + }), + }, + } as never, + { batchSize: 10 }, + ); + + expect(result.releases).toEqual([]); + }); + it("prioritizes recent releases before draining older backlog", async () => { const result = await getPackageReleaseScanBackfillBatchInternalHandler( { diff --git a/convex/packages.ts b/convex/packages.ts index 5a2105fb..b9be2833 100644 --- a/convex/packages.ts +++ b/convex/packages.ts @@ -51,6 +51,7 @@ import { requireGitHubAccountAge } from "./lib/githubAccount"; import { normalizeGitHubRepository } from "./lib/githubActionsOidc"; import { readGlobalPublicPluginsCount } from "./lib/globalStats"; import { isOfficialPublisher } from "./lib/officialPublishers"; +import { getPackageReleaseArtifactSha256 } from "./lib/packageArtifacts"; import { assertPackageVersion, ensurePluginNameMatchesPackage, @@ -95,6 +96,7 @@ import { import { MAX_ACTIVE_REPORTS_PER_USER, MAX_REPORT_REASON_LENGTH } from "./lib/reporting"; import { matchesAllTokens, matchesExploratoryTokenPrefixes, tokenize } from "./lib/searchText"; import { hashSkillFiles } from "./lib/skills"; +import { buildDeterministicPackageZip } from "./lib/skillZip"; import { runStaticPublishScan } from "./lib/staticPublishScan"; import schema from "./schema"; @@ -1056,8 +1058,8 @@ function packageArtifactSummary( release: Pick< Doc<"packageReleases">, | "artifactKind" - | "integritySha256" | "clawpackSha256" + | "sha256hash" | "clawpackSize" | "clawpackFormat" | "npmIntegrity" @@ -1070,7 +1072,7 @@ function packageArtifactSummary( if (release.artifactKind === "npm-pack") { return { kind: "npm-pack", - sha256: release.clawpackSha256, + sha256: getPackageReleaseArtifactSha256(release) ?? undefined, size: release.clawpackSize, format: release.clawpackFormat ?? "tgz", npmIntegrity: release.npmIntegrity, @@ -1082,7 +1084,7 @@ function packageArtifactSummary( } return { kind: "legacy-zip", - sha256: release.integritySha256, + sha256: getPackageReleaseArtifactSha256(release) ?? undefined, format: "zip", }; } @@ -5964,7 +5966,7 @@ export const getPackageReleaseScanBackfillBatchInternal = internalQuery({ const pkg = await ctx.db.get(release.packageId); if (!pkg || pkg.softDeletedAt || pkg.family === "skill") continue; - const needsVt = !release.sha256hash || !release.vtAnalysis; + const needsVt = !release.vtAnalysis; const needsLlm = !release.llmAnalysis || release.llmAnalysis.status === "error"; const needsStatic = !release.staticScan; if (!needsVt && !needsLlm && !needsStatic) continue; @@ -6103,19 +6105,26 @@ async function verifyPublishFileStorageMetadata( ctx: Pick, files: ReturnType, ) { - return await Promise.all( + const verified = await Promise.all( files.map(async (file) => { const blob = await ctx.storage.get(file.storageId as Id<"_storage">); if (!blob) throw new ConvexError(`Uploaded file no longer exists: ${file.path}`); const bytes = new Uint8Array(await blob.arrayBuffer()); return { - ...file, - size: blob.size, - sha256: await sha256Hex(bytes), - contentType: file.contentType?.trim() || blob.type || undefined, + file: { + ...file, + size: blob.size, + sha256: await sha256Hex(bytes), + contentType: file.contentType?.trim() || blob.type || undefined, + }, + zipEntry: { path: file.path, bytes }, }; }), ); + return { + files: verified.map(({ file }) => file), + legacyZipEntries: verified.map(({ zipEntry }) => zipEntry), + }; } async function publishPackageImpl( @@ -6247,7 +6256,10 @@ async function publishPackageImpl( } const displayName = payload.displayName?.trim() || name; - const files = await verifyPublishFileStorageMetadata(ctx, normalizePublishFiles(payload.files)); + const { files, legacyZipEntries } = await verifyPublishFileStorageMetadata( + ctx, + normalizePublishFiles(payload.files), + ); if (payload.artifact?.kind !== "npm-pack") { const oversizedFile = findOversizedPublishFile(files); if (oversizedFile) { @@ -6258,6 +6270,7 @@ async function publishPackageImpl( if (totalBytes > MAX_PUBLISH_TOTAL_BYTES) { throw new ConvexError(getPublishTotalSizeError("package")); } + const legacyZipSha256 = await sha256Hex(buildDeterministicPackageZip(legacyZipEntries)); const existingSkill = await runQueryRef(ctx, internalRefs.skills.getSkillBySlugInternal, { slug: name, @@ -6434,6 +6447,7 @@ async function publishPackageImpl( staticScan, files, integritySha256, + sha256hash: legacyZipSha256, artifactKind: payload.artifact?.kind ?? "legacy-zip", clawpackStorageId: payload.artifact?.storageId as Id<"_storage"> | undefined, clawpackSha256: payload.artifact?.sha256, @@ -7606,6 +7620,7 @@ export const insertReleaseInternal = internalMutation({ }), ), integritySha256: v.string(), + sha256hash: v.string(), artifactKind: v.optional(v.union(v.literal("legacy-zip"), v.literal("npm-pack"))), clawpackStorageId: v.optional(v.id("_storage")), clawpackSha256: v.optional(v.string()), @@ -7812,6 +7827,7 @@ export const insertReleaseInternal = internalMutation({ distTags: effectiveTags, files: args.files, integritySha256: args.integritySha256, + sha256hash: args.sha256hash, artifactKind: args.artifactKind, clawpackStorageId: args.clawpackStorageId, clawpackSha256: args.clawpackSha256, @@ -7906,6 +7922,7 @@ async function recordMaliciousPluginReleaseFinding( release: Doc<"packageReleases">, trigger: string, ) { + const artifactSha256 = getPackageReleaseArtifactSha256(release); await ctx.scheduler.runAfter(0, internal.users.recordMaliciousArtifactFindingInternal, { ownerUserId: release.createdBy, artifactKind: "plugin", @@ -7913,7 +7930,7 @@ async function recordMaliciousPluginReleaseFinding( version: release.version, trigger, ...(release.llmAnalysis?.summary ? { findingSummary: release.llmAnalysis.summary } : {}), - ...(release.sha256hash ? { sha256hash: release.sha256hash } : {}), + ...(artifactSha256 ? { sha256hash: artifactSha256 } : {}), }); } @@ -8125,7 +8142,6 @@ async function syncLatestPackageVerification( export const updateReleaseScanResultsInternal = internalMutation({ args: { releaseId: v.id("packageReleases"), - sha256hash: v.optional(v.string()), vtAnalysis: v.optional(vtAnalysisValidator), }, handler: async (ctx, args) => { @@ -8133,7 +8149,6 @@ export const updateReleaseScanResultsInternal = internalMutation({ if (!release || release.softDeletedAt) return; const patch: Partial> = {}; - if (args.sha256hash !== undefined) patch.sha256hash = args.sha256hash; if (args.vtAnalysis !== undefined) { patch.vtAnalysis = args.vtAnalysis; } diff --git a/convex/publishers.test.ts b/convex/publishers.test.ts index ec1a4167..6bec87d9 100644 --- a/convex/publishers.test.ts +++ b/convex/publishers.test.ts @@ -301,7 +301,7 @@ const resolvePublishTargetForUserInternalHandler = ( > )._handler; -function indexedRows(rows: T[]) { +function indexedRows(rows: unknown[]) { return { collect: vi.fn(async () => rows), order: vi.fn(() => ({ diff --git a/convex/schema.ts b/convex/schema.ts index 22d7efad..c32fac41 100644 --- a/convex/schema.ts +++ b/convex/schema.ts @@ -1230,6 +1230,7 @@ const packageReleases = defineTable({ runtimeId: v.optional(v.string()), sourceRepo: v.optional(v.string()), verification: packageVerificationValidator, + // Deprecated compatibility hash for exact /download ZIP bytes; use artifact.sha256 for installs. sha256hash: v.optional(v.string()), vtAnalysis: v.optional(vtAnalysisValidator), skillSpectorAnalysis: v.optional(skillSpectorAnalysisValidator), diff --git a/convex/securityDataset.ts b/convex/securityDataset.ts index 106cc2c9..1a2d5f76 100644 --- a/convex/securityDataset.ts +++ b/convex/securityDataset.ts @@ -4,6 +4,7 @@ import { internal } from "./_generated/api"; import type { Doc } from "./_generated/dataModel"; import type { ActionCtx, QueryCtx } from "./_generated/server"; import { internalAction, internalQuery } from "./functions"; +import { getPackageReleaseArtifactSha256 } from "./lib/packageArtifacts"; import { getOwnerPublisher } from "./lib/publishers"; const MAX_EXPORT_PAGE_SIZE = 50; @@ -270,7 +271,7 @@ async function packageReleasePageToExportRows( publicOwnerHandle, publicSlug: pkg.name, version: release.version, - artifactSha256: release.sha256hash ?? release.integritySha256, + artifactSha256: getPackageReleaseArtifactSha256(release), createdAt: release.createdAt, softDeletedAt: release.softDeletedAt ?? null, files: sanitizeFiles(release.files), diff --git a/convex/vt.test.ts b/convex/vt.test.ts index 2c456258..a0fd8c91 100644 --- a/convex/vt.test.ts +++ b/convex/vt.test.ts @@ -440,13 +440,7 @@ describe("package VT retries", () => { { releaseId: "packageReleases:demo" }, ); - expect(runMutation).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - releaseId: "packageReleases:demo", - sha256hash: expect.any(String), - }), - ); + expect(mutationPayloads(runMutation).every((payload) => !("sha256hash" in payload))).toBe(true); expect(scheduler.runAfter).toHaveBeenCalledWith(5 * 60 * 1000, expect.anything(), { releaseId: "packageReleases:demo", attempt: 2, @@ -503,13 +497,7 @@ describe("package VT retries", () => { { releaseId: "packageReleases:demo" }, ); - expect(runMutation).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - releaseId: "packageReleases:demo", - sha256hash: clawpackSha256, - }), - ); + expect(mutationPayloads(runMutation).every((payload) => !("sha256hash" in payload))).toBe(true); expect(fetchMock).toHaveBeenNthCalledWith( 1, `https://www.virustotal.com/api/v3/files/${clawpackSha256}`, @@ -807,7 +795,8 @@ describe("package VT retries", () => { it("retries package poll when VT lookup throws", async () => { process.env.VT_API_KEY = "test-key"; - vi.stubGlobal("fetch", vi.fn().mockRejectedValue(new Error("network error"))); + const fetchMock = vi.fn().mockRejectedValue(new Error("network error")); + vi.stubGlobal("fetch", fetchMock); const scheduler = { runAfter: vi.fn(async () => null) }; await pollPackageReleaseScanResultsHandler( @@ -816,7 +805,9 @@ describe("package VT retries", () => { _id: "packageReleases:demo", packageId: "packages:demo", version: "1.0.0", - sha256hash: "abc123", + artifactKind: "npm-pack", + sha256hash: "legacy-zip-sha", + clawpackSha256: "tgz-sha", }), runMutation: vi.fn(async () => null), scheduler, @@ -824,12 +815,39 @@ describe("package VT retries", () => { { releaseId: "packageReleases:demo", attempt: 3 }, ); + expect(fetchMock).toHaveBeenCalledWith( + "https://www.virustotal.com/api/v3/files/tgz-sha", + expect.objectContaining({ method: "GET" }), + ); expect(scheduler.runAfter).toHaveBeenCalledWith(5 * 60 * 1000, expect.anything(), { releaseId: "packageReleases:demo", attempt: 4, }); }); + it("does not poll a legacy ZIP hash when an npm-pack artifact hash is missing", async () => { + process.env.VT_API_KEY = "test-key"; + const fetchMock = vi.fn(); + vi.stubGlobal("fetch", fetchMock); + + await pollPackageReleaseScanResultsHandler( + { + runQuery: vi.fn().mockResolvedValue({ + _id: "packageReleases:demo", + packageId: "packages:demo", + version: "1.0.0", + artifactKind: "npm-pack", + sha256hash: "legacy-zip-sha", + }), + runMutation: vi.fn(async () => null), + scheduler: { runAfter: vi.fn(async () => null) }, + } as never, + { releaseId: "packageReleases:demo", attempt: 3 }, + ); + + expect(fetchMock).not.toHaveBeenCalled(); + }); + it("stores undetected-only package VT telemetry during polling even when static scan is suspicious", async () => { process.env.VT_API_KEY = "test-key"; vi.stubGlobal( diff --git a/convex/vt.ts b/convex/vt.ts index 1778ccb1..3c691b2e 100644 --- a/convex/vt.ts +++ b/convex/vt.ts @@ -2,6 +2,7 @@ import { v } from "convex/values"; import { internal } from "./_generated/api"; import type { Doc, Id } from "./_generated/dataModel"; import { internalAction, internalMutation } from "./functions"; +import { getPackageReleaseArtifactSha256 } from "./lib/packageArtifacts"; import { sourceSkillVersionFiles } from "./lib/skillCards"; import { buildDeterministicPackageZip, buildDeterministicZip } from "./lib/skillZip"; @@ -722,11 +723,6 @@ export const scanPackageReleaseWithVirusTotal = internalAction({ return; } - await runMutationRef(ctx, internalRefs.packages.updateReleaseScanResultsInternal, { - releaseId: args.releaseId, - sha256hash: artifact.sha256hash, - }); - try { const existingFile = await checkExistingFile(apiKey, artifact.sha256hash); const vtAnalysis = existingFile @@ -812,7 +808,9 @@ export const pollPackageReleaseScanResults = internalAction({ const release = (await runQueryRef(ctx, internalRefs.packages.getReleaseByIdInternal, { releaseId: args.releaseId, })) as Doc<"packageReleases"> | null; - if (!release || release.softDeletedAt || !release.sha256hash) return; + if (!release || release.softDeletedAt) return; + const artifactSha256 = getPackageReleaseArtifactSha256(release); + if (!artifactSha256) return; const pkg = (await runQueryRef(ctx, internalRefs.packages.getPackageByIdInternal, { packageId: release.packageId, })) as Doc<"packages"> | null; @@ -820,7 +818,7 @@ export const pollPackageReleaseScanResults = internalAction({ const attempt = args.attempt ?? 1; try { - const vtResult = await checkExistingFile(apiKey, release.sha256hash); + const vtResult = await checkExistingFile(apiKey, artifactSha256); if (!vtResult) { if (attempt < PACKAGE_SCAN_MAX_ATTEMPTS) { await runAfterRef( @@ -870,7 +868,7 @@ export const pollPackageReleaseScanResults = internalAction({ await enqueuePackageCodexForVtSignal(ctx, args.releaseId); } } catch (error) { - console.error(`[vt:package] Error polling ${release.sha256hash}:`, error); + console.error(`[vt:package] Error polling ${artifactSha256}:`, error); if (attempt < PACKAGE_SCAN_MAX_ATTEMPTS) { await runAfterRef( ctx, diff --git a/docs/http-api.md b/docs/http-api.md index 1bdf037c..15200183 100644 --- a/docs/http-api.md +++ b/docs/http-api.md @@ -722,7 +722,12 @@ Notes: `npm-pack` for ClawPack-backed releases. - ClawPack releases include npm-compatible `npmIntegrity`, `npmShasum`, and `npmTarballName` fields. -- `version.sha256hash`, `version.vtAnalysis`, `version.llmAnalysis`, and `version.staticScan` are included when scan data exists. +- `version.sha256hash` is deprecated compatibility metadata for old clients. It + hashes the exact ZIP bytes returned by `/api/v1/packages/{name}/download`. + Modern clients should use `version.artifact.sha256`, which identifies the + canonical release artifact. +- `version.vtAnalysis`, `version.llmAnalysis`, and `version.staticScan` are + included when scan data exists. - Private packages return `404` unless the caller can read the owning publisher. ### `GET /api/v1/packages/{name}/versions/{version}/security` diff --git a/packages/clawhub/src/schema/packages.ts b/packages/clawhub/src/schema/packages.ts index 06e08af3..996be471 100644 --- a/packages/clawhub/src/schema/packages.ts +++ b/packages/clawhub/src/schema/packages.ts @@ -422,6 +422,7 @@ export const ApiV1PackageVersionResponseSchema = type({ capabilities: PackageCapabilitySummarySchema.or("null").optional(), verification: PackageVerificationSummarySchema.or("null").optional(), artifact: PackageArtifactSummarySchema.or("null").optional(), + // Deprecated compatibility hash for exact /download ZIP bytes; use artifact.sha256 for installs. sha256hash: "string|null?", vtAnalysis: PackageVtAnalysisSchema.or("null").optional(), skillSpectorAnalysis: PackageSkillSpectorAnalysisSchema.or("null").optional(), diff --git a/packages/schema/dist/packages.js b/packages/schema/dist/packages.js index b66168ca..b9fc8c31 100644 --- a/packages/schema/dist/packages.js +++ b/packages/schema/dist/packages.js @@ -344,6 +344,7 @@ export const ApiV1PackageVersionResponseSchema = type({ capabilities: PackageCapabilitySummarySchema.or("null").optional(), verification: PackageVerificationSummarySchema.or("null").optional(), artifact: PackageArtifactSummarySchema.or("null").optional(), + // Deprecated compatibility hash for exact /download ZIP bytes; use artifact.sha256 for installs. sha256hash: "string|null?", vtAnalysis: PackageVtAnalysisSchema.or("null").optional(), skillSpectorAnalysis: PackageSkillSpectorAnalysisSchema.or("null").optional(), diff --git a/packages/schema/dist/packages.js.map b/packages/schema/dist/packages.js.map index deae8799..67be76b4 100644 --- a/packages/schema/dist/packages.js.map +++ b/packages/schema/dist/packages.js.map @@ -1 +1 @@ -{"version":3,"file":"packages.js","sourceRoot":"","sources":["../src/packages.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"packages.js","sourceRoot":"","sources":["../src/packages.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/schema/src/packages.ts b/packages/schema/src/packages.ts index 9d210b7f..488d5437 100644 --- a/packages/schema/src/packages.ts +++ b/packages/schema/src/packages.ts @@ -451,6 +451,7 @@ export const ApiV1PackageVersionResponseSchema = type({ capabilities: PackageCapabilitySummarySchema.or("null").optional(), verification: PackageVerificationSummarySchema.or("null").optional(), artifact: PackageArtifactSummarySchema.or("null").optional(), + // Deprecated compatibility hash for exact /download ZIP bytes; use artifact.sha256 for installs. sha256hash: "string|null?", vtAnalysis: PackageVtAnalysisSchema.or("null").optional(), skillSpectorAnalysis: PackageSkillSpectorAnalysisSchema.or("null").optional(), diff --git a/scripts/security-dataset/convexExport.test.ts b/scripts/security-dataset/convexExport.test.ts index a20404ba..03a980b5 100644 --- a/scripts/security-dataset/convexExport.test.ts +++ b/scripts/security-dataset/convexExport.test.ts @@ -143,7 +143,10 @@ describe("Convex export dataset ingestion", () => { packageId: "packages:public", version: "2.0.0", createdAt: 1, - integritySha256: "pkg-sha", + artifactKind: "npm-pack", + clawpackSha256: "pkg-tgz-sha", + sha256hash: "pkg-zip-sha", + integritySha256: "pkg-file-set-sha", files: [{ path: "package/index.js", size: 24, sha256: "pkg-file-sha" }], staticScan: { status: "clean", @@ -172,7 +175,7 @@ describe("Convex export dataset ingestion", () => { expect(rows[0]).toMatchObject({ sourceKind: "package", sourceDocId: "packageReleases:1", - artifactSha256: "pkg-sha", + artifactSha256: "pkg-tgz-sha", publicOwnerHandle: "alice", packageChannel: "community", sourceRepoHost: "github.com", diff --git a/scripts/security-dataset/convexExport.ts b/scripts/security-dataset/convexExport.ts index 3af720d7..77309997 100644 --- a/scripts/security-dataset/convexExport.ts +++ b/scripts/security-dataset/convexExport.ts @@ -228,7 +228,7 @@ function packageReleaseToExportRow( ), publicSlug: stringOrNull(pkg.name), version: requiredString(release.version, "packageReleases.version"), - artifactSha256: stringOrNull(release.sha256hash) ?? stringOrNull(release.integritySha256), + artifactSha256: packageReleaseArtifactSha256(release), createdAt: numberValue(release.createdAt, "packageReleases.createdAt"), softDeletedAt: numberOrNull(release.softDeletedAt), files: filesFromExport(release.files), @@ -246,6 +246,13 @@ function packageReleaseToExportRow( ]; } +function packageReleaseArtifactSha256(release: ConvexDoc) { + if (stringOrNull(release.artifactKind) === "npm-pack") { + return stringOrNull(release.clawpackSha256); + } + return stringOrNull(release.sha256hash); +} + function publicOwnerHandleFromExport( source: ConvexDoc, usersById: Map, diff --git a/src/__tests__/plugin-security-audit-route.test.tsx b/src/__tests__/plugin-security-audit-route.test.tsx index 4dda9856..bc0ee6ff 100644 --- a/src/__tests__/plugin-security-audit-route.test.tsx +++ b/src/__tests__/plugin-security-audit-route.test.tsx @@ -80,4 +80,22 @@ describe("plugin security audit route", () => { expect(screen.queryByRole("button", { name: "Rescan" })).toBeNull(); expect(screen.queryByRole("button", { name: "Download security audit" })).toBeNull(); }); + + it("links VirusTotal to the canonical npm-pack artifact hash", () => { + const loaderData = makeLoaderData(); + loaderData.version.version = { + ...loaderData.version.version, + sha256hash: "legacy-zip-sha", + artifact: { + kind: "npm-pack", + sha256: "tgz-sha", + }, + } as never; + + render(); + + expect(screen.getByRole("link", { name: "View on VirusTotal" }).getAttribute("href")).toBe( + "https://www.virustotal.com/gui/file/tgz-sha", + ); + }); }); diff --git a/src/lib/packageApi.ts b/src/lib/packageApi.ts index 5ed586b1..476178b6 100644 --- a/src/lib/packageApi.ts +++ b/src/lib/packageApi.ts @@ -64,6 +64,7 @@ export type PackageVersionDetail = { npmUnpackedSize?: number; npmFileCount?: number; } | null; + /** @deprecated Compatibility hash for exact /download ZIP bytes. Use artifact.sha256. */ sha256hash?: string | null; vtAnalysis?: { status: string; diff --git a/src/routes/plugins/$name/security-audit.tsx b/src/routes/plugins/$name/security-audit.tsx index 3fa711cd..51ae2091 100644 --- a/src/routes/plugins/$name/security-audit.tsx +++ b/src/routes/plugins/$name/security-audit.tsx @@ -145,7 +145,7 @@ export function PluginSecurityAuditPage({ ownerPublisherId: null, detailPath: buildPluginDetailHref(name), }} - sha256hash={release.sha256hash ?? null} + sha256hash={release.artifact?.sha256 ?? null} vtAnalysis={release.vtAnalysis ?? null} llmAnalysis={release.llmAnalysis ?? null} skillSpectorAnalysis={release.skillSpectorAnalysis ?? null}