@elizaos/autonomous 2.0.0-alpha.10
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/LICENSE +21 -0
- package/package.json +270 -0
- package/src/actions/emote.ts +101 -0
- package/src/actions/restart.ts +101 -0
- package/src/actions/send-message.ts +168 -0
- package/src/actions/stream-control.ts +439 -0
- package/src/actions/switch-stream-source.ts +126 -0
- package/src/actions/terminal.ts +186 -0
- package/src/api/agent-admin-routes.ts +178 -0
- package/src/api/agent-lifecycle-routes.ts +129 -0
- package/src/api/agent-model.ts +143 -0
- package/src/api/agent-transfer-routes.ts +211 -0
- package/src/api/apps-routes.ts +210 -0
- package/src/api/auth-routes.ts +90 -0
- package/src/api/bsc-trade.ts +736 -0
- package/src/api/bug-report-routes.ts +161 -0
- package/src/api/character-routes.ts +421 -0
- package/src/api/cloud-billing-routes.ts +598 -0
- package/src/api/cloud-compat-routes.ts +192 -0
- package/src/api/cloud-routes.ts +529 -0
- package/src/api/cloud-status-routes.ts +234 -0
- package/src/api/compat-utils.ts +154 -0
- package/src/api/connector-health.ts +135 -0
- package/src/api/coordinator-wiring.ts +179 -0
- package/src/api/credit-detection.ts +47 -0
- package/src/api/database.ts +1357 -0
- package/src/api/diagnostics-routes.ts +389 -0
- package/src/api/drop-service.ts +205 -0
- package/src/api/early-logs.ts +111 -0
- package/src/api/http-helpers.ts +252 -0
- package/src/api/index.ts +85 -0
- package/src/api/knowledge-routes.ts +1189 -0
- package/src/api/knowledge-service-loader.ts +92 -0
- package/src/api/memory-bounds.ts +121 -0
- package/src/api/memory-routes.ts +349 -0
- package/src/api/merkle-tree.ts +239 -0
- package/src/api/models-routes.ts +72 -0
- package/src/api/nfa-routes.ts +169 -0
- package/src/api/nft-verify.ts +188 -0
- package/src/api/og-tracker.ts +72 -0
- package/src/api/parse-action-block.ts +145 -0
- package/src/api/permissions-routes.ts +222 -0
- package/src/api/plugin-validation.ts +355 -0
- package/src/api/provider-switch-config.ts +455 -0
- package/src/api/registry-routes.ts +165 -0
- package/src/api/registry-service.ts +292 -0
- package/src/api/route-helpers.ts +21 -0
- package/src/api/sandbox-routes.ts +1480 -0
- package/src/api/server.ts +17674 -0
- package/src/api/signal-routes.ts +265 -0
- package/src/api/stream-persistence.ts +297 -0
- package/src/api/stream-route-state.ts +48 -0
- package/src/api/stream-routes.ts +1046 -0
- package/src/api/stream-voice-routes.ts +208 -0
- package/src/api/streaming-text.ts +129 -0
- package/src/api/streaming-types.ts +23 -0
- package/src/api/subscription-routes.ts +283 -0
- package/src/api/terminal-run-limits.ts +31 -0
- package/src/api/training-backend-check.ts +40 -0
- package/src/api/training-routes.ts +314 -0
- package/src/api/training-service-like.ts +46 -0
- package/src/api/trajectory-routes.ts +714 -0
- package/src/api/trigger-routes.ts +438 -0
- package/src/api/twitter-verify.ts +226 -0
- package/src/api/tx-service.ts +193 -0
- package/src/api/wallet-dex-prices.ts +206 -0
- package/src/api/wallet-evm-balance.ts +989 -0
- package/src/api/wallet-routes.ts +505 -0
- package/src/api/wallet-rpc.ts +523 -0
- package/src/api/wallet-trading-profile.ts +694 -0
- package/src/api/wallet.ts +745 -0
- package/src/api/whatsapp-routes.ts +282 -0
- package/src/api/zip-utils.ts +130 -0
- package/src/auth/anthropic.ts +63 -0
- package/src/auth/apply-stealth.ts +38 -0
- package/src/auth/claude-code-stealth.ts +141 -0
- package/src/auth/credentials.ts +226 -0
- package/src/auth/index.ts +18 -0
- package/src/auth/openai-codex.ts +94 -0
- package/src/auth/types.ts +24 -0
- package/src/awareness/registry.ts +220 -0
- package/src/bin.ts +10 -0
- package/src/cli/index.ts +36 -0
- package/src/cli/parse-duration.ts +43 -0
- package/src/cloud/auth.test.ts +370 -0
- package/src/cloud/auth.ts +176 -0
- package/src/cloud/backup.test.ts +150 -0
- package/src/cloud/backup.ts +50 -0
- package/src/cloud/base-url.ts +45 -0
- package/src/cloud/bridge-client.test.ts +481 -0
- package/src/cloud/bridge-client.ts +307 -0
- package/src/cloud/cloud-manager.test.ts +223 -0
- package/src/cloud/cloud-manager.ts +151 -0
- package/src/cloud/cloud-proxy.test.ts +122 -0
- package/src/cloud/cloud-proxy.ts +52 -0
- package/src/cloud/index.ts +23 -0
- package/src/cloud/reconnect.test.ts +178 -0
- package/src/cloud/reconnect.ts +108 -0
- package/src/cloud/validate-url.test.ts +147 -0
- package/src/cloud/validate-url.ts +176 -0
- package/src/config/character-schema.ts +44 -0
- package/src/config/config.ts +149 -0
- package/src/config/env-vars.ts +86 -0
- package/src/config/includes.ts +196 -0
- package/src/config/index.ts +15 -0
- package/src/config/object-utils.ts +10 -0
- package/src/config/paths.ts +92 -0
- package/src/config/plugin-auto-enable.ts +520 -0
- package/src/config/schema.ts +1342 -0
- package/src/config/telegram-custom-commands.ts +99 -0
- package/src/config/types.agent-defaults.ts +342 -0
- package/src/config/types.agents.ts +112 -0
- package/src/config/types.gateway.ts +243 -0
- package/src/config/types.hooks.ts +124 -0
- package/src/config/types.messages.ts +201 -0
- package/src/config/types.milady.ts +791 -0
- package/src/config/types.tools.ts +416 -0
- package/src/config/types.ts +7 -0
- package/src/config/zod-schema.agent-runtime.ts +777 -0
- package/src/config/zod-schema.core.ts +778 -0
- package/src/config/zod-schema.hooks.ts +139 -0
- package/src/config/zod-schema.providers-core.ts +1126 -0
- package/src/config/zod-schema.session.ts +98 -0
- package/src/config/zod-schema.ts +865 -0
- package/src/contracts/apps.ts +46 -0
- package/src/contracts/awareness.ts +56 -0
- package/src/contracts/config.ts +172 -0
- package/src/contracts/drop.ts +21 -0
- package/src/contracts/index.ts +8 -0
- package/src/contracts/onboarding.ts +592 -0
- package/src/contracts/permissions.ts +52 -0
- package/src/contracts/verification.ts +9 -0
- package/src/contracts/wallet.ts +503 -0
- package/src/diagnostics/integration-observability.ts +132 -0
- package/src/emotes/catalog.ts +655 -0
- package/src/external-modules.d.ts +7 -0
- package/src/hooks/discovery.test.ts +357 -0
- package/src/hooks/discovery.ts +231 -0
- package/src/hooks/eligibility.ts +146 -0
- package/src/hooks/hooks.test.ts +320 -0
- package/src/hooks/index.ts +8 -0
- package/src/hooks/loader.test.ts +418 -0
- package/src/hooks/loader.ts +256 -0
- package/src/hooks/registry.test.ts +168 -0
- package/src/hooks/registry.ts +74 -0
- package/src/hooks/types.ts +121 -0
- package/src/index.ts +19 -0
- package/src/onboarding-presets.ts +828 -0
- package/src/plugins/custom-rtmp/index.ts +40 -0
- package/src/providers/admin-trust.ts +76 -0
- package/src/providers/session-bridge.ts +143 -0
- package/src/providers/session-utils.ts +42 -0
- package/src/providers/simple-mode.ts +113 -0
- package/src/providers/ui-catalog.ts +135 -0
- package/src/providers/workspace-provider.ts +213 -0
- package/src/providers/workspace.ts +497 -0
- package/src/runtime/agent-event-service.ts +57 -0
- package/src/runtime/cloud-onboarding.test.ts +489 -0
- package/src/runtime/cloud-onboarding.ts +408 -0
- package/src/runtime/core-plugins.ts +53 -0
- package/src/runtime/custom-actions.ts +605 -0
- package/src/runtime/eliza.ts +4941 -0
- package/src/runtime/embedding-presets.ts +73 -0
- package/src/runtime/index.ts +8 -0
- package/src/runtime/milady-plugin.ts +180 -0
- package/src/runtime/onboarding-names.ts +76 -0
- package/src/runtime/release-plugin-policy.ts +119 -0
- package/src/runtime/restart.ts +59 -0
- package/src/runtime/trajectory-persistence.ts +2584 -0
- package/src/runtime/version.ts +6 -0
- package/src/security/audit-log.ts +222 -0
- package/src/security/network-policy.ts +91 -0
- package/src/server/index.ts +6 -0
- package/src/services/agent-export.ts +976 -0
- package/src/services/app-manager.ts +755 -0
- package/src/services/browser-capture.ts +215 -0
- package/src/services/coding-agent-context.ts +355 -0
- package/src/services/fallback-training-service.ts +196 -0
- package/src/services/index.ts +17 -0
- package/src/services/mcp-marketplace.ts +327 -0
- package/src/services/plugin-manager-types.ts +185 -0
- package/src/services/privy-wallets.ts +352 -0
- package/src/services/registry-client-app-meta.ts +201 -0
- package/src/services/registry-client-endpoints.ts +253 -0
- package/src/services/registry-client-local.ts +485 -0
- package/src/services/registry-client-network.ts +173 -0
- package/src/services/registry-client-queries.ts +176 -0
- package/src/services/registry-client-types.ts +104 -0
- package/src/services/registry-client.ts +366 -0
- package/src/services/remote-signing-service.ts +261 -0
- package/src/services/sandbox-engine.ts +753 -0
- package/src/services/sandbox-manager.ts +503 -0
- package/src/services/self-updater.ts +213 -0
- package/src/services/signal-pairing.ts +189 -0
- package/src/services/signing-policy.ts +230 -0
- package/src/services/skill-catalog-client.ts +195 -0
- package/src/services/skill-marketplace.ts +909 -0
- package/src/services/stream-manager.ts +707 -0
- package/src/services/tts-stream-bridge.ts +465 -0
- package/src/services/update-checker.ts +163 -0
- package/src/services/version-compat.ts +367 -0
- package/src/services/whatsapp-pairing.ts +279 -0
- package/src/shared/ui-catalog-prompt.ts +1158 -0
- package/src/test-support/process-helpers.ts +35 -0
- package/src/test-support/route-test-helpers.ts +113 -0
- package/src/test-support/test-helpers.ts +304 -0
- package/src/testing/index.ts +3 -0
- package/src/triggers/action.ts +342 -0
- package/src/triggers/runtime.ts +432 -0
- package/src/triggers/scheduling.ts +472 -0
- package/src/triggers/types.ts +133 -0
- package/src/types/app-hyperscape-routes-shim.d.ts +29 -0
- package/src/types/external-modules.d.ts +7 -0
- package/src/utils/exec-safety.ts +23 -0
- package/src/utils/number-parsing.ts +112 -0
- package/src/utils/spoken-text.ts +65 -0
- package/src/version-resolver.ts +60 -0
- package/test/api/agent-admin-routes.test.ts +160 -0
- package/test/api/agent-lifecycle-routes.test.ts +164 -0
- package/test/api/agent-transfer-routes.test.ts +136 -0
- package/test/api/apps-routes.test.ts +140 -0
- package/test/api/auth-routes.test.ts +160 -0
- package/test/api/bug-report-routes.test.ts +88 -0
- package/test/api/knowledge-routes.test.ts +73 -0
- package/test/api/lifecycle.test.ts +342 -0
- package/test/api/memory-routes.test.ts +74 -0
- package/test/api/models-routes.test.ts +112 -0
- package/test/api/nfa-routes.test.ts +78 -0
- package/test/api/permissions-routes.test.ts +185 -0
- package/test/api/registry-routes.test.ts +157 -0
- package/test/api/signal-routes.test.ts +113 -0
- package/test/api/subscription-routes.test.ts +90 -0
- package/test/api/trigger-routes.test.ts +87 -0
- package/test/api/wallet-routes.observability.test.ts +191 -0
- package/test/api/wallet-routes.test.ts +502 -0
- package/test/diagnostics/integration-observability.test.ts +135 -0
- package/test/security/audit-log.test.ts +229 -0
- package/test/security/network-policy.test.ts +143 -0
- package/test/services/version-compat.test.ts +127 -0
- package/tsconfig.build.json +21 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { resolveMiladyVersion } from "../version-resolver";
|
|
2
|
+
|
|
3
|
+
// Single source of truth for the current Milady version.
|
|
4
|
+
// - Embedded/bundled builds: injected define or env var.
|
|
5
|
+
// - Dev/npm builds: package.json or build-info fallback.
|
|
6
|
+
export const VERSION = resolveMiladyVersion(import.meta.url);
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Append-only audit log for sandbox security events.
|
|
3
|
+
* Never log real secret values — only token IDs and metadata.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const AUDIT_EVENT_TYPES = [
|
|
7
|
+
"sandbox_mode_transition",
|
|
8
|
+
"secret_token_replacement_outbound",
|
|
9
|
+
"secret_sanitization_inbound",
|
|
10
|
+
"privileged_capability_invocation",
|
|
11
|
+
"policy_decision",
|
|
12
|
+
"signing_request_submitted",
|
|
13
|
+
"signing_request_rejected",
|
|
14
|
+
"signing_request_approved",
|
|
15
|
+
"plugin_fallback_attempt",
|
|
16
|
+
"security_kill_switch",
|
|
17
|
+
"sandbox_lifecycle",
|
|
18
|
+
"fetch_proxy_error",
|
|
19
|
+
] as const;
|
|
20
|
+
|
|
21
|
+
export type AuditEventType = (typeof AUDIT_EVENT_TYPES)[number];
|
|
22
|
+
export const AUDIT_SEVERITIES = ["info", "warn", "error", "critical"] as const;
|
|
23
|
+
export type AuditSeverity = (typeof AUDIT_SEVERITIES)[number];
|
|
24
|
+
|
|
25
|
+
const DEFAULT_MAX_ENTRIES = 5000;
|
|
26
|
+
const PROCESS_FEED_MAX_ENTRIES = DEFAULT_MAX_ENTRIES;
|
|
27
|
+
|
|
28
|
+
const processFeedEntries: AuditEntry[] = [];
|
|
29
|
+
const processFeedSubscribers = new Set<AuditFeedSubscriber>();
|
|
30
|
+
|
|
31
|
+
export interface AuditEntry {
|
|
32
|
+
timestamp: string;
|
|
33
|
+
type: AuditEventType;
|
|
34
|
+
summary: string;
|
|
35
|
+
metadata?: Record<string, string | number | boolean | null>;
|
|
36
|
+
severity: AuditSeverity;
|
|
37
|
+
traceId?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface AuditLogConfig {
|
|
41
|
+
console?: boolean;
|
|
42
|
+
maxEntries?: number;
|
|
43
|
+
sink?: (entry: AuditEntry) => void;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface AuditFeedQuery {
|
|
47
|
+
type?: AuditEventType;
|
|
48
|
+
severity?: AuditSeverity;
|
|
49
|
+
sinceMs?: number;
|
|
50
|
+
limit?: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type AuditFeedSubscriber = (entry: AuditEntry) => void;
|
|
54
|
+
|
|
55
|
+
function trimEntries(entries: AuditEntry[], maxEntries: number): void {
|
|
56
|
+
if (entries.length <= maxEntries) return;
|
|
57
|
+
const keep = Math.floor(maxEntries / 2);
|
|
58
|
+
if (keep <= 0) {
|
|
59
|
+
entries.length = 0;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
entries.splice(0, entries.length - keep);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function publishToProcessFeed(entry: AuditEntry): void {
|
|
66
|
+
processFeedEntries.push(entry);
|
|
67
|
+
trimEntries(processFeedEntries, PROCESS_FEED_MAX_ENTRIES);
|
|
68
|
+
for (const subscriber of processFeedSubscribers) {
|
|
69
|
+
try {
|
|
70
|
+
subscriber(entry);
|
|
71
|
+
} catch {
|
|
72
|
+
// Ignore subscriber failures so audit recording is never blocked.
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function toSinceTimestamp(sinceMs: number | undefined): number | undefined {
|
|
78
|
+
if (sinceMs === undefined) return undefined;
|
|
79
|
+
if (!Number.isFinite(sinceMs)) return undefined;
|
|
80
|
+
return Math.trunc(sinceMs);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function toBoundedLimit(limit: number | undefined): number | undefined {
|
|
84
|
+
if (limit === undefined) return undefined;
|
|
85
|
+
if (!Number.isFinite(limit)) return undefined;
|
|
86
|
+
return Math.max(1, Math.trunc(limit));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function queryAuditFeed(query: AuditFeedQuery = {}): AuditEntry[] {
|
|
90
|
+
const sinceTimestamp = toSinceTimestamp(query.sinceMs);
|
|
91
|
+
const boundedLimit = toBoundedLimit(query.limit);
|
|
92
|
+
let entries = processFeedEntries;
|
|
93
|
+
|
|
94
|
+
if (query.type) {
|
|
95
|
+
entries = entries.filter((entry) => entry.type === query.type);
|
|
96
|
+
}
|
|
97
|
+
if (query.severity) {
|
|
98
|
+
entries = entries.filter((entry) => entry.severity === query.severity);
|
|
99
|
+
}
|
|
100
|
+
if (sinceTimestamp !== undefined) {
|
|
101
|
+
entries = entries.filter(
|
|
102
|
+
(entry) => Date.parse(entry.timestamp) >= sinceTimestamp,
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
if (boundedLimit !== undefined) {
|
|
106
|
+
return entries.slice(-boundedLimit);
|
|
107
|
+
}
|
|
108
|
+
return [...entries];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function getAuditFeedSize(): number {
|
|
112
|
+
return processFeedEntries.length;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function subscribeAuditFeed(
|
|
116
|
+
subscriber: AuditFeedSubscriber,
|
|
117
|
+
): () => void {
|
|
118
|
+
processFeedSubscribers.add(subscriber);
|
|
119
|
+
return () => {
|
|
120
|
+
processFeedSubscribers.delete(subscriber);
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** @internal Test-only helper to isolate process-wide audit state between specs. */
|
|
125
|
+
export function __resetAuditFeedForTests(): void {
|
|
126
|
+
processFeedEntries.length = 0;
|
|
127
|
+
processFeedSubscribers.clear();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export class SandboxAuditLog {
|
|
131
|
+
private entries: AuditEntry[] = [];
|
|
132
|
+
private consoleEnabled: boolean;
|
|
133
|
+
private maxEntries: number;
|
|
134
|
+
private sink?: (entry: AuditEntry) => void;
|
|
135
|
+
|
|
136
|
+
constructor(config: AuditLogConfig = {}) {
|
|
137
|
+
this.consoleEnabled = config.console ?? true;
|
|
138
|
+
this.maxEntries = config.maxEntries ?? DEFAULT_MAX_ENTRIES;
|
|
139
|
+
this.sink = config.sink;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
record(entry: Omit<AuditEntry, "timestamp">): void {
|
|
143
|
+
const full: AuditEntry = { ...entry, timestamp: new Date().toISOString() };
|
|
144
|
+
this.entries.push(full);
|
|
145
|
+
publishToProcessFeed(full);
|
|
146
|
+
|
|
147
|
+
trimEntries(this.entries, this.maxEntries);
|
|
148
|
+
|
|
149
|
+
if (this.consoleEnabled) {
|
|
150
|
+
const line = `[AUDIT:${full.severity.toUpperCase()}] ${full.type}: ${full.summary}`;
|
|
151
|
+
if (full.severity === "critical" || full.severity === "error")
|
|
152
|
+
console.error(line);
|
|
153
|
+
else if (full.severity === "warn") console.warn(line);
|
|
154
|
+
else console.log(line);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
this.sink?.(full);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
recordTokenReplacement(
|
|
161
|
+
direction: "outbound" | "inbound",
|
|
162
|
+
url: string,
|
|
163
|
+
tokenIds: string[],
|
|
164
|
+
): void {
|
|
165
|
+
this.record({
|
|
166
|
+
type:
|
|
167
|
+
direction === "outbound"
|
|
168
|
+
? "secret_token_replacement_outbound"
|
|
169
|
+
: "secret_sanitization_inbound",
|
|
170
|
+
summary: `${direction}: ${tokenIds.length} token(s) for ${url}`,
|
|
171
|
+
metadata: {
|
|
172
|
+
direction,
|
|
173
|
+
url,
|
|
174
|
+
tokenCount: tokenIds.length,
|
|
175
|
+
tokenIds: tokenIds.join(","),
|
|
176
|
+
},
|
|
177
|
+
severity: "info",
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
recordCapabilityInvocation(
|
|
182
|
+
capability: string,
|
|
183
|
+
detail: string,
|
|
184
|
+
metadata?: Record<string, string | number | boolean>,
|
|
185
|
+
): void {
|
|
186
|
+
this.record({
|
|
187
|
+
type: "privileged_capability_invocation",
|
|
188
|
+
summary: `${capability}: ${detail}`,
|
|
189
|
+
metadata: { capability, ...metadata },
|
|
190
|
+
severity: "info",
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
recordPolicyDecision(
|
|
195
|
+
decision: "allow" | "deny",
|
|
196
|
+
reason: string,
|
|
197
|
+
metadata?: Record<string, string | number | boolean>,
|
|
198
|
+
): void {
|
|
199
|
+
this.record({
|
|
200
|
+
type: "policy_decision",
|
|
201
|
+
summary: `${decision}: ${reason}`,
|
|
202
|
+
metadata: { decision, reason, ...metadata },
|
|
203
|
+
severity: decision === "deny" ? "warn" : "info",
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
getRecent(count = 100): AuditEntry[] {
|
|
208
|
+
return this.entries.slice(-count);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
getByType(type: AuditEventType, count = 50): AuditEntry[] {
|
|
212
|
+
return this.entries.filter((e) => e.type === type).slice(-count);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
get size(): number {
|
|
216
|
+
return this.entries.length;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
clear(): void {
|
|
220
|
+
this.entries = [];
|
|
221
|
+
}
|
|
222
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import net from "node:net";
|
|
2
|
+
|
|
3
|
+
const ALWAYS_BLOCKED_IP_PATTERNS: RegExp[] = [
|
|
4
|
+
/^0\./, // "this" network
|
|
5
|
+
/^169\.254\./, // link-local / metadata
|
|
6
|
+
/^fe[89ab][0-9a-f]:/i, // IPv6 link-local fe80::/10
|
|
7
|
+
/^::$/i, // unspecified
|
|
8
|
+
/^::1$/i, // IPv6 loopback
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
const PRIVATE_IP_PATTERNS: RegExp[] = [
|
|
12
|
+
/^10\./, // RFC1918
|
|
13
|
+
/^127\./, // loopback
|
|
14
|
+
/^172\.(1[6-9]|2\d|3[01])\./, // RFC1918
|
|
15
|
+
/^192\.168\./, // RFC1918
|
|
16
|
+
/^f[cd][0-9a-f]{2}:/i, // IPv6 ULA fc00::/7
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
export function normalizeHostLike(value: string): string {
|
|
20
|
+
return value
|
|
21
|
+
.trim()
|
|
22
|
+
.toLowerCase()
|
|
23
|
+
.replace(/^\[|\]$/g, "");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function decodeIpv6MappedHex(mapped: string): string | null {
|
|
27
|
+
const parts = mapped.split(":");
|
|
28
|
+
if (parts.length < 1 || parts.length > 2) return null;
|
|
29
|
+
|
|
30
|
+
const parsed = parts.map((part) => {
|
|
31
|
+
if (!/^[0-9a-f]{1,4}$/i.test(part)) return Number.NaN;
|
|
32
|
+
return Number.parseInt(part, 16);
|
|
33
|
+
});
|
|
34
|
+
if (parsed.some((value) => !Number.isFinite(value))) return null;
|
|
35
|
+
|
|
36
|
+
const [hi, lo] = parsed.length === 1 ? [0, parsed[0]] : parsed;
|
|
37
|
+
const octets = [hi >> 8, hi & 0xff, lo >> 8, lo & 0xff];
|
|
38
|
+
return octets.join(".");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function canonicalizeIpv6(ip: string): string | null {
|
|
42
|
+
try {
|
|
43
|
+
return new URL(`http://[${ip}]/`).hostname.replace(/^\[|\]$/g, "");
|
|
44
|
+
} catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function normalizeIpForPolicy(ip: string): string {
|
|
50
|
+
const base = normalizeHostLike(ip).split("%")[0];
|
|
51
|
+
if (!base) return base;
|
|
52
|
+
|
|
53
|
+
let normalized = base;
|
|
54
|
+
if (net.isIP(normalized) === 6) {
|
|
55
|
+
normalized = canonicalizeIpv6(normalized) ?? normalized;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let mapped: string | null = null;
|
|
59
|
+
if (normalized.startsWith("::ffff:")) {
|
|
60
|
+
mapped = normalized.slice("::ffff:".length);
|
|
61
|
+
} else if (normalized.startsWith("0:0:0:0:0:ffff:")) {
|
|
62
|
+
mapped = normalized.slice("0:0:0:0:0:ffff:".length);
|
|
63
|
+
}
|
|
64
|
+
if (!mapped) return normalized;
|
|
65
|
+
|
|
66
|
+
if (net.isIP(mapped) === 4) return mapped;
|
|
67
|
+
return decodeIpv6MappedHex(mapped) ?? normalized;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function isBlockedPrivateOrLinkLocalIp(ip: string): boolean {
|
|
71
|
+
const normalized = normalizeIpForPolicy(ip);
|
|
72
|
+
if (ALWAYS_BLOCKED_IP_PATTERNS.some((pattern) => pattern.test(normalized))) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
return PRIVATE_IP_PATTERNS.some((pattern) => pattern.test(normalized));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function isLoopbackHost(host: string): boolean {
|
|
79
|
+
const normalized = normalizeIpForPolicy(host);
|
|
80
|
+
if (!normalized) return false;
|
|
81
|
+
if (normalized === "localhost" || normalized === "::1") {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Accept only IPv4 literals in 127.0.0.0/8, not hostnames that prefix-match.
|
|
86
|
+
if (net.isIP(normalized) === 4) {
|
|
87
|
+
return normalized.startsWith("127.");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return false;
|
|
91
|
+
}
|