@enactprotocol/cli 1.2.0 → 1.2.2
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/index.js +190 -8
- package/dist/index.js.bak +190 -8
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -37754,7 +37754,7 @@ var require_high_level_opt = __commonJS((exports, module) => {
|
|
|
37754
37754
|
]).reduce((set, kv) => (set[kv[0]] = kv[1], set), Object.create(null)) : {};
|
|
37755
37755
|
});
|
|
37756
37756
|
|
|
37757
|
-
// ../../node_modules/
|
|
37757
|
+
// ../../node_modules/minipass/index.js
|
|
37758
37758
|
var require_minipass = __commonJS((exports) => {
|
|
37759
37759
|
var proc = typeof process === "object" && process ? process : {
|
|
37760
37760
|
stdout: null,
|
|
@@ -215402,7 +215402,7 @@ command: "${command}"
|
|
|
215402
215402
|
}
|
|
215403
215403
|
function generateFullYaml(config2) {
|
|
215404
215404
|
let yaml = `# Enact Tool Definition
|
|
215405
|
-
# Generated by
|
|
215405
|
+
# Generated by @enactprotocol/cli
|
|
215406
215406
|
|
|
215407
215407
|
name: ${config2.name}
|
|
215408
215408
|
description: "${config2.description}"
|
|
@@ -226134,11 +226134,14 @@ class DaggerExecutionProvider extends ExecutionProvider {
|
|
|
226134
226134
|
init_env_loader();
|
|
226135
226135
|
var import_yaml = __toESM(require_dist(), 1);
|
|
226136
226136
|
|
|
226137
|
-
//
|
|
226137
|
+
// ../../node_modules/@enactprotocol/security/dist/index.js
|
|
226138
226138
|
import * as nc from "node:crypto";
|
|
226139
226139
|
import fs5 from "fs";
|
|
226140
226140
|
import path8 from "path";
|
|
226141
226141
|
import os5 from "os";
|
|
226142
|
+
import fs22 from "fs";
|
|
226143
|
+
import path22 from "path";
|
|
226144
|
+
import os22 from "os";
|
|
226142
226145
|
var crypto4 = nc && typeof nc === "object" && "webcrypto" in nc ? nc.webcrypto : nc && typeof nc === "object" && ("randomBytes" in nc) ? nc : undefined;
|
|
226143
226146
|
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
226144
226147
|
function isBytes(a) {
|
|
@@ -228581,6 +228584,165 @@ class KeyManager {
|
|
|
228581
228584
|
}
|
|
228582
228585
|
}
|
|
228583
228586
|
|
|
228587
|
+
class SecurityConfigManager {
|
|
228588
|
+
static ENACT_DIR = path22.join(os22.homedir(), ".enact");
|
|
228589
|
+
static SECURITY_DIR = path22.join(this.ENACT_DIR, "security");
|
|
228590
|
+
static CONFIG_FILE = path22.join(this.SECURITY_DIR, "config.json");
|
|
228591
|
+
static ensureDirectories() {
|
|
228592
|
+
try {
|
|
228593
|
+
if (!fs22.existsSync(this.ENACT_DIR)) {
|
|
228594
|
+
fs22.mkdirSync(this.ENACT_DIR, { recursive: true, mode: 493 });
|
|
228595
|
+
console.log(`Created .enact directory: ${this.ENACT_DIR}`);
|
|
228596
|
+
}
|
|
228597
|
+
if (!fs22.existsSync(this.SECURITY_DIR)) {
|
|
228598
|
+
fs22.mkdirSync(this.SECURITY_DIR, { recursive: true, mode: 493 });
|
|
228599
|
+
console.log(`Created security directory: ${this.SECURITY_DIR}`);
|
|
228600
|
+
}
|
|
228601
|
+
} catch (error2) {
|
|
228602
|
+
console.warn(`Failed to create directories: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
228603
|
+
}
|
|
228604
|
+
}
|
|
228605
|
+
static initializeConfig() {
|
|
228606
|
+
this.ensureDirectories();
|
|
228607
|
+
try {
|
|
228608
|
+
if (fs22.existsSync(this.CONFIG_FILE)) {
|
|
228609
|
+
console.log(`Security config already exists: ${this.CONFIG_FILE}`);
|
|
228610
|
+
return this.loadConfig();
|
|
228611
|
+
}
|
|
228612
|
+
const defaultConfig = { ...DEFAULT_SECURITY_CONFIG };
|
|
228613
|
+
const configContent = JSON.stringify(defaultConfig, null, 2);
|
|
228614
|
+
fs22.writeFileSync(this.CONFIG_FILE, configContent, { mode: 420 });
|
|
228615
|
+
console.log(`Initialized security config: ${this.CONFIG_FILE}`);
|
|
228616
|
+
console.log("Default config:", defaultConfig);
|
|
228617
|
+
return defaultConfig;
|
|
228618
|
+
} catch (error2) {
|
|
228619
|
+
console.warn(`Failed to initialize security config: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
228620
|
+
console.log("Using in-memory default config");
|
|
228621
|
+
return { ...DEFAULT_SECURITY_CONFIG };
|
|
228622
|
+
}
|
|
228623
|
+
}
|
|
228624
|
+
static loadConfig() {
|
|
228625
|
+
try {
|
|
228626
|
+
if (!fs22.existsSync(this.CONFIG_FILE)) {
|
|
228627
|
+
console.log("No security config file found, initializing...");
|
|
228628
|
+
return this.initializeConfig();
|
|
228629
|
+
}
|
|
228630
|
+
const configContent = fs22.readFileSync(this.CONFIG_FILE, "utf8");
|
|
228631
|
+
const config2 = JSON.parse(configContent);
|
|
228632
|
+
const mergedConfig = { ...DEFAULT_SECURITY_CONFIG, ...config2 };
|
|
228633
|
+
console.log(`Loaded security config from: ${this.CONFIG_FILE}`);
|
|
228634
|
+
return mergedConfig;
|
|
228635
|
+
} catch (error2) {
|
|
228636
|
+
console.warn(`Failed to load security config: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
228637
|
+
console.log("Using default config");
|
|
228638
|
+
return { ...DEFAULT_SECURITY_CONFIG };
|
|
228639
|
+
}
|
|
228640
|
+
}
|
|
228641
|
+
static saveConfig(config2) {
|
|
228642
|
+
this.ensureDirectories();
|
|
228643
|
+
try {
|
|
228644
|
+
const configToSave = { ...DEFAULT_SECURITY_CONFIG, ...config2 };
|
|
228645
|
+
const configContent = JSON.stringify(configToSave, null, 2);
|
|
228646
|
+
fs22.writeFileSync(this.CONFIG_FILE, configContent, { mode: 420 });
|
|
228647
|
+
console.log(`Saved security config to: ${this.CONFIG_FILE}`);
|
|
228648
|
+
return true;
|
|
228649
|
+
} catch (error2) {
|
|
228650
|
+
console.error(`Failed to save security config: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
228651
|
+
return false;
|
|
228652
|
+
}
|
|
228653
|
+
}
|
|
228654
|
+
static updateConfig(updates) {
|
|
228655
|
+
const currentConfig = this.loadConfig();
|
|
228656
|
+
const updatedConfig = { ...currentConfig, ...updates };
|
|
228657
|
+
if (this.saveConfig(updatedConfig)) {
|
|
228658
|
+
console.log("Security config updated:", updates);
|
|
228659
|
+
return updatedConfig;
|
|
228660
|
+
} else {
|
|
228661
|
+
console.warn("Failed to save updated config, returning current config");
|
|
228662
|
+
return currentConfig;
|
|
228663
|
+
}
|
|
228664
|
+
}
|
|
228665
|
+
static resetToDefaults() {
|
|
228666
|
+
const defaultConfig = { ...DEFAULT_SECURITY_CONFIG };
|
|
228667
|
+
if (this.saveConfig(defaultConfig)) {
|
|
228668
|
+
console.log("Security config reset to defaults");
|
|
228669
|
+
return defaultConfig;
|
|
228670
|
+
} else {
|
|
228671
|
+
console.warn("Failed to reset config");
|
|
228672
|
+
return this.loadConfig();
|
|
228673
|
+
}
|
|
228674
|
+
}
|
|
228675
|
+
static getPaths() {
|
|
228676
|
+
return {
|
|
228677
|
+
enactDir: this.ENACT_DIR,
|
|
228678
|
+
securityDir: this.SECURITY_DIR,
|
|
228679
|
+
configFile: this.CONFIG_FILE
|
|
228680
|
+
};
|
|
228681
|
+
}
|
|
228682
|
+
static configExists() {
|
|
228683
|
+
return fs22.existsSync(this.CONFIG_FILE);
|
|
228684
|
+
}
|
|
228685
|
+
static getStatus() {
|
|
228686
|
+
const paths = this.getPaths();
|
|
228687
|
+
return {
|
|
228688
|
+
enactDirExists: fs22.existsSync(paths.enactDir),
|
|
228689
|
+
securityDirExists: fs22.existsSync(paths.securityDir),
|
|
228690
|
+
configFileExists: fs22.existsSync(paths.configFile),
|
|
228691
|
+
paths
|
|
228692
|
+
};
|
|
228693
|
+
}
|
|
228694
|
+
static validateConfig(config2) {
|
|
228695
|
+
if (typeof config2 !== "object" || config2 === null) {
|
|
228696
|
+
return false;
|
|
228697
|
+
}
|
|
228698
|
+
if ("allowLocalUnsigned" in config2 && typeof config2.allowLocalUnsigned !== "boolean") {
|
|
228699
|
+
return false;
|
|
228700
|
+
}
|
|
228701
|
+
if ("minimumSignatures" in config2) {
|
|
228702
|
+
if (typeof config2.minimumSignatures !== "number" || config2.minimumSignatures < 0 || !Number.isInteger(config2.minimumSignatures)) {
|
|
228703
|
+
return false;
|
|
228704
|
+
}
|
|
228705
|
+
}
|
|
228706
|
+
return true;
|
|
228707
|
+
}
|
|
228708
|
+
static importConfig(filePath) {
|
|
228709
|
+
try {
|
|
228710
|
+
if (!fs22.existsSync(filePath)) {
|
|
228711
|
+
console.error(`Config file does not exist: ${filePath}`);
|
|
228712
|
+
return null;
|
|
228713
|
+
}
|
|
228714
|
+
const configContent = fs22.readFileSync(filePath, "utf8");
|
|
228715
|
+
const config2 = JSON.parse(configContent);
|
|
228716
|
+
if (!this.validateConfig(config2)) {
|
|
228717
|
+
console.error("Invalid config format");
|
|
228718
|
+
return null;
|
|
228719
|
+
}
|
|
228720
|
+
if (this.saveConfig(config2)) {
|
|
228721
|
+
console.log(`Imported config from: ${filePath}`);
|
|
228722
|
+
return config2;
|
|
228723
|
+
} else {
|
|
228724
|
+
console.error("Failed to save imported config");
|
|
228725
|
+
return null;
|
|
228726
|
+
}
|
|
228727
|
+
} catch (error2) {
|
|
228728
|
+
console.error(`Failed to import config: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
228729
|
+
return null;
|
|
228730
|
+
}
|
|
228731
|
+
}
|
|
228732
|
+
static exportConfig(filePath) {
|
|
228733
|
+
try {
|
|
228734
|
+
const config2 = this.loadConfig();
|
|
228735
|
+
const configContent = JSON.stringify(config2, null, 2);
|
|
228736
|
+
fs22.writeFileSync(filePath, configContent, { mode: 420 });
|
|
228737
|
+
console.log(`Exported config to: ${filePath}`);
|
|
228738
|
+
return true;
|
|
228739
|
+
} catch (error2) {
|
|
228740
|
+
console.error(`Failed to export config: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
228741
|
+
return false;
|
|
228742
|
+
}
|
|
228743
|
+
}
|
|
228744
|
+
}
|
|
228745
|
+
|
|
228584
228746
|
class SigningService {
|
|
228585
228747
|
static signDocument(document, privateKey, options = {}) {
|
|
228586
228748
|
const {
|
|
@@ -228607,14 +228769,15 @@ class SigningService {
|
|
|
228607
228769
|
timestamp: Date.now()
|
|
228608
228770
|
};
|
|
228609
228771
|
}
|
|
228610
|
-
static verifyDocument(document, signature, options = {}, securityConfig
|
|
228772
|
+
static verifyDocument(document, signature, options = {}, securityConfig) {
|
|
228611
228773
|
const {
|
|
228612
228774
|
useEnactDefaults = false,
|
|
228613
228775
|
includeFields,
|
|
228614
228776
|
excludeFields,
|
|
228615
228777
|
additionalCriticalFields
|
|
228616
228778
|
} = options;
|
|
228617
|
-
const
|
|
228779
|
+
const loadedConfig = securityConfig ?? SecurityConfigManager.loadConfig();
|
|
228780
|
+
const config2 = { ...DEFAULT_SECURITY_CONFIG, ...loadedConfig };
|
|
228618
228781
|
const signatures = document.signatures || [signature];
|
|
228619
228782
|
if (signatures.length < (config2.minimumSignatures ?? 1)) {
|
|
228620
228783
|
if (config2.allowLocalUnsigned && signatures.length === 0) {
|
|
@@ -228882,6 +229045,7 @@ class EnactCore {
|
|
|
228882
229045
|
}
|
|
228883
229046
|
}
|
|
228884
229047
|
async verifyTool(tool, dangerouslySkipVerification = false) {
|
|
229048
|
+
console.log("=== VERIFY TOOL CALLED ===", tool.name, "skipVerification:", dangerouslySkipVerification);
|
|
228885
229049
|
if (dangerouslySkipVerification) {
|
|
228886
229050
|
logger_default.warn(`Skipping signature verification for tool: ${tool.name}`);
|
|
228887
229051
|
return;
|
|
@@ -228890,22 +229054,32 @@ class EnactCore {
|
|
|
228890
229054
|
if (!tool.signatures || tool.signatures.length === 0) {
|
|
228891
229055
|
throw new Error(`Tool ${tool.name} does not have any signatures`);
|
|
228892
229056
|
}
|
|
229057
|
+
console.log("=== TOOL SIGNATURE DATA ===");
|
|
229058
|
+
console.log("Tool signatures from database:", JSON.stringify(tool.signatures, null, 2));
|
|
229059
|
+
console.log("Tool command:", tool.command);
|
|
228893
229060
|
const documentForVerification = {
|
|
228894
229061
|
command: tool.command
|
|
228895
229062
|
};
|
|
228896
229063
|
const referenceSignature = {
|
|
228897
229064
|
signature: tool.signatures[0].value,
|
|
228898
|
-
publicKey:
|
|
229065
|
+
publicKey: "",
|
|
228899
229066
|
algorithm: tool.signatures[0].algorithm,
|
|
228900
229067
|
timestamp: new Date(tool.signatures[0].created).getTime()
|
|
228901
229068
|
};
|
|
228902
229069
|
const canonicalDoc = SigningService.getCanonicalDocument(documentForVerification, { includeFields: ["command"] });
|
|
229070
|
+
console.log("=== SIGNATURE VERIFICATION DEBUG ===");
|
|
229071
|
+
console.log("Original document for verification:", JSON.stringify(documentForVerification, null, 2));
|
|
229072
|
+
console.log("Canonical document:", JSON.stringify(canonicalDoc, null, 2));
|
|
228903
229073
|
const docString = JSON.stringify(canonicalDoc);
|
|
228904
229074
|
const messageHash = CryptoUtils.hash(docString);
|
|
229075
|
+
console.log("Document string:", docString);
|
|
229076
|
+
console.log("Message hash:", messageHash);
|
|
229077
|
+
console.log("Reference signature object:", JSON.stringify(referenceSignature, null, 2));
|
|
228905
229078
|
const directVerify = CryptoUtils.verify(referenceSignature.publicKey, messageHash, referenceSignature.signature);
|
|
228906
|
-
console.log("Direct crypto verification result:", directVerify);
|
|
229079
|
+
console.log("KEITH DEBUG - Direct crypto verification result:", directVerify, "publicKey:", referenceSignature.publicKey);
|
|
228907
229080
|
const trustedKeys = KeyManager.getAllTrustedPublicKeys();
|
|
228908
229081
|
console.log("Trusted keys:", trustedKeys);
|
|
229082
|
+
console.log("Our referenceSignature.publicKey:", JSON.stringify(referenceSignature.publicKey));
|
|
228909
229083
|
console.log("Is our public key trusted?", trustedKeys.includes(referenceSignature.publicKey));
|
|
228910
229084
|
const isValid = SigningService.verifyDocument(documentForVerification, referenceSignature, { includeFields: ["command"] });
|
|
228911
229085
|
console.log("Final verification result:", isValid);
|
|
@@ -228924,7 +229098,15 @@ class EnactCore {
|
|
|
228924
229098
|
logger_default.info(`Executing tool: ${tool.name}`);
|
|
228925
229099
|
validateToolStructure(tool);
|
|
228926
229100
|
const validatedInputs = validateInputs(tool, inputs);
|
|
228927
|
-
|
|
229101
|
+
const config2 = SecurityConfigManager.loadConfig();
|
|
229102
|
+
if (options.isLocalFile && config2.allowLocalUnsigned) {
|
|
229103
|
+
logger_default.warn(`Executing local file without signature verification: ${tool.name} (you can disallow in your security config)`);
|
|
229104
|
+
}
|
|
229105
|
+
if (options.dangerouslySkipVerification) {
|
|
229106
|
+
logger_default.warn(`Skipping signature verification for tool: ${tool.name} because of dangerouslySkipVerification option`);
|
|
229107
|
+
}
|
|
229108
|
+
const skipVerification = options.isLocalFile && config2.allowLocalUnsigned || Boolean(options.dangerouslySkipVerification);
|
|
229109
|
+
await this.verifyTool(tool, skipVerification);
|
|
228928
229110
|
const { resolved: envVars } = await resolveToolEnvironmentVariables(tool.name, tool.env || {});
|
|
228929
229111
|
return await this.executionProvider.execute(tool, { ...validatedInputs, ...envVars }, {
|
|
228930
229112
|
vars: { ...envVars, ...validatedInputs },
|
package/dist/index.js.bak
CHANGED
|
@@ -37753,7 +37753,7 @@ var require_high_level_opt = __commonJS((exports, module) => {
|
|
|
37753
37753
|
]).reduce((set, kv) => (set[kv[0]] = kv[1], set), Object.create(null)) : {};
|
|
37754
37754
|
});
|
|
37755
37755
|
|
|
37756
|
-
// ../../node_modules/
|
|
37756
|
+
// ../../node_modules/minipass/index.js
|
|
37757
37757
|
var require_minipass = __commonJS((exports) => {
|
|
37758
37758
|
var proc = typeof process === "object" && process ? process : {
|
|
37759
37759
|
stdout: null,
|
|
@@ -215401,7 +215401,7 @@ command: "${command}"
|
|
|
215401
215401
|
}
|
|
215402
215402
|
function generateFullYaml(config2) {
|
|
215403
215403
|
let yaml = `# Enact Tool Definition
|
|
215404
|
-
# Generated by
|
|
215404
|
+
# Generated by @enactprotocol/cli
|
|
215405
215405
|
|
|
215406
215406
|
name: ${config2.name}
|
|
215407
215407
|
description: "${config2.description}"
|
|
@@ -226133,11 +226133,14 @@ class DaggerExecutionProvider extends ExecutionProvider {
|
|
|
226133
226133
|
init_env_loader();
|
|
226134
226134
|
var import_yaml = __toESM(require_dist(), 1);
|
|
226135
226135
|
|
|
226136
|
-
//
|
|
226136
|
+
// ../../node_modules/@enactprotocol/security/dist/index.js
|
|
226137
226137
|
import * as nc from "node:crypto";
|
|
226138
226138
|
import fs5 from "fs";
|
|
226139
226139
|
import path8 from "path";
|
|
226140
226140
|
import os5 from "os";
|
|
226141
|
+
import fs22 from "fs";
|
|
226142
|
+
import path22 from "path";
|
|
226143
|
+
import os22 from "os";
|
|
226141
226144
|
var crypto4 = nc && typeof nc === "object" && "webcrypto" in nc ? nc.webcrypto : nc && typeof nc === "object" && ("randomBytes" in nc) ? nc : undefined;
|
|
226142
226145
|
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
226143
226146
|
function isBytes(a) {
|
|
@@ -228580,6 +228583,165 @@ class KeyManager {
|
|
|
228580
228583
|
}
|
|
228581
228584
|
}
|
|
228582
228585
|
|
|
228586
|
+
class SecurityConfigManager {
|
|
228587
|
+
static ENACT_DIR = path22.join(os22.homedir(), ".enact");
|
|
228588
|
+
static SECURITY_DIR = path22.join(this.ENACT_DIR, "security");
|
|
228589
|
+
static CONFIG_FILE = path22.join(this.SECURITY_DIR, "config.json");
|
|
228590
|
+
static ensureDirectories() {
|
|
228591
|
+
try {
|
|
228592
|
+
if (!fs22.existsSync(this.ENACT_DIR)) {
|
|
228593
|
+
fs22.mkdirSync(this.ENACT_DIR, { recursive: true, mode: 493 });
|
|
228594
|
+
console.log(`Created .enact directory: ${this.ENACT_DIR}`);
|
|
228595
|
+
}
|
|
228596
|
+
if (!fs22.existsSync(this.SECURITY_DIR)) {
|
|
228597
|
+
fs22.mkdirSync(this.SECURITY_DIR, { recursive: true, mode: 493 });
|
|
228598
|
+
console.log(`Created security directory: ${this.SECURITY_DIR}`);
|
|
228599
|
+
}
|
|
228600
|
+
} catch (error2) {
|
|
228601
|
+
console.warn(`Failed to create directories: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
228602
|
+
}
|
|
228603
|
+
}
|
|
228604
|
+
static initializeConfig() {
|
|
228605
|
+
this.ensureDirectories();
|
|
228606
|
+
try {
|
|
228607
|
+
if (fs22.existsSync(this.CONFIG_FILE)) {
|
|
228608
|
+
console.log(`Security config already exists: ${this.CONFIG_FILE}`);
|
|
228609
|
+
return this.loadConfig();
|
|
228610
|
+
}
|
|
228611
|
+
const defaultConfig = { ...DEFAULT_SECURITY_CONFIG };
|
|
228612
|
+
const configContent = JSON.stringify(defaultConfig, null, 2);
|
|
228613
|
+
fs22.writeFileSync(this.CONFIG_FILE, configContent, { mode: 420 });
|
|
228614
|
+
console.log(`Initialized security config: ${this.CONFIG_FILE}`);
|
|
228615
|
+
console.log("Default config:", defaultConfig);
|
|
228616
|
+
return defaultConfig;
|
|
228617
|
+
} catch (error2) {
|
|
228618
|
+
console.warn(`Failed to initialize security config: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
228619
|
+
console.log("Using in-memory default config");
|
|
228620
|
+
return { ...DEFAULT_SECURITY_CONFIG };
|
|
228621
|
+
}
|
|
228622
|
+
}
|
|
228623
|
+
static loadConfig() {
|
|
228624
|
+
try {
|
|
228625
|
+
if (!fs22.existsSync(this.CONFIG_FILE)) {
|
|
228626
|
+
console.log("No security config file found, initializing...");
|
|
228627
|
+
return this.initializeConfig();
|
|
228628
|
+
}
|
|
228629
|
+
const configContent = fs22.readFileSync(this.CONFIG_FILE, "utf8");
|
|
228630
|
+
const config2 = JSON.parse(configContent);
|
|
228631
|
+
const mergedConfig = { ...DEFAULT_SECURITY_CONFIG, ...config2 };
|
|
228632
|
+
console.log(`Loaded security config from: ${this.CONFIG_FILE}`);
|
|
228633
|
+
return mergedConfig;
|
|
228634
|
+
} catch (error2) {
|
|
228635
|
+
console.warn(`Failed to load security config: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
228636
|
+
console.log("Using default config");
|
|
228637
|
+
return { ...DEFAULT_SECURITY_CONFIG };
|
|
228638
|
+
}
|
|
228639
|
+
}
|
|
228640
|
+
static saveConfig(config2) {
|
|
228641
|
+
this.ensureDirectories();
|
|
228642
|
+
try {
|
|
228643
|
+
const configToSave = { ...DEFAULT_SECURITY_CONFIG, ...config2 };
|
|
228644
|
+
const configContent = JSON.stringify(configToSave, null, 2);
|
|
228645
|
+
fs22.writeFileSync(this.CONFIG_FILE, configContent, { mode: 420 });
|
|
228646
|
+
console.log(`Saved security config to: ${this.CONFIG_FILE}`);
|
|
228647
|
+
return true;
|
|
228648
|
+
} catch (error2) {
|
|
228649
|
+
console.error(`Failed to save security config: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
228650
|
+
return false;
|
|
228651
|
+
}
|
|
228652
|
+
}
|
|
228653
|
+
static updateConfig(updates) {
|
|
228654
|
+
const currentConfig = this.loadConfig();
|
|
228655
|
+
const updatedConfig = { ...currentConfig, ...updates };
|
|
228656
|
+
if (this.saveConfig(updatedConfig)) {
|
|
228657
|
+
console.log("Security config updated:", updates);
|
|
228658
|
+
return updatedConfig;
|
|
228659
|
+
} else {
|
|
228660
|
+
console.warn("Failed to save updated config, returning current config");
|
|
228661
|
+
return currentConfig;
|
|
228662
|
+
}
|
|
228663
|
+
}
|
|
228664
|
+
static resetToDefaults() {
|
|
228665
|
+
const defaultConfig = { ...DEFAULT_SECURITY_CONFIG };
|
|
228666
|
+
if (this.saveConfig(defaultConfig)) {
|
|
228667
|
+
console.log("Security config reset to defaults");
|
|
228668
|
+
return defaultConfig;
|
|
228669
|
+
} else {
|
|
228670
|
+
console.warn("Failed to reset config");
|
|
228671
|
+
return this.loadConfig();
|
|
228672
|
+
}
|
|
228673
|
+
}
|
|
228674
|
+
static getPaths() {
|
|
228675
|
+
return {
|
|
228676
|
+
enactDir: this.ENACT_DIR,
|
|
228677
|
+
securityDir: this.SECURITY_DIR,
|
|
228678
|
+
configFile: this.CONFIG_FILE
|
|
228679
|
+
};
|
|
228680
|
+
}
|
|
228681
|
+
static configExists() {
|
|
228682
|
+
return fs22.existsSync(this.CONFIG_FILE);
|
|
228683
|
+
}
|
|
228684
|
+
static getStatus() {
|
|
228685
|
+
const paths = this.getPaths();
|
|
228686
|
+
return {
|
|
228687
|
+
enactDirExists: fs22.existsSync(paths.enactDir),
|
|
228688
|
+
securityDirExists: fs22.existsSync(paths.securityDir),
|
|
228689
|
+
configFileExists: fs22.existsSync(paths.configFile),
|
|
228690
|
+
paths
|
|
228691
|
+
};
|
|
228692
|
+
}
|
|
228693
|
+
static validateConfig(config2) {
|
|
228694
|
+
if (typeof config2 !== "object" || config2 === null) {
|
|
228695
|
+
return false;
|
|
228696
|
+
}
|
|
228697
|
+
if ("allowLocalUnsigned" in config2 && typeof config2.allowLocalUnsigned !== "boolean") {
|
|
228698
|
+
return false;
|
|
228699
|
+
}
|
|
228700
|
+
if ("minimumSignatures" in config2) {
|
|
228701
|
+
if (typeof config2.minimumSignatures !== "number" || config2.minimumSignatures < 0 || !Number.isInteger(config2.minimumSignatures)) {
|
|
228702
|
+
return false;
|
|
228703
|
+
}
|
|
228704
|
+
}
|
|
228705
|
+
return true;
|
|
228706
|
+
}
|
|
228707
|
+
static importConfig(filePath) {
|
|
228708
|
+
try {
|
|
228709
|
+
if (!fs22.existsSync(filePath)) {
|
|
228710
|
+
console.error(`Config file does not exist: ${filePath}`);
|
|
228711
|
+
return null;
|
|
228712
|
+
}
|
|
228713
|
+
const configContent = fs22.readFileSync(filePath, "utf8");
|
|
228714
|
+
const config2 = JSON.parse(configContent);
|
|
228715
|
+
if (!this.validateConfig(config2)) {
|
|
228716
|
+
console.error("Invalid config format");
|
|
228717
|
+
return null;
|
|
228718
|
+
}
|
|
228719
|
+
if (this.saveConfig(config2)) {
|
|
228720
|
+
console.log(`Imported config from: ${filePath}`);
|
|
228721
|
+
return config2;
|
|
228722
|
+
} else {
|
|
228723
|
+
console.error("Failed to save imported config");
|
|
228724
|
+
return null;
|
|
228725
|
+
}
|
|
228726
|
+
} catch (error2) {
|
|
228727
|
+
console.error(`Failed to import config: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
228728
|
+
return null;
|
|
228729
|
+
}
|
|
228730
|
+
}
|
|
228731
|
+
static exportConfig(filePath) {
|
|
228732
|
+
try {
|
|
228733
|
+
const config2 = this.loadConfig();
|
|
228734
|
+
const configContent = JSON.stringify(config2, null, 2);
|
|
228735
|
+
fs22.writeFileSync(filePath, configContent, { mode: 420 });
|
|
228736
|
+
console.log(`Exported config to: ${filePath}`);
|
|
228737
|
+
return true;
|
|
228738
|
+
} catch (error2) {
|
|
228739
|
+
console.error(`Failed to export config: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
228740
|
+
return false;
|
|
228741
|
+
}
|
|
228742
|
+
}
|
|
228743
|
+
}
|
|
228744
|
+
|
|
228583
228745
|
class SigningService {
|
|
228584
228746
|
static signDocument(document, privateKey, options = {}) {
|
|
228585
228747
|
const {
|
|
@@ -228606,14 +228768,15 @@ class SigningService {
|
|
|
228606
228768
|
timestamp: Date.now()
|
|
228607
228769
|
};
|
|
228608
228770
|
}
|
|
228609
|
-
static verifyDocument(document, signature, options = {}, securityConfig
|
|
228771
|
+
static verifyDocument(document, signature, options = {}, securityConfig) {
|
|
228610
228772
|
const {
|
|
228611
228773
|
useEnactDefaults = false,
|
|
228612
228774
|
includeFields,
|
|
228613
228775
|
excludeFields,
|
|
228614
228776
|
additionalCriticalFields
|
|
228615
228777
|
} = options;
|
|
228616
|
-
const
|
|
228778
|
+
const loadedConfig = securityConfig ?? SecurityConfigManager.loadConfig();
|
|
228779
|
+
const config2 = { ...DEFAULT_SECURITY_CONFIG, ...loadedConfig };
|
|
228617
228780
|
const signatures = document.signatures || [signature];
|
|
228618
228781
|
if (signatures.length < (config2.minimumSignatures ?? 1)) {
|
|
228619
228782
|
if (config2.allowLocalUnsigned && signatures.length === 0) {
|
|
@@ -228881,6 +229044,7 @@ class EnactCore {
|
|
|
228881
229044
|
}
|
|
228882
229045
|
}
|
|
228883
229046
|
async verifyTool(tool, dangerouslySkipVerification = false) {
|
|
229047
|
+
console.log("=== VERIFY TOOL CALLED ===", tool.name, "skipVerification:", dangerouslySkipVerification);
|
|
228884
229048
|
if (dangerouslySkipVerification) {
|
|
228885
229049
|
logger_default.warn(`Skipping signature verification for tool: ${tool.name}`);
|
|
228886
229050
|
return;
|
|
@@ -228889,22 +229053,32 @@ class EnactCore {
|
|
|
228889
229053
|
if (!tool.signatures || tool.signatures.length === 0) {
|
|
228890
229054
|
throw new Error(`Tool ${tool.name} does not have any signatures`);
|
|
228891
229055
|
}
|
|
229056
|
+
console.log("=== TOOL SIGNATURE DATA ===");
|
|
229057
|
+
console.log("Tool signatures from database:", JSON.stringify(tool.signatures, null, 2));
|
|
229058
|
+
console.log("Tool command:", tool.command);
|
|
228892
229059
|
const documentForVerification = {
|
|
228893
229060
|
command: tool.command
|
|
228894
229061
|
};
|
|
228895
229062
|
const referenceSignature = {
|
|
228896
229063
|
signature: tool.signatures[0].value,
|
|
228897
|
-
publicKey:
|
|
229064
|
+
publicKey: "",
|
|
228898
229065
|
algorithm: tool.signatures[0].algorithm,
|
|
228899
229066
|
timestamp: new Date(tool.signatures[0].created).getTime()
|
|
228900
229067
|
};
|
|
228901
229068
|
const canonicalDoc = SigningService.getCanonicalDocument(documentForVerification, { includeFields: ["command"] });
|
|
229069
|
+
console.log("=== SIGNATURE VERIFICATION DEBUG ===");
|
|
229070
|
+
console.log("Original document for verification:", JSON.stringify(documentForVerification, null, 2));
|
|
229071
|
+
console.log("Canonical document:", JSON.stringify(canonicalDoc, null, 2));
|
|
228902
229072
|
const docString = JSON.stringify(canonicalDoc);
|
|
228903
229073
|
const messageHash = CryptoUtils.hash(docString);
|
|
229074
|
+
console.log("Document string:", docString);
|
|
229075
|
+
console.log("Message hash:", messageHash);
|
|
229076
|
+
console.log("Reference signature object:", JSON.stringify(referenceSignature, null, 2));
|
|
228904
229077
|
const directVerify = CryptoUtils.verify(referenceSignature.publicKey, messageHash, referenceSignature.signature);
|
|
228905
|
-
console.log("Direct crypto verification result:", directVerify);
|
|
229078
|
+
console.log("KEITH DEBUG - Direct crypto verification result:", directVerify, "publicKey:", referenceSignature.publicKey);
|
|
228906
229079
|
const trustedKeys = KeyManager.getAllTrustedPublicKeys();
|
|
228907
229080
|
console.log("Trusted keys:", trustedKeys);
|
|
229081
|
+
console.log("Our referenceSignature.publicKey:", JSON.stringify(referenceSignature.publicKey));
|
|
228908
229082
|
console.log("Is our public key trusted?", trustedKeys.includes(referenceSignature.publicKey));
|
|
228909
229083
|
const isValid = SigningService.verifyDocument(documentForVerification, referenceSignature, { includeFields: ["command"] });
|
|
228910
229084
|
console.log("Final verification result:", isValid);
|
|
@@ -228923,7 +229097,15 @@ class EnactCore {
|
|
|
228923
229097
|
logger_default.info(`Executing tool: ${tool.name}`);
|
|
228924
229098
|
validateToolStructure(tool);
|
|
228925
229099
|
const validatedInputs = validateInputs(tool, inputs);
|
|
228926
|
-
|
|
229100
|
+
const config2 = SecurityConfigManager.loadConfig();
|
|
229101
|
+
if (options.isLocalFile && config2.allowLocalUnsigned) {
|
|
229102
|
+
logger_default.warn(`Executing local file without signature verification: ${tool.name} (you can disallow in your security config)`);
|
|
229103
|
+
}
|
|
229104
|
+
if (options.dangerouslySkipVerification) {
|
|
229105
|
+
logger_default.warn(`Skipping signature verification for tool: ${tool.name} because of dangerouslySkipVerification option`);
|
|
229106
|
+
}
|
|
229107
|
+
const skipVerification = options.isLocalFile && config2.allowLocalUnsigned || Boolean(options.dangerouslySkipVerification);
|
|
229108
|
+
await this.verifyTool(tool, skipVerification);
|
|
228927
229109
|
const { resolved: envVars } = await resolveToolEnvironmentVariables(tool.name, tool.env || {});
|
|
228928
229110
|
return await this.executionProvider.execute(tool, { ...validatedInputs, ...envVars }, {
|
|
228929
229111
|
vars: { ...envVars, ...validatedInputs },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enactprotocol/cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Official CLI for the Enact Protocol - package, secure, and discover AI tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"node": ">=18.0.0"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@enactprotocol/shared": "1.2.
|
|
45
|
+
"@enactprotocol/shared": "1.2.2",
|
|
46
46
|
"@clack/core": "^0.4.2",
|
|
47
47
|
"@clack/prompts": "^0.10.1",
|
|
48
48
|
"picocolors": "^1.1.1"
|