Skip to content

Commit 02f1345

Browse files
committed
fix: race condition where artifacts from late resolving flights could be silently dropped
1 parent 986e9eb commit 02f1345

File tree

5 files changed

+248
-21
lines changed

5 files changed

+248
-21
lines changed

bun.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/modes/authenticated.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export default function (apiKey: string): ScannerImplementation {
1212
return createScanner({
1313
maxSending: 30,
1414
maxBatchLength: 1,
15-
fetchStrategy: async (purls, artifacts) => {
15+
fetchStrategy: async (purls) => {
1616
const body = JSON.stringify({
1717
components: purls.map(purl => ({ purl }))
1818
} satisfies SocketBatchEndpointBody)
@@ -33,7 +33,7 @@ export default function (apiKey: string): ScannerImplementation {
3333

3434
const data = await res.text()
3535

36-
artifacts.push(...data.split('\n').filter(Boolean).map(line => JSON.parse(line)))
36+
return data.split('\n').filter(Boolean).map(line => JSON.parse(line))
3737
}
3838
})
3939
}

src/modes/unauthenticated.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
import type { ScannerImplementation } from '../types'
1+
import type { ScannerImplementation, SocketArtifact } from '../types'
22
import { createScanner } from '../scanner-factory'
33
import { userAgent } from './user-agent'
44

55
export default function (): ScannerImplementation {
66
return createScanner({
77
maxSending: 20,
88
maxBatchLength: 50,
9-
fetchStrategy: async (purls, artifacts) => {
9+
fetchStrategy: async (purls) => {
1010
const urls = purls.map(purl => `https://firewall-api.socket.dev/purl/${encodeURIComponent(purl)}`)
11+
const results: SocketArtifact[] = []
1112
await Promise.all(urls.map(async url => {
1213
const res = await fetch(url, {
1314
headers: {
@@ -18,8 +19,9 @@ export default function (): ScannerImplementation {
1819
throw new Error(`Socket Security Scanner: Received ${res.status} from server`)
1920
}
2021
const data = await res.text()
21-
artifacts.push(...data.split('\n').filter(Boolean).map(line => JSON.parse(line)))
22+
results.push(...data.split('\n').filter(Boolean).map(line => JSON.parse(line)))
2223
}))
24+
return results
2325
}
2426
})
2527
}

src/scanner-factory.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,38 @@ import type { SocketArtifact, ScannerImplementation } from './types'
33
type ScannerConfig = {
44
maxSending: number
55
maxBatchLength: number
6-
fetchStrategy: (purls: string[], artifacts: SocketArtifact[]) => Promise<void>
6+
fetchStrategy: (purls: string[]) => Promise<SocketArtifact[]>
77
}
88

99
export function createScanner({ maxSending, maxBatchLength, fetchStrategy }: ScannerConfig): ScannerImplementation {
1010
return async function*(packages) {
1111
let artifacts: SocketArtifact[] = []
1212
let batch: Bun.Security.Package[] = []
13-
let in_flight = 0
13+
let inFlight = 0
1414

1515
const pending: Set<Promise<void>> = new Set()
1616

1717
async function startFlight() {
1818
const purls = batch.map(p => `pkg:npm/${p.name}@${p.version}`)
1919
batch = []
20-
in_flight += purls.length
20+
inFlight += purls.length
2121

22-
if (in_flight >= maxSending) {
22+
if (inFlight >= maxSending) {
2323
if (pending.size !== 0) {
2424
await Promise.race([...pending])
2525
} else {
2626
// bug if we get here
2727
}
2828
}
2929

30-
const flight = fetchStrategy(purls, artifacts)
30+
const flight = fetchStrategy(purls).then(results => {
31+
artifacts.push(...results)
32+
})
3133

3234
pending.add(flight)
3335

3436
flight.finally(() => {
35-
in_flight -= purls.length
37+
inFlight -= purls.length
3638
pending.delete(flight)
3739
})
3840
}

0 commit comments

Comments
 (0)