@husk-ai/core 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.
Files changed (61) hide show
  1. package/dist/audit.d.ts +65 -0
  2. package/dist/audit.d.ts.map +1 -0
  3. package/dist/audit.js +87 -0
  4. package/dist/audit.js.map +1 -0
  5. package/dist/browse.d.ts +66 -0
  6. package/dist/browse.d.ts.map +1 -0
  7. package/dist/browse.js +217 -0
  8. package/dist/browse.js.map +1 -0
  9. package/dist/config.d.ts +73 -0
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +61 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/errors.d.ts +59 -0
  14. package/dist/errors.d.ts.map +1 -0
  15. package/dist/errors.js +40 -0
  16. package/dist/errors.js.map +1 -0
  17. package/dist/ids.d.ts +7 -0
  18. package/dist/ids.d.ts.map +1 -0
  19. package/dist/ids.js +29 -0
  20. package/dist/ids.js.map +1 -0
  21. package/dist/index.d.ts +23 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +19 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/lifecycle.d.ts +38 -0
  26. package/dist/lifecycle.d.ts.map +1 -0
  27. package/dist/lifecycle.js +52 -0
  28. package/dist/lifecycle.js.map +1 -0
  29. package/dist/logger.d.ts +20 -0
  30. package/dist/logger.d.ts.map +1 -0
  31. package/dist/logger.js +59 -0
  32. package/dist/logger.js.map +1 -0
  33. package/dist/net.d.ts +48 -0
  34. package/dist/net.d.ts.map +1 -0
  35. package/dist/net.js +219 -0
  36. package/dist/net.js.map +1 -0
  37. package/dist/spec.d.ts +832 -0
  38. package/dist/spec.d.ts.map +1 -0
  39. package/dist/spec.js +191 -0
  40. package/dist/spec.js.map +1 -0
  41. package/dist/types/agent.d.ts +168 -0
  42. package/dist/types/agent.d.ts.map +1 -0
  43. package/dist/types/agent.js +2 -0
  44. package/dist/types/agent.js.map +1 -0
  45. package/dist/types/computer.d.ts +205 -0
  46. package/dist/types/computer.d.ts.map +1 -0
  47. package/dist/types/computer.js +9 -0
  48. package/dist/types/computer.js.map +1 -0
  49. package/dist/types/model.d.ts +197 -0
  50. package/dist/types/model.d.ts.map +1 -0
  51. package/dist/types/model.js +16 -0
  52. package/dist/types/model.js.map +1 -0
  53. package/dist/types/transcript.d.ts +64 -0
  54. package/dist/types/transcript.d.ts.map +1 -0
  55. package/dist/types/transcript.js +3 -0
  56. package/dist/types/transcript.js.map +1 -0
  57. package/dist/util.d.ts +69 -0
  58. package/dist/util.d.ts.map +1 -0
  59. package/dist/util.js +236 -0
  60. package/dist/util.js.map +1 -0
  61. package/package.json +26 -0
