@aexhq/cli 0.21.0 → 0.22.1
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/dist/cli.mjs +39 -3
- package/dist/cli.mjs.sha256 +1 -1
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -350,6 +350,25 @@ var SKILL_BUNDLE_LIMITS = {
|
|
|
350
350
|
defaultDirMode: 493
|
|
351
351
|
};
|
|
352
352
|
var ASSET_ID_PATTERN = /^asset_[A-Za-z0-9_-]{8,128}$/;
|
|
353
|
+
var MOUNT_PATH_PATTERN = /^\/(?:[^/\0\\]+\/?)*$/;
|
|
354
|
+
var MOUNT_PATH_MAX_LENGTH = 512;
|
|
355
|
+
function assertValidMountPath(value, field) {
|
|
356
|
+
if (value.length === 0 || value.length > MOUNT_PATH_MAX_LENGTH) {
|
|
357
|
+
throw new Error(`${field} must be 1..${MOUNT_PATH_MAX_LENGTH} chars`);
|
|
358
|
+
}
|
|
359
|
+
if (!value.startsWith("/")) {
|
|
360
|
+
throw new Error(`${field} must be an absolute path starting with '/'`);
|
|
361
|
+
}
|
|
362
|
+
if (value.includes("\0") || value.includes("\\")) {
|
|
363
|
+
throw new Error(`${field} must not contain NUL or backslash`);
|
|
364
|
+
}
|
|
365
|
+
if (value.split("/").some((seg) => seg === "..")) {
|
|
366
|
+
throw new Error(`${field} must not contain '..' traversal segments`);
|
|
367
|
+
}
|
|
368
|
+
if (!MOUNT_PATH_PATTERN.test(value)) {
|
|
369
|
+
throw new Error(`${field} must match ${MOUNT_PATH_PATTERN.source}`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
353
372
|
function parseSkillRef(input, path) {
|
|
354
373
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
355
374
|
throw new Error(`${path} must be a SkillRef object`);
|
|
@@ -401,8 +420,11 @@ function parseAssetRefFields(record, path) {
|
|
|
401
420
|
throw new Error(`${path}.name must be a non-empty string (<= 128 chars)`);
|
|
402
421
|
}
|
|
403
422
|
const mountPath = record.mountPath;
|
|
404
|
-
if (mountPath !== void 0
|
|
405
|
-
|
|
423
|
+
if (mountPath !== void 0) {
|
|
424
|
+
if (typeof mountPath !== "string") {
|
|
425
|
+
throw new Error(`${path}.mountPath, when provided, must be a string`);
|
|
426
|
+
}
|
|
427
|
+
assertValidMountPath(mountPath, `${path}.mountPath`);
|
|
406
428
|
}
|
|
407
429
|
return {
|
|
408
430
|
kind: "asset",
|
|
@@ -879,7 +901,16 @@ var forbiddenStringPatterns = Object.freeze([
|
|
|
879
901
|
{ reason: "vault_id", regex: /\b(?:vault|vlt|secret)[_:-][A-Za-z0-9][A-Za-z0-9_-]{7,}\b/i },
|
|
880
902
|
{
|
|
881
903
|
reason: "private_resource_handle",
|
|
882
|
-
|
|
904
|
+
// `<keyword><sep><id>` opaque handles (`session_a1B2c3D4e5`, `file_9f8e7d…`).
|
|
905
|
+
// The keyword set overlaps ordinary English (agent/file/skill/resource/…), so
|
|
906
|
+
// the bare shape also matched documentation prose that simply chains those
|
|
907
|
+
// words with `_`/`-` (`agent_decision_failure`, `file_grounded`,
|
|
908
|
+
// `session_handoff_contract`, `agent-judgment` — read straight out of a
|
|
909
|
+
// skill-pack doc in tool-result text). The `accept` predicate keeps the shape
|
|
910
|
+
// but requires the id segment to look minted rather than spelled — i.e. carry
|
|
911
|
+
// a digit — so genuine handles stay flagged while dictionary-word prose does not.
|
|
912
|
+
regex: /\b(?:machine|session|agent|file|skill|env|resource|handle|token_hash|bearer_hash)[_:-][A-Za-z0-9][A-Za-z0-9_-]{7,}\b/i,
|
|
913
|
+
accept: isMintedResourceHandle
|
|
883
914
|
},
|
|
884
915
|
{
|
|
885
916
|
reason: "high_entropy_token",
|
|
@@ -909,6 +940,11 @@ function isHighEntropySecretRun(run) {
|
|
|
909
940
|
}
|
|
910
941
|
return highEntropyShannonBits(run) >= 3;
|
|
911
942
|
}
|
|
943
|
+
function isMintedResourceHandle(match) {
|
|
944
|
+
const separatorIndex = match.search(/[_:-]/);
|
|
945
|
+
const id = match.slice(separatorIndex + 1);
|
|
946
|
+
return /\d/.test(id);
|
|
947
|
+
}
|
|
912
948
|
function highEntropyCharClassCount(value) {
|
|
913
949
|
let count = 0;
|
|
914
950
|
if (/[a-z]/.test(value))
|
package/dist/cli.mjs.sha256
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
84dede6ed017defb49617f6f799912364125363867fa9ca8054150ebc0446286 cli.mjs
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aexhq/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/aexhq/aex.git"
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"fflate": "^0.8.2",
|
|
30
|
-
"@aexhq/contracts": "0.
|
|
30
|
+
"@aexhq/contracts": "0.22.1"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"esbuild": "^0.28.0"
|