@adea-ai/plugins 2.0.41 → 2.0.43
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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adea-ai/plugins",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.43",
|
|
4
4
|
"description": "Deterministic compiler for AI agent plugin marketplaces: schemas, source parsing, provenance verification, per-harness materialization, and provenance-checked static artifacts.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"dependencies": {
|
|
92
92
|
"tar-stream": "^3.2.1",
|
|
93
93
|
"yaml": "2.9.1",
|
|
94
|
-
"zod": "^4.6.
|
|
94
|
+
"zod": "^4.6.6"
|
|
95
95
|
},
|
|
96
96
|
"engines": {
|
|
97
97
|
"bun": ">=1.4.0 <2",
|
|
@@ -25,3 +25,38 @@ for (const [name, schema] of [
|
|
|
25
25
|
})
|
|
26
26
|
})
|
|
27
27
|
}
|
|
28
|
+
|
|
29
|
+
it('rejects an oversized file collection before reading any attacker-controlled entries', () => {
|
|
30
|
+
let visitedEntries = 0
|
|
31
|
+
const oversizedFiles = new Proxy([], {
|
|
32
|
+
get(target, property, receiver) {
|
|
33
|
+
if (property === 'length') return 8193
|
|
34
|
+
if (typeof property === 'string' && /^(0|[1-9][0-9]*)$/.test(property)) {
|
|
35
|
+
visitedEntries += 1
|
|
36
|
+
throw new Error('Oversized file entries must not be traversed.')
|
|
37
|
+
}
|
|
38
|
+
return Reflect.get(target, property, receiver)
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const result = AgentPackageSchema.shape.files.safeParse(oversizedFiles)
|
|
43
|
+
|
|
44
|
+
assert.equal(result.success, false)
|
|
45
|
+
assert.equal(visitedEntries, 0)
|
|
46
|
+
if (!result.success) assert.equal(result.error.issues[0]?.code, 'too_big')
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('accepts a file collection at the public schema limit', () => {
|
|
50
|
+
const file = {
|
|
51
|
+
action: 'copy',
|
|
52
|
+
sourcePath: 'source.txt',
|
|
53
|
+
targetPath: 'target.txt',
|
|
54
|
+
digest: `sha256:${'a'.repeat(64)}`,
|
|
55
|
+
preserveMode: true,
|
|
56
|
+
} as const
|
|
57
|
+
|
|
58
|
+
const result = AgentPackageSchema.shape.files.safeParse(Array.from({ length: 8192 }, () => file))
|
|
59
|
+
|
|
60
|
+
assert.equal(result.success, true)
|
|
61
|
+
if (result.success) assert.equal(result.data.length, 8192)
|
|
62
|
+
})
|
|
@@ -22,7 +22,7 @@ for (const name of ['marketplace-ci', 'marketplace-sync', 'publish-packages']) {
|
|
|
22
22
|
"github.ref == format('refs/heads/{0}', github.event.repository.default_branch)"
|
|
23
23
|
)
|
|
24
24
|
expect(block).toContain("steps.bun-downloads.outputs.cache-hit != 'true'")
|
|
25
|
-
expect(block).toContain("runner.os }}-${{ runner.arch }}-1.4.
|
|
25
|
+
expect(block).toContain("runner.os }}-${{ runner.arch }}-1.4.4-${{ hashFiles('bun.lock')")
|
|
26
26
|
const events = name === 'marketplace-sync' ? ['schedule', 'workflow_dispatch'] : ['push']
|
|
27
27
|
for (const event of events) {
|
|
28
28
|
expect(source.slice(0, source.indexOf('\npermissions:'))).toContain(`${event}:`)
|
|
@@ -2,7 +2,8 @@ import { it } from 'node:test'
|
|
|
2
2
|
import assert from 'node:assert/strict'
|
|
3
3
|
import { existsSync, lstatSync, realpathSync } from 'node:fs'
|
|
4
4
|
import { writeFile, mkdir, readFile, readdir, mkdtemp, symlink, rm, chmod } from 'node:fs/promises'
|
|
5
|
-
import { join } from 'node:path'
|
|
5
|
+
import { join, sep } from 'node:path'
|
|
6
|
+
import { pathToFileURL } from 'node:url'
|
|
6
7
|
import { tmpdir } from 'node:os'
|
|
7
8
|
import { synchronize, verifyArtifacts, digest } from './index.js'
|
|
8
9
|
import {
|
|
@@ -420,10 +421,13 @@ it('gives a PACKED consumer the same installation plan as the workspace path', (
|
|
|
420
421
|
// The compiled artifact was reached through the PUBLIC specifier: the
|
|
421
422
|
// resolved module lives in the packed package's dist, not in the
|
|
422
423
|
// workspace source.
|
|
423
|
-
|
|
424
|
+
const physicalConsumerRootUrl = pathToFileURL(
|
|
425
|
+
`${realpathSync(consumer.consumerRoot)}${sep}`
|
|
426
|
+
).href
|
|
427
|
+
assert.ok(nodeResult.resolvedHarness.startsWith(physicalConsumerRootUrl))
|
|
424
428
|
assert.ok(nodeResult.resolvedHarness.includes('@adea-ai/plugins'))
|
|
425
429
|
assert.ok(nodeResult.resolvedHarness.includes('/dist/'))
|
|
426
|
-
assert.ok(nodeResult.resolvedCatalog.startsWith(
|
|
430
|
+
assert.ok(nodeResult.resolvedCatalog.startsWith(physicalConsumerRootUrl))
|
|
427
431
|
assert.ok(nodeResult.resolvedCatalog.includes('@adea-ai/plugins'))
|
|
428
432
|
assert.ok(nodeResult.resolvedCatalog.includes('/dist/'))
|
|
429
433
|
|
|
@@ -440,10 +444,10 @@ it('gives a PACKED consumer the same installation plan as the workspace path', (
|
|
|
440
444
|
}
|
|
441
445
|
assert.equal(bunResult.ok, true)
|
|
442
446
|
assert.deepEqual(bunResult.plan, sourcePlan)
|
|
443
|
-
assert.ok(bunResult.resolvedHarness.startsWith(
|
|
447
|
+
assert.ok(bunResult.resolvedHarness.startsWith(physicalConsumerRootUrl))
|
|
444
448
|
assert.ok(bunResult.resolvedHarness.includes('@adea-ai/plugins'))
|
|
445
449
|
assert.ok(bunResult.resolvedHarness.includes('/src/'))
|
|
446
|
-
assert.ok(bunResult.resolvedCatalog.startsWith(
|
|
450
|
+
assert.ok(bunResult.resolvedCatalog.startsWith(physicalConsumerRootUrl))
|
|
447
451
|
assert.ok(bunResult.resolvedCatalog.includes('@adea-ai/plugins'))
|
|
448
452
|
assert.ok(bunResult.resolvedCatalog.includes('/src/'))
|
|
449
453
|
}))
|