@wardnmesh/sdk-node 0.2.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.
Files changed (42) hide show
  1. package/LICENSE +47 -0
  2. package/README.md +178 -0
  3. package/bin/setup.js +119 -0
  4. package/dist/agent-guard.d.ts +28 -0
  5. package/dist/agent-guard.js +206 -0
  6. package/dist/config/security-limits.d.ts +42 -0
  7. package/dist/config/security-limits.js +52 -0
  8. package/dist/detectors/base.d.ts +22 -0
  9. package/dist/detectors/base.js +51 -0
  10. package/dist/detectors/pattern.d.ts +7 -0
  11. package/dist/detectors/pattern.js +76 -0
  12. package/dist/detectors/semantic-detector.d.ts +16 -0
  13. package/dist/detectors/semantic-detector.js +96 -0
  14. package/dist/detectors/sequence.d.ts +11 -0
  15. package/dist/detectors/sequence.js +182 -0
  16. package/dist/detectors/state.d.ts +8 -0
  17. package/dist/detectors/state.js +86 -0
  18. package/dist/index.d.ts +15 -0
  19. package/dist/index.js +31 -0
  20. package/dist/integrations/vercel.d.ts +7 -0
  21. package/dist/integrations/vercel.js +34 -0
  22. package/dist/middleware/express.d.ts +36 -0
  23. package/dist/middleware/express.js +54 -0
  24. package/dist/middleware/nextjs.d.ts +3 -0
  25. package/dist/middleware/nextjs.js +40 -0
  26. package/dist/state/session-manager.d.ts +13 -0
  27. package/dist/state/session-manager.js +22 -0
  28. package/dist/telemetry/reporter.d.ts +32 -0
  29. package/dist/telemetry/reporter.js +86 -0
  30. package/dist/types.d.ts +206 -0
  31. package/dist/types.js +14 -0
  32. package/dist/update-checker.d.ts +21 -0
  33. package/dist/update-checker.js +218 -0
  34. package/dist/utils/logger.d.ts +40 -0
  35. package/dist/utils/logger.js +79 -0
  36. package/dist/utils/rule-validator.d.ts +15 -0
  37. package/dist/utils/rule-validator.js +143 -0
  38. package/dist/utils/safe-regex.d.ts +53 -0
  39. package/dist/utils/safe-regex.js +220 -0
  40. package/dist/wardn.d.ts +67 -0
  41. package/dist/wardn.js +443 -0
  42. package/package.json +47 -0
