@aimarket/warden 0.0.1 → 0.3.0

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.
@@ -0,0 +1,158 @@
1
+ export type JSONSchema = Record<string, unknown>;
2
+ /** An MCP tool as its server advertises it — the primary attack surface. */
3
+ export interface ToolDef {
4
+ name: string;
5
+ description: string;
6
+ inputSchema: JSONSchema;
7
+ }
8
+ export interface McpServerRef {
9
+ id: string;
10
+ name: string;
11
+ transport: "stdio" | "sse" | "http";
12
+ command?: string;
13
+ args?: string[];
14
+ url?: string;
15
+ env?: Record<string, string>;
16
+ /** Optional catalog this server was discovered from. */
17
+ catalog?: string;
18
+ }
19
+ export type Severity = "info" | "low" | "medium" | "high" | "critical";
20
+ export interface WardenFinding {
21
+ gate: string;
22
+ severity: Severity;
23
+ /** Stable machine code, e.g. "TOOL_DEF_INJECTION". */
24
+ code: string;
25
+ message: string;
26
+ /** Optional tool the finding refers to. */
27
+ tool?: string;
28
+ /**
29
+ * Report-only: this finding NEVER blocks a connection and never costs a tool,
30
+ * at ANY `blockAtSeverity` setting. It is still reported. Whether it affects a
31
+ * gate's score is the gate's decision — the static scanner excludes advisory
32
+ * hits from its score, the pinning gate still rates an unpinned server 0.9.
33
+ *
34
+ * The tier is data, not a consequence of severity, because severity answers
35
+ * "how much attention" and tiering answers "is this a defect at all". A tool
36
+ * whose schema takes an `api_key` is worth pointing at and is not a defect;
37
+ * expressing that by lowering its severity would have made it blocking again
38
+ * for anyone who tightened `blockAtSeverity`.
39
+ */
40
+ advisory?: boolean;
41
+ }
42
+ export interface WardenVerdict {
43
+ allow: boolean;
44
+ /** 0..1 composite safety score (1 = safe). */
45
+ score: number;
46
+ /** The gate that produced the final decision, if blocked. */
47
+ decidedBy?: string;
48
+ findings: WardenFinding[];
49
+ /** Per-tool decisions when partial allow is in play. */
50
+ allowedTools: string[];
51
+ blockedTools: string[];
52
+ /**
53
+ * Which rule tables produced these findings. A recorded scan is only
54
+ * reproducible together with them: the same server can score differently
55
+ * under a later ruleset, and without the version and digest there is no way
56
+ * to tell that apart from the server having changed.
57
+ */
58
+ rulesets: {
59
+ staticScan: RulesetRef;
60
+ };
61
+ }
62
+ /** Identifies an exact rule table: a human version plus a digest of its content. */
63
+ export interface RulesetRef {
64
+ /** Monotonic version of the rule table. */
65
+ version: string;
66
+ /** `sha256-<base64>` over the canonical serialization of every rule. */
67
+ digest: string;
68
+ }
69
+ /** What a gate sees: the server + its advertised tools + accumulating state. */
70
+ export interface WardenGateInput {
71
+ server: McpServerRef;
72
+ tools: ToolDef[];
73
+ /** Findings accumulated by earlier gates. */
74
+ prior: WardenFinding[];
75
+ policy: WardenPolicy;
76
+ }
77
+ export interface WardenGateResult {
78
+ findings: WardenFinding[];
79
+ /** Per-gate score contribution 0..1 (1 = this gate is satisfied). */
80
+ score: number;
81
+ /** If true, short-circuit the chain and block immediately. */
82
+ fatal?: boolean;
83
+ }
84
+ export interface WardenGate {
85
+ readonly name: string;
86
+ evaluate(input: WardenGateInput): Promise<WardenGateResult>;
87
+ }
88
+ export interface WardenPolicy {
89
+ /** Block the whole connection if any finding >= this severity. */
90
+ blockAtSeverity: Severity;
91
+ /** Tool names that always require explicit user approval before running. */
92
+ sensitiveToolPatterns: string[];
93
+ /**
94
+ * Allow connecting to servers the operator never declared — that is, servers
95
+ * the host discovered from a remote catalog, which carry
96
+ * `McpServerRef.catalog`. `false` is fail-closed: only servers the operator
97
+ * listed explicitly may connect.
98
+ *
99
+ * This knob used to mean "has no reputation score yet", which no deployment
100
+ * could satisfy: nothing ever passed trust edges to the reputation oracle, so
101
+ * every server came back unvouched and `false` blocked all of them. Catalog
102
+ * provenance is a fact the host actually holds locally, needs no network, and
103
+ * cannot deadlock — a declared server is always known.
104
+ */
105
+ allowUnknownServers: boolean;
106
+ /** Re-approval required if a server's tool defs change after pinning. */
107
+ pinToolDefs: boolean;
108
+ }
109
+ /** A pinned snapshot of a server's tools, used for drift detection. */
110
+ export interface PinnedServer {
111
+ serverId: string;
112
+ /** sha256 over the canonical tool-def set. */
113
+ toolsHash: string;
114
+ approvedAt: string;
115
+ toolNames: string[];
116
+ }
117
+ /**
118
+ * Where approvals are remembered between runs — the only persistence WARDEN
119
+ * needs. Narrow on purpose: any store with these two methods works, including a
120
+ * Map for tests. Without durable pins, drift detection degrades to "every
121
+ * server is seen for the first time, every time".
122
+ */
123
+ export interface PinStore {
124
+ getPin(serverId: string): Promise<PinnedServer | undefined>;
125
+ putPin(p: PinnedServer): Promise<void>;
126
+ }
127
+ /**
128
+ * Which surface a threat pattern is meaningful against:
129
+ * - `server` — the server's identity/config only (id, name, url, command, args).
130
+ * - `tool` — the advertised tool definitions only (name, description, inputSchema).
131
+ * - `any` — both. This is the default when a record omits `scope`.
132
+ */
133
+ export type ThreatScope = "server" | "tool" | "any";
134
+ /** A signed threat-intel record about a known-bad server/tool. */
135
+ export interface ThreatRecord {
136
+ /** Pattern matched against server identity and/or tool definitions per `scope`. */
137
+ pattern: string;
138
+ severity: Severity;
139
+ code: string;
140
+ reason: string;
141
+ source: string;
142
+ /** Match surface; defaults to `"any"` when absent. */
143
+ scope?: ThreatScope;
144
+ }
145
+ export type LogLevel = "debug" | "info" | "warn" | "error";
146
+ /**
147
+ * Where WARDEN writes. Structurally identical to most host loggers, so an
148
+ * existing one usually satisfies it as-is; `silentLogger()` is provided for
149
+ * hosts that have none.
150
+ */
151
+ export interface WardenLogger {
152
+ debug(msg: string, ...a: unknown[]): void;
153
+ info(msg: string, ...a: unknown[]): void;
154
+ warn(msg: string, ...a: unknown[]): void;
155
+ error(msg: string, ...a: unknown[]): void;
156
+ child(scope: string): WardenLogger;
157
+ }
158
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,11 @@
1
+ // ─────────────────────────────────────────────────────────────────────────────
2
+ // WARDEN — the MCP security firewall: protocol types
3
+ //
4
+ // Everything a host needs to talk to WARDEN lives in this file, and nothing
5
+ // here depends on a particular agent. Two of these interfaces are host-supplied
6
+ // seams rather than data — `PinStore` (where approvals are remembered) and
7
+ // `WardenLogger` (where findings are written) — deliberately narrowed to what
8
+ // the gates actually call, so a host can satisfy them with a Map and a no-op.
9
+ // ─────────────────────────────────────────────────────────────────────────────
10
+ export {};
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,qDAAqD;AACrD,EAAE;AACF,4EAA4E;AAC5E,gFAAgF;AAChF,2EAA2E;AAC3E,8EAA8E;AAC9E,8EAA8E;AAC9E,gFAAgF"}
package/package.json CHANGED
@@ -1,18 +1,75 @@
1
1
  {
2
2
  "name": "@aimarket/warden",
3
- "version": "0.0.1",
4
- "description": "ARGUS WARDEN MCP firewall namespace",
3
+ "version": "0.3.0",
4
+ "description": "WARDEN — MCP security firewall. Vets an MCP server's tool definitions, threat feed, origin and pinning before any tool runs. Zero runtime dependencies.",
5
+ "type": "module",
5
6
  "license": "MIT",
6
- "main": "index.js",
7
- "files": ["index.js", "README.md"],
8
- "homepage": "https://www.npmjs.com/package/argus-warden",
7
+ "author": "AICOM (alexar76)",
8
+ "homepage": "https://github.com/alexar76/warden",
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "git+https://github.com/alexar76/aimarket-sdks.git"
11
+ "url": "git+https://github.com/alexar76/warden.git"
12
12
  },
