matimo 0.1.0-alpha.8 → 0.1.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/package.json +10 -8
- package/packages/cli/dist/bin.d.ts +3 -0
- package/packages/cli/dist/bin.d.ts.map +1 -0
- package/packages/cli/dist/bin.js +50 -0
- package/packages/cli/dist/bin.js.map +1 -0
- package/packages/cli/dist/cli.d.ts.map +1 -1
- package/packages/cli/dist/cli.js +64 -2
- package/packages/cli/dist/cli.js.map +1 -1
- package/packages/cli/dist/commands/doctor.d.ts +2 -0
- package/packages/cli/dist/commands/doctor.d.ts.map +1 -0
- package/packages/cli/dist/commands/doctor.js +174 -0
- package/packages/cli/dist/commands/doctor.js.map +1 -0
- package/packages/cli/dist/commands/mcp-setup.d.ts +9 -0
- package/packages/cli/dist/commands/mcp-setup.d.ts.map +1 -0
- package/packages/cli/dist/commands/mcp-setup.js +106 -0
- package/packages/cli/dist/commands/mcp-setup.js.map +1 -0
- package/packages/cli/dist/commands/mcp.d.ts +17 -0
- package/packages/cli/dist/commands/mcp.d.ts.map +1 -0
- package/packages/cli/dist/commands/mcp.js +228 -0
- package/packages/cli/dist/commands/mcp.js.map +1 -0
- package/packages/cli/dist/commands/review.d.ts +10 -0
- package/packages/cli/dist/commands/review.d.ts.map +1 -0
- package/packages/cli/dist/commands/review.js +176 -0
- package/packages/cli/dist/commands/review.js.map +1 -0
- package/packages/core/dist/approval/approval-handler.d.ts +5 -1
- package/packages/core/dist/approval/approval-handler.d.ts.map +1 -1
- package/packages/core/dist/approval/approval-handler.js +6 -0
- package/packages/core/dist/approval/approval-handler.js.map +1 -1
- package/packages/core/dist/core/schema.d.ts +41 -10
- package/packages/core/dist/core/schema.d.ts.map +1 -1
- package/packages/core/dist/core/schema.js +40 -4
- package/packages/core/dist/core/schema.js.map +1 -1
- package/packages/core/dist/core/skill-content-parser.d.ts +91 -0
- package/packages/core/dist/core/skill-content-parser.d.ts.map +1 -0
- package/packages/core/dist/core/skill-content-parser.js +248 -0
- package/packages/core/dist/core/skill-content-parser.js.map +1 -0
- package/packages/core/dist/core/skill-loader.d.ts +46 -0
- package/packages/core/dist/core/skill-loader.d.ts.map +1 -0
- package/packages/core/dist/core/skill-loader.js +310 -0
- package/packages/core/dist/core/skill-loader.js.map +1 -0
- package/packages/core/dist/core/skill-registry.d.ts +131 -0
- package/packages/core/dist/core/skill-registry.d.ts.map +1 -0
- package/packages/core/dist/core/skill-registry.js +316 -0
- package/packages/core/dist/core/skill-registry.js.map +1 -0
- package/packages/core/dist/core/tfidf-embedding.d.ts +45 -0
- package/packages/core/dist/core/tfidf-embedding.d.ts.map +1 -0
- package/packages/core/dist/core/tfidf-embedding.js +199 -0
- package/packages/core/dist/core/tfidf-embedding.js.map +1 -0
- package/packages/core/dist/core/tool-loader.d.ts +3 -1
- package/packages/core/dist/core/tool-loader.d.ts.map +1 -1
- package/packages/core/dist/core/tool-loader.js +33 -10
- package/packages/core/dist/core/tool-loader.js.map +1 -1
- package/packages/core/dist/core/types.d.ts +203 -6
- package/packages/core/dist/core/types.d.ts.map +1 -1
- package/packages/core/dist/encodings/parameter-encoding.d.ts +1 -1
- package/packages/core/dist/encodings/parameter-encoding.d.ts.map +1 -1
- package/packages/core/dist/encodings/parameter-encoding.js +9 -4
- package/packages/core/dist/encodings/parameter-encoding.js.map +1 -1
- package/packages/core/dist/errors/matimo-error.d.ts +11 -2
- package/packages/core/dist/errors/matimo-error.d.ts.map +1 -1
- package/packages/core/dist/errors/matimo-error.js +25 -1
- package/packages/core/dist/errors/matimo-error.js.map +1 -1
- package/packages/core/dist/executors/command-executor.d.ts +9 -2
- package/packages/core/dist/executors/command-executor.d.ts.map +1 -1
- package/packages/core/dist/executors/command-executor.js +29 -5
- package/packages/core/dist/executors/command-executor.js.map +1 -1
- package/packages/core/dist/executors/function-executor.d.ts +10 -3
- package/packages/core/dist/executors/function-executor.d.ts.map +1 -1
- package/packages/core/dist/executors/function-executor.js +44 -24
- package/packages/core/dist/executors/function-executor.js.map +1 -1
- package/packages/core/dist/executors/http-executor.d.ts +79 -4
- package/packages/core/dist/executors/http-executor.d.ts.map +1 -1
- package/packages/core/dist/executors/http-executor.js +232 -28
- package/packages/core/dist/executors/http-executor.js.map +1 -1
- package/packages/core/dist/index.d.ts +25 -3
- package/packages/core/dist/index.d.ts.map +1 -1
- package/packages/core/dist/index.js +19 -1
- package/packages/core/dist/index.js.map +1 -1
- package/packages/core/dist/integrations/langchain.d.ts +55 -0
- package/packages/core/dist/integrations/langchain.d.ts.map +1 -1
- package/packages/core/dist/integrations/langchain.js +71 -4
- package/packages/core/dist/integrations/langchain.js.map +1 -1
- package/packages/core/dist/logging/logger.d.ts +8 -2
- package/packages/core/dist/logging/logger.d.ts.map +1 -1
- package/packages/core/dist/logging/logger.js.map +1 -1
- package/packages/core/dist/logging/winston-logger.d.ts.map +1 -1
- package/packages/core/dist/logging/winston-logger.js +9 -1
- package/packages/core/dist/logging/winston-logger.js.map +1 -1
- package/packages/core/dist/matimo-instance.d.ts +230 -18
- package/packages/core/dist/matimo-instance.d.ts.map +1 -1
- package/packages/core/dist/matimo-instance.js +739 -40
- package/packages/core/dist/matimo-instance.js.map +1 -1
- package/packages/core/dist/mcp/index.d.ts +18 -0
- package/packages/core/dist/mcp/index.d.ts.map +1 -0
- package/packages/core/dist/mcp/index.js +24 -0
- package/packages/core/dist/mcp/index.js.map +1 -0
- package/packages/core/dist/mcp/mcp-server.d.ts +141 -0
- package/packages/core/dist/mcp/mcp-server.d.ts.map +1 -0
- package/packages/core/dist/mcp/mcp-server.js +754 -0
- package/packages/core/dist/mcp/mcp-server.js.map +1 -0
- package/packages/core/dist/mcp/secrets/aws-resolver.d.ts +41 -0
- package/packages/core/dist/mcp/secrets/aws-resolver.d.ts.map +1 -0
- package/packages/core/dist/mcp/secrets/aws-resolver.js +141 -0
- package/packages/core/dist/mcp/secrets/aws-resolver.js.map +1 -0
- package/packages/core/dist/mcp/secrets/dotenv-resolver.d.ts +23 -0
- package/packages/core/dist/mcp/secrets/dotenv-resolver.d.ts.map +1 -0
- package/packages/core/dist/mcp/secrets/dotenv-resolver.js +94 -0
- package/packages/core/dist/mcp/secrets/dotenv-resolver.js.map +1 -0
- package/packages/core/dist/mcp/secrets/env-resolver.d.ts +14 -0
- package/packages/core/dist/mcp/secrets/env-resolver.d.ts.map +1 -0
- package/packages/core/dist/mcp/secrets/env-resolver.js +27 -0
- package/packages/core/dist/mcp/secrets/env-resolver.js.map +1 -0
- package/packages/core/dist/mcp/secrets/index.d.ts +14 -0
- package/packages/core/dist/mcp/secrets/index.d.ts.map +1 -0
- package/packages/core/dist/mcp/secrets/index.js +13 -0
- package/packages/core/dist/mcp/secrets/index.js.map +1 -0
- package/packages/core/dist/mcp/secrets/resolver-chain.d.ts +34 -0
- package/packages/core/dist/mcp/secrets/resolver-chain.d.ts.map +1 -0
- package/packages/core/dist/mcp/secrets/resolver-chain.js +141 -0
- package/packages/core/dist/mcp/secrets/resolver-chain.js.map +1 -0
- package/packages/core/dist/mcp/secrets/types.d.ts +73 -0
- package/packages/core/dist/mcp/secrets/types.d.ts.map +1 -0
- package/packages/core/dist/mcp/secrets/types.js +8 -0
- package/packages/core/dist/mcp/secrets/types.js.map +1 -0
- package/packages/core/dist/mcp/secrets/vault-resolver.d.ts +43 -0
- package/packages/core/dist/mcp/secrets/vault-resolver.d.ts.map +1 -0
- package/packages/core/dist/mcp/secrets/vault-resolver.js +127 -0
- package/packages/core/dist/mcp/secrets/vault-resolver.js.map +1 -0
- package/packages/core/dist/mcp/tool-converter.d.ts +40 -0
- package/packages/core/dist/mcp/tool-converter.d.ts.map +1 -0
- package/packages/core/dist/mcp/tool-converter.js +185 -0
- package/packages/core/dist/mcp/tool-converter.js.map +1 -0
- package/packages/core/dist/policy/approval-manifest.d.ts +76 -0
- package/packages/core/dist/policy/approval-manifest.d.ts.map +1 -0
- package/packages/core/dist/policy/approval-manifest.js +197 -0
- package/packages/core/dist/policy/approval-manifest.js.map +1 -0
- package/packages/core/dist/policy/content-validator.d.ts +19 -0
- package/packages/core/dist/policy/content-validator.d.ts.map +1 -0
- package/packages/core/dist/policy/content-validator.js +196 -0
- package/packages/core/dist/policy/content-validator.js.map +1 -0
- package/packages/core/dist/policy/default-policy.d.ts +46 -0
- package/packages/core/dist/policy/default-policy.d.ts.map +1 -0
- package/packages/core/dist/policy/default-policy.js +241 -0
- package/packages/core/dist/policy/default-policy.js.map +1 -0
- package/packages/core/dist/policy/events.d.ts +71 -0
- package/packages/core/dist/policy/events.d.ts.map +1 -0
- package/packages/core/dist/policy/events.js +8 -0
- package/packages/core/dist/policy/events.js.map +1 -0
- package/packages/core/dist/policy/index.d.ts +13 -0
- package/packages/core/dist/policy/index.d.ts.map +1 -0
- package/packages/core/dist/policy/index.js +9 -0
- package/packages/core/dist/policy/index.js.map +1 -0
- package/packages/core/dist/policy/integrity-tracker.d.ts +62 -0
- package/packages/core/dist/policy/integrity-tracker.d.ts.map +1 -0
- package/packages/core/dist/policy/integrity-tracker.js +79 -0
- package/packages/core/dist/policy/integrity-tracker.js.map +1 -0
- package/packages/core/dist/policy/policy-loader.d.ts +58 -0
- package/packages/core/dist/policy/policy-loader.d.ts.map +1 -0
- package/packages/core/dist/policy/policy-loader.js +156 -0
- package/packages/core/dist/policy/policy-loader.js.map +1 -0
- package/packages/core/dist/policy/risk-classifier.d.ts +18 -0
- package/packages/core/dist/policy/risk-classifier.d.ts.map +1 -0
- package/packages/core/dist/policy/risk-classifier.js +47 -0
- package/packages/core/dist/policy/risk-classifier.js.map +1 -0
- package/packages/core/dist/policy/types.d.ts +131 -0
- package/packages/core/dist/policy/types.d.ts.map +1 -0
- package/packages/core/dist/policy/types.js +8 -0
- package/packages/core/dist/policy/types.js.map +1 -0
- package/LICENSE +0 -21
- package/README.md +0 -243
- package/packages/cli/bin/matimo.cjs +0 -26
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Approval Manifest for Matimo.
|
|
3
|
+
*
|
|
4
|
+
* Manages HMAC-signed approval records for agent-created tools.
|
|
5
|
+
* Prevents agent forgery of approvals via cryptographic verification.
|
|
6
|
+
*/
|
|
7
|
+
import { createHmac, randomUUID, createHash } from 'crypto';
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { MatimoError, ErrorCode } from '../errors/matimo-error';
|
|
11
|
+
import { getGlobalMatimoLogger } from '../logging';
|
|
12
|
+
export class ApprovalManifest {
|
|
13
|
+
/**
|
|
14
|
+
* @param approvalDir - Directory where `.matimo-approvals.json` lives
|
|
15
|
+
* @param secret - HMAC secret. If not provided, reads `MATIMO_APPROVAL_SECRET`
|
|
16
|
+
* from env. If that's also missing, generates one and logs it.
|
|
17
|
+
* @param ttlSeconds - Optional TTL in seconds. Approvals older than this are treated as expired.
|
|
18
|
+
*/
|
|
19
|
+
constructor(approvalDir, secret, ttlSeconds) {
|
|
20
|
+
this.cache = new Map();
|
|
21
|
+
this.pendingSet = new Set();
|
|
22
|
+
this.ttlSeconds = ttlSeconds;
|
|
23
|
+
this.manifestPath = path.join(approvalDir, '.matimo-approvals.json');
|
|
24
|
+
if (secret) {
|
|
25
|
+
this.secret = secret;
|
|
26
|
+
}
|
|
27
|
+
else if (process.env.MATIMO_APPROVAL_SECRET) {
|
|
28
|
+
this.secret = process.env.MATIMO_APPROVAL_SECRET;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
if (process.env.NODE_ENV === 'production' || process.env.MATIMO_ENV === 'production') {
|
|
32
|
+
throw new MatimoError('MATIMO_APPROVAL_SECRET is required in production environments. ' +
|
|
33
|
+
'Set it to a stable, securely generated value (e.g. from a secrets manager).', ErrorCode.AUTH_FAILED);
|
|
34
|
+
}
|
|
35
|
+
this.secret = randomUUID();
|
|
36
|
+
const logger = getGlobalMatimoLogger();
|
|
37
|
+
// Create a non-sensitive fingerprint for debugging (first 4 chars only)
|
|
38
|
+
const fingerprint = this.secret.substring(0, 4);
|
|
39
|
+
logger.warn('No MATIMO_APPROVAL_SECRET set. An ephemeral secret was auto-generated ' +
|
|
40
|
+
'(fingerprint: ' +
|
|
41
|
+
fingerprint +
|
|
42
|
+
'...) ' +
|
|
43
|
+
'for this process. Approvals may not persist across restarts. ' +
|
|
44
|
+
'To persist approvals, set MATIMO_APPROVAL_SECRET to a stable, securely ' +
|
|
45
|
+
'generated value in the environment.');
|
|
46
|
+
}
|
|
47
|
+
this.loadFromDisk();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Compute the HMAC signature for a tool approval.
|
|
51
|
+
*/
|
|
52
|
+
sign(toolName, yamlHash) {
|
|
53
|
+
return createHmac('sha256', this.secret).update(`${toolName}:${yamlHash}`).digest('hex');
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Compute SHA-256 hash of content.
|
|
57
|
+
*/
|
|
58
|
+
computeHash(content) {
|
|
59
|
+
return createHash('sha256').update(content, 'utf8').digest('hex');
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Verify that an approval record has a valid HMAC signature and
|
|
63
|
+
* the stored hash matches the current YAML content hash.
|
|
64
|
+
*/
|
|
65
|
+
isApproved(toolName, currentYamlHash) {
|
|
66
|
+
const record = this.cache.get(toolName);
|
|
67
|
+
if (!record)
|
|
68
|
+
return false;
|
|
69
|
+
// Hash mismatch = YAML was modified after approval → revoked
|
|
70
|
+
if (record.hash !== currentYamlHash)
|
|
71
|
+
return false;
|
|
72
|
+
// TTL check — if configured, reject approvals older than ttlSeconds
|
|
73
|
+
if (this.ttlSeconds !== undefined) {
|
|
74
|
+
// Fail closed if timestamp is missing or unparsable
|
|
75
|
+
if (!record.approvedAt)
|
|
76
|
+
return false;
|
|
77
|
+
const approvedAt = new Date(record.approvedAt).getTime();
|
|
78
|
+
if (!Number.isFinite(approvedAt))
|
|
79
|
+
return false;
|
|
80
|
+
const ageMs = Date.now() - approvedAt;
|
|
81
|
+
if (ageMs > this.ttlSeconds * 1000)
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
// Verify HMAC to detect manifest tampering
|
|
85
|
+
const expectedSig = this.sign(toolName, record.hash);
|
|
86
|
+
return record.signature === expectedSig;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Approve a tool. Creates an HMAC-signed record in the manifest.
|
|
90
|
+
*/
|
|
91
|
+
approve(toolName, yamlHash, approvedBy) {
|
|
92
|
+
const signature = this.sign(toolName, yamlHash);
|
|
93
|
+
const record = {
|
|
94
|
+
name: toolName,
|
|
95
|
+
hash: yamlHash,
|
|
96
|
+
signature,
|
|
97
|
+
approvedAt: new Date().toISOString(),
|
|
98
|
+
approvedBy,
|
|
99
|
+
};
|
|
100
|
+
this.cache.set(toolName, record);
|
|
101
|
+
this.saveToDisk();
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Revoke a tool's approval. Removes from both cache and pendingSet
|
|
105
|
+
* to ensure consistent state (tool no longer tracked as approved or pending).
|
|
106
|
+
*/
|
|
107
|
+
revoke(toolName) {
|
|
108
|
+
const cacheDeleted = this.cache.delete(toolName);
|
|
109
|
+
const pendingDeleted = this.pendingSet.delete(toolName);
|
|
110
|
+
if (cacheDeleted || pendingDeleted) {
|
|
111
|
+
this.saveToDisk();
|
|
112
|
+
}
|
|
113
|
+
return cacheDeleted || pendingDeleted;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Get the approval record for a tool.
|
|
117
|
+
*/
|
|
118
|
+
getApproval(toolName) {
|
|
119
|
+
return this.cache.get(toolName);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* List all approved tool names.
|
|
123
|
+
*/
|
|
124
|
+
listApproved() {
|
|
125
|
+
return Array.from(this.cache.keys());
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Mark a tool as pending approval. Called by matimo_create_tool after writing to disk.
|
|
129
|
+
*/
|
|
130
|
+
markPending(toolName) {
|
|
131
|
+
this.pendingSet.add(toolName);
|
|
132
|
+
this.saveToDisk();
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Return all tool names that have been proposed (written to disk) but not yet approved.
|
|
136
|
+
*/
|
|
137
|
+
getPendingTools() {
|
|
138
|
+
return Array.from(this.pendingSet).filter((name) => !this.cache.has(name));
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Load the manifest file from disk.
|
|
142
|
+
*/
|
|
143
|
+
loadFromDisk() {
|
|
144
|
+
try {
|
|
145
|
+
if (!fs.existsSync(this.manifestPath))
|
|
146
|
+
return;
|
|
147
|
+
const raw = fs.readFileSync(this.manifestPath, 'utf-8');
|
|
148
|
+
const data = JSON.parse(raw);
|
|
149
|
+
if (data.version !== '1' || !Array.isArray(data.approvals))
|
|
150
|
+
return;
|
|
151
|
+
this.cache.clear();
|
|
152
|
+
for (const record of data.approvals) {
|
|
153
|
+
if (record.name && record.hash && record.signature) {
|
|
154
|
+
this.cache.set(record.name, record);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
this.pendingSet.clear();
|
|
158
|
+
if (Array.isArray(data.pending)) {
|
|
159
|
+
for (const name of data.pending) {
|
|
160
|
+
if (typeof name === 'string')
|
|
161
|
+
this.pendingSet.add(name);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// Corrupted manifest — start fresh
|
|
167
|
+
const logger = getGlobalMatimoLogger();
|
|
168
|
+
logger.warn('Failed to load approval manifest, starting fresh', {
|
|
169
|
+
path: this.manifestPath,
|
|
170
|
+
});
|
|
171
|
+
this.cache.clear();
|
|
172
|
+
this.pendingSet.clear();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Save current approvals to disk using atomic write pattern.
|
|
177
|
+
* Writes to a temporary file first, then atomically renames it.
|
|
178
|
+
* This prevents data corruption if the process crashes mid-write.
|
|
179
|
+
*/
|
|
180
|
+
saveToDisk() {
|
|
181
|
+
const data = {
|
|
182
|
+
version: '1',
|
|
183
|
+
approvals: Array.from(this.cache.values()),
|
|
184
|
+
pending: Array.from(this.pendingSet).filter((name) => !this.cache.has(name)),
|
|
185
|
+
};
|
|
186
|
+
const dir = path.dirname(this.manifestPath);
|
|
187
|
+
if (!fs.existsSync(dir)) {
|
|
188
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
189
|
+
}
|
|
190
|
+
// Atomic write: write to temp file, then rename
|
|
191
|
+
const json = JSON.stringify(data, null, 2);
|
|
192
|
+
const tempPath = path.join(dir, `${path.basename(this.manifestPath)}.tmp-${process.pid}-${Date.now()}`);
|
|
193
|
+
fs.writeFileSync(tempPath, json, 'utf-8');
|
|
194
|
+
fs.renameSync(tempPath, this.manifestPath);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=approval-manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-manifest.js","sourceRoot":"","sources":["../../src/policy/approval-manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content Validator for Matimo tools.
|
|
3
|
+
*
|
|
4
|
+
* Deterministic structural rules that detect malicious or unsafe patterns
|
|
5
|
+
* in agent-created tool definitions. No LLM involved.
|
|
6
|
+
*/
|
|
7
|
+
import type { ToolDefinition } from '../core/schema';
|
|
8
|
+
import type { ValidationResult, ValidationContext } from './types';
|
|
9
|
+
/**
|
|
10
|
+
* Validate a tool definition against content safety rules.
|
|
11
|
+
* Returns all violations found (does not short-circuit).
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateToolContent(tool: ToolDefinition, context: ValidationContext): ValidationResult;
|
|
14
|
+
/**
|
|
15
|
+
* Check if a URL targets an internal/metadata network (SSRF protection).
|
|
16
|
+
* Handles IPv4, IPv6, and common internal hostnames.
|
|
17
|
+
*/
|
|
18
|
+
export declare function isSSRFTarget(url: string): boolean;
|
|
19
|
+
//# sourceMappingURL=content-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-validator.d.ts","sourceRoot":"","sources":["../../src/policy/content-validator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAa,MAAM,SAAS,CAAC;AAM9E;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,iBAAiB,GACzB,gBAAgB,CAqHlB;AAkBD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CA4CjD"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content Validator for Matimo tools.
|
|
3
|
+
*
|
|
4
|
+
* Deterministic structural rules that detect malicious or unsafe patterns
|
|
5
|
+
* in agent-created tool definitions. No LLM involved.
|
|
6
|
+
*/
|
|
7
|
+
import { extractAuthPlaceholders } from '../mcp/tool-converter';
|
|
8
|
+
const DEFAULT_ALLOWED_HTTP_METHODS = ['GET', 'POST'];
|
|
9
|
+
const DEFAULT_PROTECTED_NAMESPACES = ['matimo_'];
|
|
10
|
+
/**
|
|
11
|
+
* Validate a tool definition against content safety rules.
|
|
12
|
+
* Returns all violations found (does not short-circuit).
|
|
13
|
+
*/
|
|
14
|
+
export function validateToolContent(tool, context) {
|
|
15
|
+
const violations = [];
|
|
16
|
+
const config = context.policy ?? {};
|
|
17
|
+
// Only apply restrictive rules to untrusted sources
|
|
18
|
+
if (context.source !== 'untrusted') {
|
|
19
|
+
return { valid: true, violations: [] };
|
|
20
|
+
}
|
|
21
|
+
// Rule 1: Block execution type: function (arbitrary code)
|
|
22
|
+
if (tool.execution.type === 'function') {
|
|
23
|
+
if (!config.allowFunctionTools) {
|
|
24
|
+
violations.push({
|
|
25
|
+
rule: 'no-function-execution',
|
|
26
|
+
severity: 'critical',
|
|
27
|
+
message: 'Agent-created tools cannot use execution type "function" (arbitrary code execution)',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Rule 2: Block execution type: command (shell injection)
|
|
32
|
+
if (tool.execution.type === 'command') {
|
|
33
|
+
if (!config.allowCommandTools) {
|
|
34
|
+
violations.push({
|
|
35
|
+
rule: 'no-command-execution',
|
|
36
|
+
severity: 'critical',
|
|
37
|
+
message: 'Agent-created tools cannot use execution type "command" (shell injection risk)',
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Rule 3: Block SSRF targets in HTTP URLs
|
|
42
|
+
if (tool.execution.type === 'http') {
|
|
43
|
+
const url = tool.execution.url;
|
|
44
|
+
if (isSSRFTarget(url)) {
|
|
45
|
+
violations.push({
|
|
46
|
+
rule: 'no-ssrf',
|
|
47
|
+
severity: 'critical',
|
|
48
|
+
message: `URL targets internal/metadata network: ${url}`,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Rule 4: Block unauthorized credential references
|
|
53
|
+
if (config.allowedCredentials && config.allowedCredentials.length > 0) {
|
|
54
|
+
const referencedVars = extractAuthPlaceholders(tool);
|
|
55
|
+
for (const envVar of referencedVars) {
|
|
56
|
+
if (!config.allowedCredentials.includes(envVar)) {
|
|
57
|
+
violations.push({
|
|
58
|
+
rule: 'unauthorized-credential',
|
|
59
|
+
severity: 'high',
|
|
60
|
+
message: `Tool references credential "${envVar}" not in allowlist`,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Rule 5: Block reserved namespaces
|
|
66
|
+
const namespaces = config.protectedNamespaces ?? DEFAULT_PROTECTED_NAMESPACES;
|
|
67
|
+
for (const ns of namespaces) {
|
|
68
|
+
if (tool.name.startsWith(ns)) {
|
|
69
|
+
violations.push({
|
|
70
|
+
rule: 'reserved-namespace',
|
|
71
|
+
severity: 'critical',
|
|
72
|
+
message: `Tool name prefix "${ns}" is reserved for built-in tools`,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Rule 6: Force requires_approval on agent-created tools
|
|
77
|
+
if (tool.requires_approval === false || tool.requires_approval === undefined) {
|
|
78
|
+
violations.push({
|
|
79
|
+
rule: 'forced-approval',
|
|
80
|
+
severity: 'high',
|
|
81
|
+
message: 'Agent-created tools must have requires_approval: true',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
// Rule 7: Block disallowed HTTP methods
|
|
85
|
+
if (tool.execution.type === 'http') {
|
|
86
|
+
const allowed = config.allowedHttpMethods ?? DEFAULT_ALLOWED_HTTP_METHODS;
|
|
87
|
+
const method = tool.execution.method.toUpperCase();
|
|
88
|
+
if (!allowed.map((m) => m.toUpperCase()).includes(method)) {
|
|
89
|
+
violations.push({
|
|
90
|
+
rule: 'blocked-http-method',
|
|
91
|
+
severity: 'high',
|
|
92
|
+
message: `HTTP method "${method}" is not in the allowed list: ${allowed.join(', ')}`,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Rule 8: Block domains not in allowlist (if configured)
|
|
97
|
+
if (tool.execution.type === 'http' && config.allowedDomains && config.allowedDomains.length > 0) {
|
|
98
|
+
const hostname = extractHostname(tool.execution.url);
|
|
99
|
+
if (hostname &&
|
|
100
|
+
!config.allowedDomains.some((d) => hostname === d || hostname.endsWith(`.${d}`))) {
|
|
101
|
+
violations.push({
|
|
102
|
+
rule: 'blocked-domain',
|
|
103
|
+
severity: 'high',
|
|
104
|
+
message: `URL domain "${hostname}" is not in the allowed list`,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Rule 9: Force draft status on agent-created tools
|
|
109
|
+
if (tool.status !== undefined && tool.status !== 'draft') {
|
|
110
|
+
violations.push({
|
|
111
|
+
rule: 'forced-draft-status',
|
|
112
|
+
severity: 'medium',
|
|
113
|
+
message: 'Agent-created tools must have status "draft"',
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return { valid: violations.length === 0, violations };
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Replace all {...} placeholder patterns with 'placeholder' string.
|
|
120
|
+
* Uses safe string operations (indexOf) to avoid ReDoS vulnerabilities.
|
|
121
|
+
*/
|
|
122
|
+
function cleanUrlPlaceholders(url) {
|
|
123
|
+
let cleaned = url;
|
|
124
|
+
while (true) {
|
|
125
|
+
const start = cleaned.indexOf('{');
|
|
126
|
+
if (start === -1)
|
|
127
|
+
break;
|
|
128
|
+
const end = cleaned.indexOf('}', start);
|
|
129
|
+
if (end === -1)
|
|
130
|
+
break;
|
|
131
|
+
cleaned = cleaned.substring(0, start) + 'placeholder' + cleaned.substring(end + 1);
|
|
132
|
+
}
|
|
133
|
+
return cleaned;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Check if a URL targets an internal/metadata network (SSRF protection).
|
|
137
|
+
* Handles IPv4, IPv6, and common internal hostnames.
|
|
138
|
+
*/
|
|
139
|
+
export function isSSRFTarget(url) {
|
|
140
|
+
let hostname;
|
|
141
|
+
try {
|
|
142
|
+
const cleanUrl = cleanUrlPlaceholders(url);
|
|
143
|
+
const parsed = new URL(cleanUrl);
|
|
144
|
+
hostname = parsed.hostname.toLowerCase();
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
// If URL can't be parsed, it may contain only placeholders — allow it
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
// Strip IPv6 brackets
|
|
151
|
+
if (hostname.startsWith('[') && hostname.endsWith(']')) {
|
|
152
|
+
hostname = hostname.slice(1, -1);
|
|
153
|
+
}
|
|
154
|
+
// Exact matches
|
|
155
|
+
if (hostname === 'localhost' ||
|
|
156
|
+
hostname === '127.0.0.1' ||
|
|
157
|
+
hostname === '::1' ||
|
|
158
|
+
hostname === '0.0.0.0' ||
|
|
159
|
+
hostname === '0') {
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
// AWS/cloud metadata endpoint
|
|
163
|
+
if (hostname === '169.254.169.254') {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
// Private IPv4 ranges
|
|
167
|
+
if (hostname.startsWith('169.254.'))
|
|
168
|
+
return true;
|
|
169
|
+
if (hostname.startsWith('10.'))
|
|
170
|
+
return true;
|
|
171
|
+
if (hostname.startsWith('192.168.'))
|
|
172
|
+
return true;
|
|
173
|
+
if (/^172\.(1[6-9]|2\d|3[01])\./.test(hostname))
|
|
174
|
+
return true;
|
|
175
|
+
// Internal/local domain suffixes
|
|
176
|
+
if (hostname.endsWith('.internal'))
|
|
177
|
+
return true;
|
|
178
|
+
if (hostname.endsWith('.local'))
|
|
179
|
+
return true;
|
|
180
|
+
if (hostname.endsWith('.localhost'))
|
|
181
|
+
return true;
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Extract the hostname from a URL string. Returns undefined if unparseable.
|
|
186
|
+
*/
|
|
187
|
+
function extractHostname(url) {
|
|
188
|
+
try {
|
|
189
|
+
const cleanUrl = cleanUrlPlaceholders(url);
|
|
190
|
+
return new URL(cleanUrl).hostname.toLowerCase();
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=content-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-validator.js","sourceRoot":"","sources":["../../src/policy/content-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default Policy Engine for Matimo.
|
|
3
|
+
*
|
|
4
|
+
* Conservative defaults that protect against malicious agent-created tools.
|
|
5
|
+
* Frozen at boot time — agents cannot modify policy at runtime.
|
|
6
|
+
*/
|
|
7
|
+
import type { ToolDefinition } from '../core/schema';
|
|
8
|
+
import type { PolicyEngine, PolicyContext, PolicyDecision, PolicyConfig, PolicyTier } from './types';
|
|
9
|
+
export declare class DefaultPolicyEngine implements PolicyEngine {
|
|
10
|
+
private config;
|
|
11
|
+
constructor(config?: PolicyConfig);
|
|
12
|
+
/**
|
|
13
|
+
* Check whether a tool definition may be created/proposed.
|
|
14
|
+
* First applies the tier gate (fast early-return for TIER 3 blocked tools),
|
|
15
|
+
* then runs ContentValidator rules.
|
|
16
|
+
*/
|
|
17
|
+
canCreate(context: PolicyContext, toolDef: ToolDefinition): PolicyDecision;
|
|
18
|
+
/**
|
|
19
|
+
* Check whether the caller is allowed to execute a given tool.
|
|
20
|
+
*/
|
|
21
|
+
canExecute(context: PolicyContext, tool: ToolDefinition): PolicyDecision;
|
|
22
|
+
/**
|
|
23
|
+
* Filter tools to only those the caller is allowed to see and use.
|
|
24
|
+
*/
|
|
25
|
+
filterForAgent(context: PolicyContext, tools: ToolDefinition[]): ToolDefinition[];
|
|
26
|
+
/** Expose the resolved config (read-only snapshot). */
|
|
27
|
+
getConfig(): Readonly<Required<Omit<PolicyConfig, 'approvalTtlSeconds'>> & Pick<PolicyConfig, 'approvalTtlSeconds'>>;
|
|
28
|
+
/**
|
|
29
|
+
* Hot-reload policy configuration at runtime.
|
|
30
|
+
* Merges the new config with DEFAULT_CONFIG (preserving conservative defaults
|
|
31
|
+
* for any unset fields), then replaces the active config atomically.
|
|
32
|
+
*/
|
|
33
|
+
updateConfig(config: PolicyConfig): void;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Pure utility: classify an agent-proposed tool into a policy tier.
|
|
37
|
+
*
|
|
38
|
+
* - `blocked`: reserved namespace, function/command execution type, SSRF URL
|
|
39
|
+
* - `approval-required`: any auth credential, non-GET HTTP method, any data write
|
|
40
|
+
* - `auto`: low-risk read-only HTTP GET with no auth
|
|
41
|
+
*
|
|
42
|
+
* This runs BEFORE content validation and is a hard gate — `blocked` tools
|
|
43
|
+
* are rejected immediately without running the full content-validator.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getTierForTool(tool: ToolDefinition, config?: PolicyConfig): PolicyTier;
|
|
46
|
+
//# sourceMappingURL=default-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-policy.d.ts","sourceRoot":"","sources":["../../src/policy/default-policy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,cAAc,EACd,YAAY,EACZ,UAAU,EAEX,MAAM,SAAS,CAAC;AAiBjB,qBAAa,mBAAoB,YAAW,YAAY;IACtD,OAAO,CAAC,MAAM,CAC6B;gBAE/B,MAAM,CAAC,EAAE,YAAY;IAIjC;;;;OAIG;IACH,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,cAAc,GAAG,cAAc;IAuG1E;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,cAAc,GAAG,cAAc;IA8CxE;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,cAAc,EAAE;IAOjF,uDAAuD;IACvD,SAAS,IAAI,QAAQ,CACnB,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,oBAAoB,CAAC,CAAC,GAAG,IAAI,CAAC,YAAY,EAAE,oBAAoB,CAAC,CAC9F;IAID;;;;OAIG;IACH,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;CAGzC;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,UAAU,CAsBtF"}
|