Skip to content

Commit e3424a7

Browse files
committed
Cleanup
1 parent 495d79d commit e3424a7

4 files changed

Lines changed: 26 additions & 121 deletions

File tree

app/composables/npm/usePackage.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
1-
import type { Packument, SlimPackument, SlimVersion, SlimPackumentVersion } from '#shared/types'
1+
import type {
2+
Packument,
3+
SlimPackument,
4+
SlimVersion,
5+
SlimPackumentVersion,
6+
PackumentVersion,
7+
PublishTrustLevel,
8+
} from '#shared/types'
29
import { NPM_REGISTRY } from '~/utils/npm/common'
310
import { extractInstallScriptsInfo } from '~/utils/install-scripts'
411

512
/** Number of recent versions to include in initial payload */
613
const RECENT_VERSIONS_COUNT = 5
714

8-
function hasAttestations(version: Packument['versions'][string]): boolean {
15+
function hasAttestations(version: PackumentVersion): boolean {
916
return Boolean(version.dist.attestations)
1017
}
1118

12-
function hasTrustedPublisher(version: Packument['versions'][string]): boolean {
19+
function hasTrustedPublisher(version: PackumentVersion): boolean {
1320
return Boolean(version._npmUser?.trustedPublisher)
1421
}
1522

16-
function hasPublishTrustEvidence(version: Packument['versions'][string]): boolean {
17-
return hasAttestations(version) || hasTrustedPublisher(version)
18-
}
19-
20-
function getTrustLevel(version: Packument['versions'][string]): SlimVersion['trustLevel'] {
23+
function getTrustLevel(version: PackumentVersion): PublishTrustLevel {
2124
if (hasAttestations(version)) return 'provenance'
2225
if (hasTrustedPublisher(version)) return 'trustedPublisher'
2326
return 'none'
@@ -84,8 +87,8 @@ export function transformPackument(
8487
installScripts: installScripts ?? undefined,
8588
}
8689
}
87-
const hasProvenance = hasPublishTrustEvidence(version)
8890
const trustLevel = getTrustLevel(version)
91+
const hasProvenance = trustLevel !== 'none'
8992

9093
filteredVersions[v] = {
9194
hasProvenance,

app/pages/package/[...package].vue

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,10 +245,9 @@ const publishSecurityDowngrade = computed(() => {
245245
return detectPublishSecurityDowngradeForVersion(versionSecurityMetadata.value, currentVersion)
246246
})
247247
248-
const installVersionOverride = computed(() => {
249-
if (!publishSecurityDowngrade.value) return null
250-
return publishSecurityDowngrade.value.trustedVersion
251-
})
248+
const installVersionOverride = computed(
249+
() => publishSecurityDowngrade.value?.trustedVersion ?? null,
250+
)
252251
253252
const sizeTooltip = computed(() => {
254253
const chunks = [

app/utils/publish-security.ts

Lines changed: 10 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -31,59 +31,23 @@ function toTimestamp(time?: string): number {
3131
}
3232

3333
function sortByRecency(a: VersionWithIndex, b: VersionWithIndex): number {
34-
const aValid = Number.isFinite(a.timestamp)
35-
const bValid = Number.isFinite(b.timestamp)
34+
const aValid = !Number.isNaN(a.timestamp)
35+
const bValid = !Number.isNaN(b.timestamp)
3636

37-
if (aValid && bValid && a.timestamp !== b.timestamp) {
38-
return b.timestamp - a.timestamp
37+
if (!aValid && !bValid) {
38+
// Fall back to semver comparison if no valid timestamps
39+
const semverOrder = compare(b.version, a.version)
40+
if (semverOrder !== 0) return semverOrder
41+
42+
// If semver is also equal, maintain original order
43+
return a.index - b.index
3944
}
4045

4146
if (aValid !== bValid) {
4247
return aValid ? -1 : 1
4348
}
4449

45-
const semverOrder = compare(b.version, a.version)
46-
if (semverOrder !== 0) return semverOrder
47-
48-
return a.index - b.index
49-
}
50-
51-
/**
52-
* Detects a security downgrade where the newest publish is not trusted,
53-
* but an older publish was trusted (e.g. OIDC/provenance -> manual publish).
54-
*/
55-
export function detectPublishSecurityDowngrade(
56-
versions: PackageVersionInfo[],
57-
): PublishSecurityDowngrade | null {
58-
if (versions.length < 2) return null
59-
60-
const sorted = versions
61-
.map((version, index) => ({
62-
...version,
63-
index,
64-
timestamp: toTimestamp(version.time),
65-
trustRank: getTrustRank(version),
66-
}))
67-
.sort(sortByRecency)
68-
69-
const latest = sorted.at(0)
70-
if (!latest) return null
71-
72-
let strongestOlder: VersionWithIndex | null = null
73-
for (const version of sorted.slice(1)) {
74-
if (!strongestOlder || version.trustRank > strongestOlder.trustRank) {
75-
strongestOlder = version
76-
}
77-
}
78-
79-
if (!strongestOlder || strongestOlder.trustRank <= latest.trustRank) return null
80-
81-
return {
82-
downgradedVersion: latest.version,
83-
downgradedPublishedAt: latest.time,
84-
trustedVersion: strongestOlder.version,
85-
trustedPublishedAt: strongestOlder.time,
86-
}
50+
return b.timestamp - a.timestamp
8751
}
8852

8953
/**

test/unit/app/utils/publish-security.spec.ts

Lines changed: 1 addition & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,5 @@
11
import { describe, expect, it } from 'vitest'
2-
import {
3-
detectPublishSecurityDowngrade,
4-
detectPublishSecurityDowngradeForVersion,
5-
} from '../../../../app/utils/publish-security'
6-
7-
describe('detectPublishSecurityDowngrade', () => {
8-
it('detects downgrade when latest publish is untrusted and older publish is trusted', () => {
9-
const result = detectPublishSecurityDowngrade([
10-
{
11-
version: '1.0.0',
12-
time: '2026-01-01T00:00:00.000Z',
13-
hasProvenance: true,
14-
},
15-
{
16-
version: '1.0.1',
17-
time: '2026-01-02T00:00:00.000Z',
18-
hasProvenance: false,
19-
},
20-
])
21-
22-
expect(result).toEqual({
23-
downgradedVersion: '1.0.1',
24-
downgradedPublishedAt: '2026-01-02T00:00:00.000Z',
25-
trustedVersion: '1.0.0',
26-
trustedPublishedAt: '2026-01-01T00:00:00.000Z',
27-
})
28-
})
29-
30-
it('returns null when latest publish is trusted', () => {
31-
const result = detectPublishSecurityDowngrade([
32-
{
33-
version: '1.0.0',
34-
time: '2026-01-01T00:00:00.000Z',
35-
hasProvenance: false,
36-
},
37-
{
38-
version: '1.0.1',
39-
time: '2026-01-02T00:00:00.000Z',
40-
hasProvenance: true,
41-
},
42-
])
43-
44-
expect(result).toBeNull()
45-
})
46-
47-
it('returns null when there is no trusted historical release', () => {
48-
const result = detectPublishSecurityDowngrade([
49-
{
50-
version: '1.0.0',
51-
time: '2026-01-01T00:00:00.000Z',
52-
hasProvenance: false,
53-
},
54-
{
55-
version: '1.0.1',
56-
time: '2026-01-02T00:00:00.000Z',
57-
hasProvenance: false,
58-
},
59-
])
60-
61-
expect(result).toBeNull()
62-
})
63-
})
2+
import { detectPublishSecurityDowngradeForVersion } from '../../../../app/utils/publish-security'
643

654
describe('detectPublishSecurityDowngradeForVersion', () => {
665
const versions = [

0 commit comments

Comments
 (0)