create-metamynd-agent 0.7.6 → 0.7.7
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/README.md +17 -12
- package/index.mjs +29 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -150,7 +150,7 @@ What actually stops that bypass is that `bookFlight()` doesn't exist in the agen
|
|
|
150
150
|
It exists only in `gateway/server.mjs` — a separate process, started separately, holding any real
|
|
151
151
|
tool credentials the agent process never sees — which independently re-verifies every request
|
|
152
152
|
against the agent's own published policy bundle before running it, **binds that request to the
|
|
153
|
-
actual body being executed** (`@metamynd/agentsafe-http-gateway` ≥ 0.
|
|
153
|
+
actual body being executed** (`@metamynd/agentsafe-http-gateway` ≥ 0.4.0), and requires the
|
|
154
154
|
agent's `authorizationId` to atomically claim single-use execution against the real stateful gate
|
|
155
155
|
(`requireAuthorization`, `@metamynd/agentsafe-mcp-guard` ≥ 0.3.0) — closing a confused-deputy gap
|
|
156
156
|
and a replay/cumulative-spend gap, both found during independent testing. Same shape as the mutual
|
|
@@ -167,22 +167,27 @@ Named precisely, not left implicit:
|
|
|
167
167
|
|
|
168
168
|
- **Direct call.** `bookFlight()` doesn't exist in the agent's process.
|
|
169
169
|
- **Confused deputy (payload).** Signing a cheap request while executing an expensive one (a
|
|
170
|
-
different amount/
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
170
|
+
different amount/merchant in the body than what was signed) is refused before the tool runs —
|
|
171
|
+
payload binding (`@metamynd/agentsafe-http-gateway` ≥ 0.4.0). The default binder requires
|
|
172
|
+
`amount`/`merchant` to actually be found in the body whenever the signed request names a real
|
|
173
|
+
value for them — not just "did the body offer at least one correct-looking field." A first
|
|
174
|
+
attempt at this (0.3.0) checked the weaker version and was re-tested and closed the same day: a
|
|
175
|
+
correct decoy in one field (e.g. a matching `merchant`) let the OTHER field hide anywhere —
|
|
176
|
+
nested, renamed, an array, or an entirely empty/non-JSON body.
|
|
177
177
|
- **Replay.** A captured, resent request fails to atomically claim single-use execution the second
|
|
178
178
|
time — `requireAuthorization`.
|
|
179
179
|
- **Cumulative spend.** The claimed authorization only exists because the real stateful gate
|
|
180
180
|
already checked it against the mandate's TOTAL budget when minted, not just this one request's
|
|
181
181
|
amount — so many small legal-looking calls can't add up past the cap this way.
|
|
182
|
-
- **Amount unknown.**
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
182
|
+
- **Amount unknown.** Two separate places this matters, both actually authored, not just
|
|
183
|
+
available: the platform's own custodial-signing tools (`@metamynd/agentsafe-guard` ≥ 0.6.0,
|
|
184
|
+
`@metamynd/agentsafe-mcp-guard` ≥ 0.3.0) block by default when a signed-transaction tool's raw
|
|
185
|
+
bytes or a nested x402 payload hide the amount from a naive spend cap — AND this agent's own
|
|
186
|
+
starter SOP puts the same `amount-unknown` check ahead of its per-transaction cap (both the
|
|
187
|
+
hosted default and `--harness`'s local one). The atom existing was not the gap: for a while
|
|
188
|
+
this SOP still only ever authored `amount-over`, which silently does not fire on a missing or
|
|
189
|
+
string amount (`typeof c.amount === 'number'` is false either way) — a real, live-confirmed way
|
|
190
|
+
to slip a booking's cap untested. Fixed at the template, not just the atom registry.
|
|
186
191
|
|
|
187
192
|
The claim above also checks `agentDid`/`amount`/`currency`/`merchant` together against the
|
|
188
193
|
request being executed (`@metamynd/agentsafe-mcp-guard` ≥ 0.2.1) — a same-amount, same-currency
|
package/index.mjs
CHANGED
|
@@ -36,11 +36,12 @@ const MCP_GUARD_VERSION = '^0.3.0';
|
|
|
36
36
|
const GATEWAY_PKG = '@metamynd/agentsafe-http-gateway';
|
|
37
37
|
// 0.2.0 fixes a confused-deputy gap (payload not bound to the signed request) — the CLI must
|
|
38
38
|
// never scaffold a range that could resolve below it.
|
|
39
|
-
// 0.3.0
|
|
40
|
-
// fields
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
|
|
39
|
+
// 0.3.0 was a first, INCOMPLETE attempt at the follow-on gap (checked only "did the body offer
|
|
40
|
+
// NONE of the three fields" — a correct decoy in one field let the other hide anywhere). 0.4.0
|
|
41
|
+
// is the actual fix: requires amount/merchant specifically, whenever the signature names a real
|
|
42
|
+
// value for them. Re-tested live and closed same day; ^0.3.0 here would still resolve to the
|
|
43
|
+
// broken version.
|
|
44
|
+
const GATEWAY_VERSION = '^0.4.0';
|
|
44
45
|
const DEFAULT_API = 'https://metamynd.ai/api/v1';
|
|
45
46
|
const DEFAULT_GATEWAY_PORT = 4401; // distinct from --harness's dashboard (4400)
|
|
46
47
|
|
|
@@ -916,13 +917,13 @@ own code, or a network attacker) might attempt:
|
|
|
916
917
|
- **Direct call.** \`bookFlight()\` doesn't exist in the agent's process. There's nothing to call.
|
|
917
918
|
- **Confused deputy (payload).** The gateway re-verifies the signed request against this agent's
|
|
918
919
|
own policy AND binds it to the actual request body (payload binding,
|
|
919
|
-
\`@metamynd/agentsafe-http-gateway\` ≥ 0.
|
|
920
|
-
expensive one is refused before the tool ever runs. The default binder
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
920
|
+
\`@metamynd/agentsafe-http-gateway\` ≥ 0.4.0) — signing a cheap request while executing an
|
|
921
|
+
expensive one is refused before the tool ever runs. The default binder requires \`amount\`/
|
|
922
|
+
\`merchant\` to actually be found in the body whenever the signature names a real value for
|
|
923
|
+
them — not just "did the body offer at least one correct-looking field." A first attempt at
|
|
924
|
+
this (0.3.0) checked the weaker version and was re-tested and closed the same day: a correct
|
|
925
|
+
decoy in one field let the OTHER field hide anywhere — nested, renamed, an array, or an
|
|
926
|
+
entirely empty/non-JSON body.
|
|
926
927
|
- **Replay.** \`requireAuthorization: true\` (set in \`server.mjs\`) requires the agent's
|
|
927
928
|
\`authorizationId\` — from a REAL \`guard.authorize()\` call, which \`index.mjs\` already makes for
|
|
928
929
|
any value-bearing action by default — to atomically claim single-use execution against the
|
|
@@ -931,10 +932,13 @@ own code, or a network attacker) might attempt:
|
|
|
931
932
|
already checked it against the mandate's TOTAL budget when it was minted — not just this one
|
|
932
933
|
request's amount. Many small legal-looking calls can't add up past the mandate cap this way,
|
|
933
934
|
because each needed its own real authorization first.
|
|
934
|
-
- **Amount unknown.**
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
935
|
+
- **Amount unknown.** \`amount-unknown\` (\`@metamynd/agentsafe-mcp-guard\` ≥ 0.3.0) blocks a
|
|
936
|
+
platform tool by default when its raw bytes or a nested payload hide the amount from a naive
|
|
937
|
+
spend cap — AND this agent's OWN starter SOP (see \`agent.metamynd.json\` /
|
|
938
|
+
\`harness-rules.json\`) puts the same check ahead of its per-transaction cap. That second part
|
|
939
|
+
didn't used to be true: the SOP only ever authored \`amount-over\`, which silently does not fire
|
|
940
|
+
on a missing or string amount, so either one slipped the cap untested — the atom existing
|
|
941
|
+
wasn't the gap, this template never authoring it was.
|
|
938
942
|
|
|
939
943
|
The claim above also checks the claimed authorization's own \`agentDid\`/\`amount\`/\`currency\`/
|
|
940
944
|
\`merchant\` against the request actually being executed (\`@metamynd/agentsafe-mcp-guard\` ≥ 0.2.1)
|
|
@@ -1064,10 +1068,17 @@ async function runSandbox(args) {
|
|
|
1064
1068
|
|
|
1065
1069
|
/** Mirrors defaultSopDocument() in backend/src/features/onboarding/onboarding.provision.ts —
|
|
1066
1070
|
* same starter rules the hosted platform issues, so a harness project behaves identically
|
|
1067
|
-
* to a freshly-provisioned one before anyone edits either.
|
|
1071
|
+
* to a freshly-provisioned one before anyone edits either.
|
|
1072
|
+
*
|
|
1073
|
+
* `amount-unknown` first matters MORE here than on the hosted path: evaluateLocally() runs
|
|
1074
|
+
* entirely client-side with no schema boundary in front of it, so nothing stops a caller from
|
|
1075
|
+
* passing amount: "5000" (a string) or omitting amount entirely — `amount-over` silently does
|
|
1076
|
+
* not fire on either (`typeof c.amount === 'number'` is false), so the cap passes untested,
|
|
1077
|
+
* not safe. Ordering amount-unknown first blocks that instead of letting it through. */
|
|
1068
1078
|
function harnessDefaultSop(perTxnMax) {
|
|
1069
1079
|
return {
|
|
1070
1080
|
molecules: [
|
|
1081
|
+
{ id: 'amount-known', name: 'Amount must be determinable', combinator: 'any', atoms: [{ id: 'a0', predicate: 'amount-unknown' }], decision: 'block', reasonCode: 'AMOUNT_NOT_DETERMINABLE' },
|
|
1071
1082
|
{ id: 'cap', name: 'Per-transaction cap', combinator: 'any', atoms: [{ id: 'a1', predicate: 'amount-over', config: { limit: perTxnMax } }], decision: 'block', reasonCode: 'SOP_SPEND_CAP' },
|
|
1072
1083
|
{ id: 'review', name: 'High-risk review', combinator: 'any', atoms: [{ id: 'a2', predicate: 'risk-at-or-above', config: { level: 'high' } }], decision: 'escalate', reasonCode: 'RISK_REVIEW' },
|
|
1073
1084
|
],
|
|
@@ -1139,6 +1150,7 @@ function renderConstraint(c) {
|
|
|
1139
1150
|
function renderAtom(a) {
|
|
1140
1151
|
const c = a.config || {};
|
|
1141
1152
|
switch (a.predicate) {
|
|
1153
|
+
case 'amount-unknown': return \`transaction amount must be a real, determinable number\`;
|
|
1142
1154
|
case 'amount-over': return \`transaction amount must not exceed \${c.limit}\`;
|
|
1143
1155
|
case 'cumulative-over': return \`cumulative spend must not exceed \${c.limit}\`;
|
|
1144
1156
|
case 'jurisdiction-not-allowed': return \`jurisdiction must be one of [\${(c.allowed || []).join(', ')}]\`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-metamynd-agent",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.7",
|
|
4
4
|
"description": "Scaffold a MetaMynd/AgentSafe-governed AI agent in one command — logs in, provisions the agent (identity + mandate + SOP + Standards) in a single call, writes agent.metamynd.json plus a runnable agent + separate tool-gateway process that closes direct-call, confused-deputy, replay, and cumulative-spend bypasses. --harness scaffolds a free, local, zero-network governance harness instead.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|