13
- "keywords": ["aimarket", "modelmarket", "ai-market"],
14
- "publishConfig": { "access": "public" },
13
+ "bugs": {
14
+ "url": "https://github.com/alexar76/warden/issues"
15
+ },
16
+ "main": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js",
22
+ "default": "./dist/index.js"
23
+ },
24
+ "./jcs": {
25
+ "types": "./dist/jcs.d.ts",
26
+ "import": "./dist/jcs.js",
27
+ "default": "./dist/jcs.js"
28
+ }
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "README.md",
33
+ "README-ru.md",
34
+ "README-es.md",
35
+ "README-fr.md",
36
+ "README-zh.md",
37
+ "CHANGELOG.md",
38
+ "LICENSE"
39
+ ],
40
+ "engines": {
41
+ "node": ">=20"
42
+ },
43
+ "sideEffects": false,
15
44
  "scripts": {
16
- "test": "node -e \"require('./index.js')\""
45
+ "build": "tsc -p tsconfig.json",
46
+ "typecheck": "tsc -p tsconfig.json --noEmit",
47
+ "test": "vitest run",
48
+ "test:coverage": "vitest run --coverage",
49
+ "test:watch": "vitest",
50
+ "prepublishOnly": "npm run build && npm test"
51
+ },
52
+ "keywords": [
53
+ "mcp",
54
+ "mcp-security",
55
+ "model-context-protocol",
56
+ "prompt-injection",
57
+ "tool-poisoning",
58
+ "warden",
59
+ "firewall",
60
+ "security",
61
+ "ai-agent",
62
+ "llm",
63
+ "aimarket",
64
+ "aicom"
65
+ ],
66
+ "publishConfig": {
67
+ "access": "public"
68
+ },
69
+ "devDependencies": {
70
+ "@types/node": "^22.10.2",
71
+ "@vitest/coverage-v8": "^2.1.9",
72
+ "typescript": "^5.7.2",
73
+ "vitest": "^2.1.8"
17
74
  }
18
75
  }
package/index.js DELETED
@@ -1,6 +0,0 @@
1
- 'use strict';
2
- module.exports = {
3
- name: '@aimarket/warden',
4
- install: 'npm install -g argus-warden',
5
- homepage: 'https://www.npmjs.com/package/argus-warden',
6
- };