@@ -0,0 +1,218 @@
1
+ "use strict";
2
+ /**
3
+ * Update Checker - Check for new SDK versions on GitHub Releases
4
+ * Caches results to avoid excessive API calls
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.checkForUpdates = checkForUpdates;
41
+ exports.notifyIfUpdateAvailable = notifyIfUpdateAvailable;
42
+ const logger_1 = require("./utils/logger");
43
+ const security_limits_1 = require("./config/security-limits");
44
+ const fs = __importStar(require("fs"));
45
+ const path = __importStar(require("path"));
46
+ const os = __importStar(require("os"));
47
+ const GITHUB_RELEASES_API = "https://api.github.com/repos/PCIRCLE-AI/wardnmesh/releases/latest";
48
+ const CACHE_DIR = path.join(os.homedir(), ".wardnmesh", "cache");
49
+ const VERSION_CACHE_FILE = path.join(CACHE_DIR, "version-check.json");
50
+ /**
51
+ * Get current SDK version from package.json
52
+ */
53
+ function getCurrentVersion() {
54
+ try {
55
+ const packageJsonPath = path.join(__dirname, "../package.json");
56
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
57
+ return packageJson.version;
58
+ }
59
+ catch (error) {
60
+ logger_1.logger.warn("Failed to read SDK version from package.json");
61
+ return "0.0.0";
62
+ }
63
+ }
64
+ /**
65
+ * Load cached version check result
66
+ */
67
+ function loadCachedVersionCheck() {
68
+ try {
69
+ if (fs.existsSync(VERSION_CACHE_FILE)) {
70
+ const content = fs.readFileSync(VERSION_CACHE_FILE, "utf-8");
71
+ const cache = JSON.parse(content);
72
+ // Check if cache is still valid (TTL: 6 hours)
73
+ const now = Date.now();
74
+ const age = now - cache.checkedAt;
75
+ if (age < security_limits_1.SECURITY_LIMITS.UPDATE_CHECK_CACHE_TTL_MS) {
76
+ return cache;
77
+ }
78
+ }
79
+ }
80
+ catch (error) {
81
+ logger_1.logger.warn("Failed to load version check cache:", error);
82
+ }
83
+ return null;
84
+ }
85
+ /**
86
+ * Save version check result to cache
87
+ */
88
+ function saveVersionCheckCache(cache) {
89
+ try {
90
+ // Ensure cache directory exists
91
+ if (!fs.existsSync(CACHE_DIR)) {
92
+ fs.mkdirSync(CACHE_DIR, { recursive: true });
93
+ }
94
+ fs.writeFileSync(VERSION_CACHE_FILE, JSON.stringify(cache, null, 2));
95
+ }
96
+ catch (error) {
97
+ logger_1.logger.warn("Failed to save version check cache:", error);
98
+ }
99
+ }
100
+ /**
101
+ * Fetch latest version from GitHub Releases API
102
+ */
103
+ async function fetchLatestVersion() {
104
+ try {
105
+ const controller = new AbortController();
106
+ const timeoutId = setTimeout(() => controller.abort(), security_limits_1.SECURITY_LIMITS.FETCH_TIMEOUT_MS);
107
+ const response = await fetch(GITHUB_RELEASES_API, {
108
+ headers: {
109
+ Accept: "application/vnd.github+json",
110
+ "User-Agent": "@wardnmesh/sdk-node",
111
+ },
112
+ signal: controller.signal,
113
+ });
114
+ clearTimeout(timeoutId);
115
+ if (!response.ok) {
116
+ logger_1.logger.warn(`GitHub API returned status ${response.status}: ${response.statusText}`);
117
+ return null;
118
+ }
119
+ const data = await response.json();
120
+ return {
121
+ version: data.tag_name?.replace(/^v/, "") || "0.0.0",
122
+ url: data.html_url || "",
123
+ publishedAt: data.published_at || new Date().toISOString(),
124
+ };
125
+ }
126
+ catch (error) {
127
+ logger_1.logger.warn("Failed to fetch latest version from GitHub:", error);
128
+ return null;
129
+ }
130
+ }
131
+ /**
132
+ * Compare two semantic versions
133
+ * Returns: 1 if v1 > v2, -1 if v1 < v2, 0 if equal
134
+ */
135
+ function compareVersions(v1, v2) {
136
+ const parts1 = v1.split(".").map(Number);
137
+ const parts2 = v2.split(".").map(Number);
138
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
139
+ const num1 = parts1[i] || 0;
140
+ const num2 = parts2[i] || 0;
141
+ if (num1 > num2)
142
+ return 1;
143
+ if (num1 < num2)
144
+ return -1;
145
+ }
146
+ return 0;
147
+ }
148
+ /**
149
+ * Check for SDK updates (uses cache if available)
150
+ * @param forceCheck - Force check even if cache is valid
151
+ * @returns Version information including update availability
152
+ */
153
+ async function checkForUpdates(forceCheck = false) {
154
+ const currentVersion = getCurrentVersion();
155
+ // Try loading from cache first
156
+ if (!forceCheck) {
157
+ const cached = loadCachedVersionCheck();
158
+ if (cached) {
159
+ const updateAvailable = compareVersions(cached.latestVersion, currentVersion) > 0;
160
+ return {
161
+ currentVersion,
162
+ latestVersion: cached.latestVersion,
163
+ updateAvailable,
164
+ releaseUrl: cached.releaseUrl,
165
+ publishedAt: cached.publishedAt,
166
+ };
167
+ }
168
+ }
169
+ // Fetch latest version from GitHub
170
+ const latest = await fetchLatestVersion();
171
+ if (!latest) {
172
+ // Fallback: no update available (API failure)
173
+ return {
174
+ currentVersion,
175
+ latestVersion: currentVersion,
176
+ updateAvailable: false,
177
+ };
178
+ }
179
+ // Save to cache
180
+ saveVersionCheckCache({
181
+ latestVersion: latest.version,
182
+ releaseUrl: latest.url,
183
+ publishedAt: latest.publishedAt,
184
+ checkedAt: Date.now(),
185
+ });
186
+ const updateAvailable = compareVersions(latest.version, currentVersion) > 0;
187
+ return {
188
+ currentVersion,
189
+ latestVersion: latest.version,
190
+ updateAvailable,
191
+ releaseUrl: latest.url,
192
+ publishedAt: latest.publishedAt,
193
+ };
194
+ }
195
+ /**
196
+ * Log update notification if update is available
197
+ */
198
+ async function notifyIfUpdateAvailable() {
199
+ try {
200
+ const versionInfo = await checkForUpdates();
201
+ if (versionInfo.updateAvailable) {
202
+ logger_1.logger.info(`\n` +
203
+ `┌─────────────────────────────────────────────────────────────┐\n` +
204
+ `│ 🎉 New version of @wardnmesh/sdk-node is available! │\n` +
205
+ `│ │\n` +
206
+ `│ Current: ${versionInfo.currentVersion.padEnd(47)} │\n` +
207
+ `│ Latest: ${versionInfo.latestVersion.padEnd(47)} │\n` +
208
+ `│ │\n` +
209
+ `│ Run: npm install @wardnmesh/sdk-node@latest │\n` +
210
+ `│ Release: ${(versionInfo.releaseUrl || "").padEnd(42)} │\n` +
211
+ `└─────────────────────────────────────────────────────────────┘\n`);
212
+ }
213
+ }
214
+ catch (error) {
215
+ // Silently fail - don't disrupt SDK functionality
216
+ logger_1.logger.warn("Failed to check for updates:", error);
217
+ }
218
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Logger Utility - Centralized logging for WardnMesh SDK
3
+ *
4
+ * Provides consistent logging with configurable log levels.
5
+ * Can be easily extended to integrate with external logging services.
6
+ */
7
+ export type LogLevel = "debug" | "info" | "warn" | "error" | "silent";
8
+ declare class Logger {
9
+ private level;
10
+ private prefix;
11
+ constructor(prefix?: string, level?: LogLevel);
12
+ private shouldLog;
13
+ private formatMessage;
14
+ /**
15
+ * Set log level dynamically
16
+ */
17
+ setLevel(level: LogLevel): void;
18
+ /**
19
+ * Get current log level
20
+ */
21
+ getLevel(): LogLevel;
22
+ /**
23
+ * Debug level - detailed information for debugging
24
+ */
25
+ debug(message: string, ...args: unknown[]): void;
26
+ /**
27
+ * Info level - general operational information
28
+ */
29
+ info(message: string, ...args: unknown[]): void;
30
+ /**
31
+ * Warn level - potentially harmful situations
32
+ */
33
+ warn(message: string, ...args: unknown[]): void;
34
+ /**
35
+ * Error level - error events
36
+ */
37
+ error(message: string, ...args: unknown[]): void;
38
+ }
39
+ export declare const logger: Logger;
40
+ export { Logger };
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ /**
3
+ * Logger Utility - Centralized logging for WardnMesh SDK
4
+ *
5
+ * Provides consistent logging with configurable log levels.
6
+ * Can be easily extended to integrate with external logging services.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.Logger = exports.logger = void 0;
10
+ const LOG_LEVELS = {
11
+ debug: 0,
12
+ info: 1,
13
+ warn: 2,
14
+ error: 3,
15
+ silent: 4,
16
+ };
17
+ class Logger {
18
+ constructor(prefix = "[Wardn]", level) {
19
+ this.prefix = prefix;
20
+ // Default to 'info' in production, 'debug' in development
21
+ this.level =
22
+ level ||
23
+ process.env.WARDN_LOG_LEVEL ||
24
+ (process.env.NODE_ENV === "development" ? "debug" : "info");
25
+ }
26
+ shouldLog(level) {
27
+ return LOG_LEVELS[level] >= LOG_LEVELS[this.level];
28
+ }
29
+ formatMessage(message) {
30
+ return `${this.prefix} ${message}`;
31
+ }
32
+ /**
33
+ * Set log level dynamically
34
+ */
35
+ setLevel(level) {
36
+ this.level = level;
37
+ }
38
+ /**
39
+ * Get current log level
40
+ */
41
+ getLevel() {
42
+ return this.level;
43
+ }
44
+ /**
45
+ * Debug level - detailed information for debugging
46
+ */
47
+ debug(message, ...args) {
48
+ if (this.shouldLog("debug")) {
49
+ console.debug(this.formatMessage(message), ...args);
50
+ }
51
+ }
52
+ /**
53
+ * Info level - general operational information
54
+ */
55
+ info(message, ...args) {
56
+ if (this.shouldLog("info")) {
57
+ console.log(this.formatMessage(message), ...args);
58
+ }
59
+ }
60
+ /**
61
+ * Warn level - potentially harmful situations
62
+ */
63
+ warn(message, ...args) {
64
+ if (this.shouldLog("warn")) {
65
+ console.warn(this.formatMessage(message), ...args);
66
+ }
67
+ }
68
+ /**
69
+ * Error level - error events
70
+ */
71
+ error(message, ...args) {
72
+ if (this.shouldLog("error")) {
73
+ console.error(this.formatMessage(message), ...args);
74
+ }
75
+ }
76
+ }
77
+ exports.Logger = Logger;
78
+ // Singleton instance for the SDK
79
+ exports.logger = new Logger("[Wardn]");
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Rule Validator - Validates remote rules against expected schema
3
+ */
4
+ export interface ValidationResult {
5
+ valid: boolean;
6
+ errors: string[];
7
+ }
8
+ /**
9
+ * Validate an array of rules from remote source
10
+ */
11
+ export declare function validateRules(rules: unknown): ValidationResult;
12
+ /**
13
+ * Validate remote rules URL
14
+ */
15
+ export declare function validateRemoteUrl(url: string): ValidationResult;
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ /**
3
+ * Rule Validator - Validates remote rules against expected schema
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.validateRules = validateRules;
7
+ exports.validateRemoteUrl = validateRemoteUrl;
8
+ const VALID_DETECTOR_TYPES = [
9
+ "sequence",
10
+ "state",
11
+ "pattern",
12
+ "content_analysis",
13
+ "semantic",
14
+ ];
15
+ const VALID_SEVERITIES = ["critical", "major", "minor"];
16
+ const VALID_CATEGORIES = [
17
+ "workflow",
18
+ "quality",
19
+ "safety",
20
+ "network_boundary",
21
+ "supply_chain",
22
+ ];
23
+ /**
24
+ * Validate a single rule object
25
+ */
26
+ function validateRule(rule, index) {
27
+ const errors = [];
28
+ const prefix = `Rule[${index}]`;
29
+ if (!rule || typeof rule !== "object") {
30
+ return [`${prefix}: Must be an object`];
31
+ }
32
+ const r = rule;
33
+ // Required string fields
34
+ if (typeof r.id !== "string" || !r.id) {
35
+ errors.push(`${prefix}: Missing or invalid 'id' field`);
36
+ }
37
+ if (typeof r.name !== "string" || !r.name) {
38
+ errors.push(`${prefix}: Missing or invalid 'name' field`);
39
+ }
40
+ if (typeof r.description !== "string") {
41
+ errors.push(`${prefix}: Missing or invalid 'description' field`);
42
+ }
43
+ // Category validation
44
+ if (!VALID_CATEGORIES.includes(r.category)) {
45
+ errors.push(`${prefix}: Invalid category '${r.category}'. Must be one of: ${VALID_CATEGORIES.join(", ")}`);
46
+ }
47
+ // Severity validation
48
+ if (!VALID_SEVERITIES.includes(r.severity)) {
49
+ errors.push(`${prefix}: Invalid severity '${r.severity}'. Must be one of: ${VALID_SEVERITIES.join(", ")}`);
50
+ }
51
+ // Detector validation
52
+ if (!r.detector || typeof r.detector !== "object") {
53
+ errors.push(`${prefix}: Missing or invalid 'detector' field`);
54
+ }
55
+ else {
56
+ const detector = r.detector;
57
+ if (!VALID_DETECTOR_TYPES.includes(detector.type)) {
58
+ errors.push(`${prefix}: Invalid detector type '${detector.type}'. Must be one of: ${VALID_DETECTOR_TYPES.join(", ")}`);
59
+ }
60
+ if (!detector.config || typeof detector.config !== "object") {
61
+ errors.push(`${prefix}: Missing or invalid 'detector.config' field`);
62
+ }
63
+ }
64
+ // Escalation validation
65
+ if (!r.escalation || typeof r.escalation !== "object") {
66
+ errors.push(`${prefix}: Missing or invalid 'escalation' field`);
67
+ }
68
+ return errors;
69
+ }
70
+ /**
71
+ * Validate an array of rules from remote source
72
+ */
73
+ function validateRules(rules) {
74
+ const errors = [];
75
+ if (!Array.isArray(rules)) {
76
+ return {
77
+ valid: false,
78
+ errors: ["Rules must be an array"],
79
+ };
80
+ }
81
+ if (rules.length === 0) {
82
+ return {
83
+ valid: false,
84
+ errors: ["Rules array cannot be empty"],
85
+ };
86
+ }
87
+ // Limit maximum rules to prevent DoS
88
+ const MAX_RULES = 1000;
89
+ if (rules.length > MAX_RULES) {
90
+ return {
91
+ valid: false,
92
+ errors: [`Too many rules (${rules.length}). Maximum allowed: ${MAX_RULES}`],
93
+ };
94
+ }
95
+ // Validate each rule
96
+ for (let i = 0; i < rules.length; i++) {
97
+ const ruleErrors = validateRule(rules[i], i);
98
+ errors.push(...ruleErrors);
99
+ }
100
+ return {
101
+ valid: errors.length === 0,
102
+ errors,
103
+ };
104
+ }
105
+ /**
106
+ * Validate remote rules URL
107
+ */
108
+ function validateRemoteUrl(url) {
109
+ const errors = [];
110
+ try {
111
+ const parsed = new URL(url);
112
+ // Enforce HTTPS in production
113
+ if (process.env.NODE_ENV === "production" &&
114
+ parsed.protocol !== "https:") {
115
+ errors.push("Remote rules URL must use HTTPS in production");
116
+ }
117
+ // Block localhost in production
118
+ if (process.env.NODE_ENV === "production" &&
119
+ (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1")) {
120
+ errors.push("Remote rules URL cannot use localhost in production");
121
+ }
122
+ // Block private IP ranges (basic SSRF protection)
123
+ const privatePatterns = [
124
+ /^10\./,
125
+ /^172\.(1[6-9]|2[0-9]|3[0-1])\./,
126
+ /^192\.168\./,
127
+ /^169\.254\./, // Link-local
128
+ ];
129
+ for (const pattern of privatePatterns) {
130
+ if (pattern.test(parsed.hostname)) {
131
+ errors.push("Remote rules URL cannot use private IP addresses");
132
+ break;
133
+ }
134
+ }
135
+ }
136
+ catch {
137
+ errors.push("Invalid URL format");
138
+ }
139
+ return {
140
+ valid: errors.length === 0,
141
+ errors,
142
+ };
143
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Safe Regex Utilities - ReDoS Prevention
3
+ *
4
+ * Provides regex validation and safe execution with timeout protection.
5
+ */
6
+ export interface RegexValidationResult {
7
+ valid: boolean;
8
+ error?: string;
9
+ }
10
+ export interface PCREConversionResult {
11
+ pattern: string;
12
+ flags: string;
13
+ converted: boolean;
14
+ error?: string;
15
+ }
16
+ /**
17
+ * Convert PCRE inline modifiers to JavaScript flags
18
+ * Handles: (?i), (?m), (?s), (?x), and combinations like (?im)
19
+ */
20
+ export declare function convertPCREModifiers(pattern: string): PCREConversionResult;
21
+ /**
22
+ * Validate a regex pattern for potential ReDoS vulnerabilities
23
+ */
24
+ export declare function validateRegexPattern(pattern: string): RegexValidationResult;
25
+ /**
26
+ * Pattern error metrics for monitoring
27
+ */
28
+ export interface PatternErrorMetrics {
29
+ pcreConversionFailures: number;
30
+ validationFailures: number;
31
+ regexCompilationFailures: number;
32
+ totalPatternsProcessed: number;
33
+ }
34
+ /**
35
+ * Get current pattern error metrics
36
+ */
37
+ export declare function getPatternErrorMetrics(): Readonly<PatternErrorMetrics>;
38
+ /**
39
+ * Reset pattern error metrics (useful for testing)
40
+ */
41
+ export declare function resetPatternErrorMetrics(): void;
42
+ /**
43
+ * Get a cached regex instance or create a new one
44
+ */
45
+ export declare function getCachedRegex(pattern: string, flags?: string): RegExp | null;
46
+ /**
47
+ * Execute regex with content length limit
48
+ */
49
+ export declare function safeRegexExec(regex: RegExp, content: string, maxLength?: number): RegExpExecArray | null;
50
+ /**
51
+ * Safe regex test with content length limit
52
+ */
53
+ export declare function safeRegexTest(regex: RegExp, content: string, maxLength?: number): boolean;