Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/advisory/osv-advisory-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ export class OsvAdvisorySource implements AdvisorySource {

const data = await response.json();

if (!Array.isArray(data?.results)) {
throw new Error(
'OSV batch query returned a 200 response with no "results" array',
);
}

return data.results.map((r: any, i: number) => ({
package: packages[i].name,
version: packages[i].version,
Expand Down Expand Up @@ -135,4 +141,4 @@ export class OsvAdvisorySource implements AdvisorySource {
throw new Error(`OSV vuln fetch failed for ${id} via ${this.baseUrl}: ${message}`);
}
}
}
}
52 changes: 52 additions & 0 deletions tests/osv-advisory-source-missing-results.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { describe, it, expect } from "@jest/globals";
import { OsvAdvisorySource } from "../src/advisory/osv-advisory-source.js";
import type { PackageRef } from "../src/types.js";

function pkg(name: string): PackageRef {
return { name, version: "1.0.0", ecosystem: "npm" };
}

function makeFetch(body: unknown, status = 200): () => Promise<Response> {
return async () =>
new Response(JSON.stringify(body), {
status,
headers: { "Content-Type": "application/json" },
});
}

describe("OsvAdvisorySource.queryBatch — missing results field", () => {
it("throws when response body has no results field", async () => {
const source = new OsvAdvisorySource(
"https://api.osv.dev",
undefined,
makeFetch({}),
);

await expect(
source.queryBatch([pkg("lodash")]),
).rejects.toThrow(/results/);
});

it("succeeds normally when results is a populated array (control case)", async () => {
const source = new OsvAdvisorySource(
"https://api.osv.dev",
undefined,
makeFetch({ results: [{ vulns: [{ id: "OSV-123" }] }] }),
);

const results = await source.queryBatch([pkg("lodash")]);
expect(results).toHaveLength(1);
expect(results[0].vulnerabilities).toEqual([{ id: "OSV-123" }]);
});

it("succeeds when results is an empty array", async () => {
const source = new OsvAdvisorySource(
"https://api.osv.dev",
undefined,
makeFetch({ results: [] }),
);

const results = await source.queryBatch([pkg("lodash")]);
expect(results).toHaveLength(0);
});
});