package/dist/net.js ADDED
@@ -0,0 +1,219 @@
1
+ import { HuskError } from './errors.js';
2
+ /**
3
+ * Network policy, in one place.
4
+ *
5
+ * This lived in three copies -- `@husk-ai/runtime`, `@husk-ai/agent`, and by
6
+ * implication the docs -- and they drifted: one blocked the cloud metadata
7
+ * endpoint in `mode: 'full'` and one did not. A security check with two answers
8
+ * is not a security check, so it lives here and everything re-exports it.
9
+ */
10
+ /** Match a hostname against one pattern. Supports a single leading `*.` wildcard. */
11
+ export function hostMatches(host, pattern) {
12
+ const h = host.toLowerCase().replace(/\.$/, '');
13
+ const p = pattern.toLowerCase().replace(/\.$/, '');
14
+ if (p === '*')
15
+ return true;
16
+ if (p.startsWith('*.')) {
17
+ const suffix = p.slice(1); // ".example.com"
18
+ return h.endsWith(suffix) && h.length > suffix.length;
19
+ }
20
+ return h === p;
21
+ }
22
+ /**
23
+ * Hosts that are never reachable by default, whatever the mode says.
24
+ *
25
+ * `mode: 'full'` means "the internet", not "and also the cloud metadata
26
+ * service". 169.254.169.254 hands out IAM credentials to anything that asks,
27
+ * and a prompt-injected agent will ask. Loopback and the RFC1918 ranges are the
28
+ * same problem one hop out: the host's own admin panels, and the LAN.
29
+ *
30
+ * An operator who genuinely wants one of these names it in `allow`, where a
31
+ * reviewer reading the husk.yaml can see the decision.
32
+ */
33
+ /**
34
+ * Normalise the many spellings of one IPv4 address.
35
+ *
36
+ * `127.1`, `2130706433` and `0x7f000001` are all `127.0.0.1` to every resolver
37
+ * that matters -- curl, the browser, and Python's urllib all accept them --
38
+ * and a rule that only understands four dotted octets waves each of them
39
+ * through. Measured: `isInternalHost('127.1')` returned false while
40
+ * `isInternalHost('127.0.0.1')` returned true.
41
+ *
42
+ * Returns the four octets, or null when this is not an IPv4 literal at all.
43
+ */
44
+ function ipv4Octets(host) {
45
+ const parts = host.split('.');
46
+ if (parts.length > 4 || parts.some((p) => p === ''))
47
+ return null;
48
+ // Each part may be decimal, octal (leading zero) or hex (0x). inet_aton
49
+ // accepts all three, so refusing to understand them is not a defence.
50
+ const nums = [];
51
+ for (const part of parts) {
52
+ let value;
53
+ if (/^0[xX][0-9a-fA-F]+$/.test(part))
54
+ value = parseInt(part, 16);
55
+ else if (/^0[0-7]+$/.test(part))
56
+ value = parseInt(part, 8);
57
+ else if (/^[0-9]+$/.test(part))
58
+ value = Number(part);
59
+ else
60
+ return null;
61
+ if (!Number.isFinite(value) || value < 0)
62
+ return null;
63
+ nums.push(value);
64
+ }
65
+ // The last part absorbs the remaining octets: `127.1` is 127.0.0.1 and
66
+ // `2130706433` is the whole address in one number.
67
+ const last = nums.pop();
68
+ if (last === undefined)
69
+ return null;
70
+ const width = 4 - nums.length;
71
+ if (last >= 256 ** width)
72
+ return null;
73
+ if (nums.some((n) => n > 255))
74
+ return null;
75
+ const tail = [];
76
+ for (let i = width - 1; i >= 0; i--)
77
+ tail.push((last >>> (8 * i)) & 0xff);
78
+ const all = [...nums, ...tail];
79
+ return all.length === 4 ? all : null;
80
+ }
81
+ export function isInternalHost(host) {
82
+ const h = host.toLowerCase().replace(/\.$/, '').replace(/^\[|\]$/g, '');
83
+ if (h === 'localhost' || h.endsWith('.localhost') || h.endsWith('.local'))
84
+ return true;
85
+ if (h.endsWith('.internal') || h === 'metadata.google.internal')
86
+ return true;
87
+ if (h === '::1' || h === '0:0:0:0:0:0:0:1')
88
+ return true;
89
+ if (/^f[cd][0-9a-f]{2}:/.test(h) || /^fe80:/.test(h))
90
+ return true;
91
+ const v4 = ipv4Octets(h);
92
+ if (v4) {
93
+ const a = v4[0];
94
+ const b = v4[1];
95
+ if (a === 127 || a === 0 || a === 10)
96
+ return true;
97
+ if (a === 169 && b === 254)
98
+ return true; // link-local, incl. the metadata endpoint
99
+ if (a === 172 && b >= 16 && b <= 31)
100
+ return true;
101
+ if (a === 192 && b === 168)
102
+ return true;
103
+ if (a === 100 && b >= 64 && b <= 127)
104
+ return true; // carrier-grade NAT
105
+ }
106
+ return false;
107
+ }
108
+ /** Loopback specifically, as distinct from the rest of the private ranges. */
109
+ export function isLoopbackHost(host) {
110
+ const h = host.toLowerCase().replace(/\.$/, '').replace(/^\[|\]$/g, '');
111
+ if (h === 'localhost' || h.endsWith('.localhost'))
112
+ return true;
113
+ if (h === '::1' || h === '0:0:0:0:0:0:0:1')
114
+ return true;
115
+ const v4 = ipv4Octets(h);
116
+ return v4 !== null && (v4[0] === 127 || v4[0] === 0);
117
+ }
118
+ /**
119
+ * Providers where the computer has its own network namespace.
120
+ *
121
+ * On these, `127.0.0.1` inside the computer is the computer, so an agent can
122
+ * start a server and look at it -- the most common thing it will ever want to
123
+ * do. On `local` that address is the host's own loopback, and on `ssh` it
124
+ * belongs to a box the user may be running things on, so neither qualifies.
125
+ *
126
+ * This lives here, beside `isHostAllowed`, because it is the same policy
127
+ * question and it had already been copied into three files. `net.ts` exists to
128
+ * be the one answer: the last time this rule had two copies, they disagreed
129
+ * about whether `mode: 'full'` could reach the cloud metadata endpoint.
130
+ */
131
+ const OWNS_LOOPBACK = new Set(['docker', 'podman', 'fly']);
132
+ /** Whether this provider's loopback belongs to the computer rather than the host. */
133
+ export function ownsLoopback(provider) {
134
+ return OWNS_LOOPBACK.has(provider);
135
+ }
136
+ /**
137
+ * Whether the computer shares a network stack with whoever is running husk.
138
+ *
139
+ * The inverse of {@link ownsLoopback}, named for the thing a caller usually
140
+ * wants to warn about.
141
+ */
142
+ export function sharesHostNetwork(provider) {
143
+ return !OWNS_LOOPBACK.has(provider);
144
+ }
145
+ export function isHostAllowed(host, policy, ctx = {}) {
146
+ const explicitlyAllowed = (policy?.allow ?? []).some((p) => hostMatches(host, p));
147
+ // The floor is checked before the mode, so `full` cannot reach the metadata
148
+ // service. Loopback is carved out of it when the computer owns its own.
149
+ if (!explicitlyAllowed) {
150
+ if (isLoopbackHost(host)) {
151
+ if (!ctx.loopbackIsOwn)
152
+ return false;
153
+ }
154
+ else if (isInternalHost(host)) {
155
+ return false;
156
+ }
157
+ }
158
+ if (!policy)
159
+ return true;
160
+ if (policy.deny?.some((p) => hostMatches(host, p)))
161
+ return false;
162
+ switch (policy.mode) {
163
+ case 'none':
164
+ return false;
165
+ case 'full':
166
+ return true;
167
+ case 'egress':
168
+ // An egress policy with no allow-list allows nothing. Reading it as
169
+ // "unrestricted" would be the dangerous interpretation.
170
+ return explicitlyAllowed;
171
+ }
172
+ }
173
+ /** The hostname of a URL, or null when it does not parse. */
174
+ export function urlHost(url) {
175
+ try {
176
+ return new URL(url).hostname;
177
+ }
178
+ catch {
179
+ return null;
180
+ }
181
+ }
182
+ /**
183
+ * Parse and authorise a URL in one step.
184
+ *
185
+ * Returns the parsed URL so a caller cannot accidentally check one string and
186
+ * then fetch a different one.
187
+ */
188
+ export function assertUrlAllowed(url, policy, ctx = {}) {
189
+ let parsed;
190
+ try {
191
+ parsed = new URL(url);
192
+ }
193
+ catch {
194
+ throw new HuskError('E_EXEC_DENIED', `not a valid URL: ${url}`, {
195
+ hint: 'include the scheme, e.g. https://example.com',
196
+ });
197
+ }
198
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
199
+ throw new HuskError('E_EXEC_DENIED', `refusing the ${parsed.protocol} scheme`, {
200
+ hint: 'only http and https are fetched; file:// would read the host filesystem',
201
+ });
202
+ }
203
+ if (!isHostAllowed(parsed.hostname, policy, ctx)) {
204
+ const loopback = isLoopbackHost(parsed.hostname);
205
+ const internal = isInternalHost(parsed.hostname);
206
+ throw new HuskError('E_EXEC_DENIED', `network policy refuses ${parsed.hostname}`, {
207
+ hint: loopback && !ctx.loopbackIsOwn
208
+ ? 'on this provider loopback is the host machine, not the computer -- use an isolated ' +
209
+ 'provider (docker, podman, fly) to reach a server the agent started, or name the ' +
210
+ 'host in computer.network.allow'
211
+ : internal
212
+ ? 'link-local and RFC1918 hosts must be named in computer.network.allow'
213
+ : `add it to computer.network.allow, or set computer.network.mode: full`,
214
+ details: { host: parsed.hostname, mode: policy?.mode ?? 'unset', internal, loopback },
215
+ });
216
+ }
217
+ return parsed;
218
+ }
219
+ //# sourceMappingURL=net.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"net.js","sourceRoot":"","sources":["../src/net.ts"],"names":[],"mappings":"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"}