@ai-ecoverse/slicc-kernel 1.170.3 → 1.170.4

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/dist/node.js CHANGED
@@ -3695,7 +3695,7 @@ function satisfies(version, range2) {
3695
3695
  }
3696
3696
 
3697
3697
  // src/version.ts
3698
- var KERNEL_VERSION = true ? "1.170.3" : "0.0.0-dev";
3698
+ var KERNEL_VERSION = true ? "1.170.4" : "0.0.0-dev";
3699
3699
  var OS_RELEASE = "6.0.0-slicc";
3700
3700
  function procVersion() {
3701
3701
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -5602,6 +5602,78 @@ var CronService = class {
5602
5602
  }
5603
5603
  };
5604
5604
 
5605
+ // src/kernel/net/placeholder-floor.ts
5606
+ var PLACEHOLDER = /fnox_proxy_[0-9a-f]{24}/;
5607
+ var ESCAPE = /%([0-9a-f]{2})/gi;
5608
+ var BASIC = /\bbasic\b(.*)/is;
5609
+ var PERCENT_LAYERS = 8;
5610
+ var BASE64_GROUP = 4;
5611
+ var PLACEHOLDER_REFUSED = "refused: this request has a sealed placeholder in its URL, a header or a Basic credential, and nothing fills it, so it was not sent";
5612
+ var PlaceholderRefused = class extends Error {
5613
+ status = 403;
5614
+ code = "EACCES";
5615
+ constructor() {
5616
+ super(PLACEHOLDER_REFUSED);
5617
+ }
5618
+ };
5619
+ function carries(text) {
5620
+ let layer = text;
5621
+ for (let i = 0; i < PERCENT_LAYERS; i++) {
5622
+ if (PLACEHOLDER.test(layer)) return true;
5623
+ const next3 = layer.replace(
5624
+ ESCAPE,
5625
+ (_, hex4) => String.fromCharCode(Number.parseInt(hex4, 16))
5626
+ );
5627
+ if (next3 === layer) return false;
5628
+ layer = next3;
5629
+ }
5630
+ return PLACEHOLDER.test(layer);
5631
+ }
5632
+ function basicCarries(value2) {
5633
+ const credential = BASIC.exec(value2)?.[1];
5634
+ if (credential === void 0) return false;
5635
+ const letters = credential.replace(/[^A-Za-z0-9+/_-]/g, "").replaceAll("-", "+").replaceAll("_", "/");
5636
+ for (let shift = 0; shift < BASE64_GROUP; shift++) {
5637
+ const part = letters.slice(shift);
5638
+ const whole = part.length % BASE64_GROUP === 1 ? part.slice(0, -1) : part;
5639
+ if (carries(atob(whole))) return true;
5640
+ }
5641
+ return false;
5642
+ }
5643
+ function headersCarry(headers) {
5644
+ return headers.some(
5645
+ ([name2, value2]) => carries(name2.toLowerCase()) || carries(value2) || basicCarries(value2)
5646
+ );
5647
+ }
5648
+ function urlCarries(url) {
5649
+ return carries(url) || URL.canParse(url) && carries(new URL(url).href);
5650
+ }
5651
+ function refuse(request) {
5652
+ if (urlCarries(request.url) || headersCarry(request.headers)) throw new PlaceholderRefused();
5653
+ }
5654
+ function refuseSocket(request) {
5655
+ refuse(request);
5656
+ if (request.protocols.some(carries)) throw new PlaceholderRefused();
5657
+ }
5658
+ function placeholderFloor(inner) {
5659
+ const open = inner.websocket?.bind(inner);
5660
+ return {
5661
+ get traits() {
5662
+ return inner.traits;
5663
+ },
5664
+ ...open ? {
5665
+ websocket: async (request) => {
5666
+ refuseSocket(request);
5667
+ return open(request);
5668
+ }
5669
+ } : {},
5670
+ async fetch(request, owner) {
5671
+ refuse(request);
5672
+ return inner.fetch(request, owner);
5673
+ }
5674
+ };
5675
+ }
5676
+
5605
5677
  // src/kernel/net/ws-queue.ts
5606
5678
  var INBOUND_LIMIT = 16 * 1024 * 1024;
5607
5679
  var MESSAGE_LIMIT = 64 * 1024 * 1024;
@@ -6176,7 +6248,8 @@ var RealmProxy = class {
6176
6248
  });
6177
6249
  } catch (e) {
6178
6250
  waiting.abort();
6179
- throw new HttpError(502, e instanceof Error ? e.message : String(e));
6251
+ const status = e instanceof PlaceholderRefused ? e.status : 502;
6252
+ throw new HttpError(status, e instanceof Error ? e.message : String(e));
6180
6253
  }
6181
6254
  ctx.idle.ms = Number.POSITIVE_INFINITY;
6182
6255
  try {
@@ -6390,7 +6463,7 @@ async function relay(socket, conn) {
6390
6463
  // src/fs/attest.ts
6391
6464
  var ATTEST_MAX = 1024 * 1024;
6392
6465
  var UNOWNED = 1e3;
6393
- function refuse(code, path, why) {
6466
+ function refuse2(code, path, why) {
6394
6467
  throw Object.assign(new Error(`attest ${path}: ${why}`), { code });
6395
6468
  }
6396
6469
  function chainOf(path) {
@@ -6432,11 +6505,11 @@ async function trustedParents(fs, path, o) {
6432
6505
  const parents = [];
6433
6506
  for (const dir of chainOf(path).slice(0, -1)) {
6434
6507
  const st = await fs.lstat(dir);
6435
- if (st.isSymbolicLink) refuse("EACCES", path, `${dir} is a symlink`);
6436
- if (!st.isDirectory) refuse("ENOTDIR", path, `${dir} is not a directory`);
6508
+ if (st.isSymbolicLink) refuse2("EACCES", path, `${dir} is a symlink`);
6509
+ if (!st.isDirectory) refuse2("ENOTDIR", path, `${dir} is not a directory`);
6437
6510
  const perm = owned(dir, st);
6438
6511
  if (o.users !== "off" && (perm.uid !== 0 || (perm.mode & 18) !== 0)) {
6439
- refuse("EACCES", path, `${dir} is not root-owned or is writable by group or others`);
6512
+ refuse2("EACCES", path, `${dir} is not root-owned or is writable by group or others`);
6440
6513
  }
6441
6514
  parents.push(perm);
6442
6515
  }
@@ -6444,27 +6517,27 @@ async function trustedParents(fs, path, o) {
6444
6517
  }
6445
6518
  async function attest(fs, asked, o) {
6446
6519
  if (typeof asked !== "string" || !asked.startsWith("/")) {
6447
- refuse("EINVAL", String(asked), "not an absolute path");
6520
+ refuse2("EINVAL", String(asked), "not an absolute path");
6448
6521
  }
6449
6522
  const path = normalizePath(asked);
6450
6523
  const mount = o.mounts.find((target) => {
6451
6524
  const at = normalizePath(target);
6452
6525
  return at === "/" || under(path, at);
6453
6526
  });
6454
- if (mount !== void 0) refuse("EACCES", path, `under the mount ${mount}`);
6527
+ if (mount !== void 0) refuse2("EACCES", path, `under the mount ${mount}`);
6455
6528
  const parents = await trustedParents(fs, path, o);
6456
6529
  for (let tries = 0; ; tries++) {
6457
6530
  const before = await fs.lstat(path);
6458
- if (before.isSymbolicLink) refuse("EACCES", path, "is a symlink");
6531
+ if (before.isSymbolicLink) refuse2("EACCES", path, "is a symlink");
6459
6532
  if (!before.isFile)
6460
- refuse(before.isDirectory ? "EISDIR" : "EINVAL", path, "is not a regular file");
6461
- if (before.size > ATTEST_MAX) refuse("EFBIG", path, `is over ${ATTEST_MAX} bytes`);
6533
+ refuse2(before.isDirectory ? "EISDIR" : "EINVAL", path, "is not a regular file");
6534
+ if (before.size > ATTEST_MAX) refuse2("EFBIG", path, `is over ${ATTEST_MAX} bytes`);
6462
6535
  const bytes = (await fs.readFileBuffer(path)).slice();
6463
6536
  const after = await fs.lstat(path);
6464
6537
  if (unchanged(before, after, bytes)) {
6465
6538
  return attested(path, after, bytes, await sha256(bytes), o, parents);
6466
6539
  }
6467
- if (tries >= 1) refuse("EAGAIN", path, "changed while it was read");
6540
+ if (tries >= 1) refuse2("EAGAIN", path, "changed while it was read");
6468
6541
  }
6469
6542
  }
6470
6543
  var WATCH_DEBOUNCE_MS = 50;
@@ -11702,7 +11775,7 @@ function encodeSabResult(result) {
11702
11775
  message: result.message,
11703
11776
  ...result.direct ? { direct: true } : {},
11704
11777
  ...result.dev !== void 0 ? { dev: result.dev } : {},
11705
- ...result.detail === "transport" ? { detail: result.detail } : {}
11778
+ ...result.detail ? { detail: result.detail } : {}
11706
11779
  })
11707
11780
  )
11708
11781
  };
@@ -15116,22 +15189,28 @@ var HttpHandles = class {
15116
15189
  return response.redirected ? { ...head, json: { ...head.json, redirected: true } } : head;
15117
15190
  } catch (e) {
15118
15191
  entry.upload?.cancel();
15119
- const text = message2(e);
15120
- if (port !== void 0) return { ok: false, errno: codeOf2(e), message: text };
15121
- const status = e.status;
15122
- if (text === NO_TRANSPORT || typeof status !== "number" || status === 502) {
15123
- const code = codeOf2(e);
15124
- const errno3 = text === NO_TRANSPORT ? "ENETUNREACH" : code !== "EIO" ? code : "ECONNREFUSED";
15125
- const failed3 = e.detail === "transport";
15126
- return { ok: false, errno: errno3, message: text, ...failed3 ? { detail: "transport" } : {} };
15127
- }
15128
- entry.body = once(new TextEncoder().encode(text))[Symbol.asyncIterator]();
15129
- return this.headOf(handle, req.url, {
15130
- status,
15131
- statusText: "",
15132
- headers: [["content-type", "text/plain; charset=utf-8"]]
15133
- });
15192
+ if (port !== void 0) return { ok: false, errno: codeOf2(e), message: message2(e) };
15193
+ return this.failure(handle, req, e, entry);
15194
+ }
15195
+ }
15196
+ failure(handle, req, e, entry) {
15197
+ const text = message2(e);
15198
+ if (e instanceof PlaceholderRefused) {
15199
+ return { ok: false, errno: e.code, message: text, detail: "placeholder" };
15134
15200
  }
15201
+ const status = e.status;
15202
+ if (text === NO_TRANSPORT || typeof status !== "number" || status === 502) {
15203
+ const code = codeOf2(e);
15204
+ const errno3 = text === NO_TRANSPORT ? "ENETUNREACH" : code !== "EIO" ? code : "ECONNREFUSED";
15205
+ const failed3 = e.detail === "transport";
15206
+ return { ok: false, errno: errno3, message: text, ...failed3 ? { detail: "transport" } : {} };
15207
+ }
15208
+ entry.body = once(new TextEncoder().encode(text))[Symbol.asyncIterator]();
15209
+ return this.headOf(handle, req.url, {
15210
+ status,
15211
+ statusText: "",
15212
+ headers: [["content-type", "text/plain; charset=utf-8"]]
15213
+ });
15135
15214
  }
15136
15215
  headOf(handle, url, response) {
15137
15216
  const { status, statusText, headers } = response;
@@ -18230,7 +18309,7 @@ var HEAD_MAX = 16 * 1024;
18230
18309
  var ANY_PLACEHOLDER = /fnox_proxy_[0-9a-f]{24}/g;
18231
18310
  var REQUEST_LINE2 = /^([!#$%&'*+.^_`|~0-9A-Za-z-]+) ([\x21-\x7e]+) HTTP\/1\.[01]$/;
18232
18311
  var HEADER_LINE = /^([!#$%&'*+.^_`|~0-9A-Za-z-]+):[ \t]*(.*?)[ \t]*$/;
18233
- var BASIC = /^(Basic[ \t]+)([A-Za-z0-9+/]+={0,2})$/i;
18312
+ var BASIC2 = /^(Basic[ \t]+)([A-Za-z0-9+/]+={0,2})$/i;
18234
18313
  var encoder8 = new TextEncoder();
18235
18314
  function binary(text) {
18236
18315
  let out = "";
@@ -18246,7 +18325,7 @@ function sniffHttp1(start2) {
18246
18325
  return "no";
18247
18326
  }
18248
18327
  function basicOf(value2) {
18249
- const m = BASIC.exec(value2);
18328
+ const m = BASIC2.exec(value2);
18250
18329
  if (!m) return void 0;
18251
18330
  try {
18252
18331
  return { scheme: m[1], decoded: atob(m[2]) };
@@ -25254,7 +25333,8 @@ function replayingHops(inner, heldMs = HELD_MS) {
25254
25333
  return { ...inner.traits, manualRedirects: true };
25255
25334
  },
25256
25335
  ...inner.websocket ? { websocket: inner.websocket.bind(inner) } : {},
25257
- async fetch(request, owner = KERNEL) {
25336
+ async fetch(request, caller) {
25337
+ const owner = caller ?? KERNEL;
25258
25338
  const key = keyOf3(owner, request.method, request.url);
25259
25339
  const waiting = held.get(key);
25260
25340
  if (waiting && waiting.fingerprint === fingerprint(request.headers)) {
@@ -25263,7 +25343,7 @@ function replayingHops(inner, heldMs = HELD_MS) {
25263
25343
  return replay(waiting);
25264
25344
  }
25265
25345
  if (waiting) drop(key);
25266
- const response = await inner.fetch(request);
25346
+ const response = await inner.fetch(request, caller);
25267
25347
  if (!response.redirects?.length) return response;
25268
25348
  return replay({
25269
25349
  owner,
@@ -30990,7 +31070,7 @@ var Launcher = class {
30990
31070
  ...options.env
30991
31071
  };
30992
31072
  this.ca = kernelCa(options.caStore ?? memoryCaStore());
30993
- this.transport = replayingHops(options.transport ?? missingTransport());
31073
+ this.transport = placeholderFloor(replayingHops(options.transport ?? missingTransport()));
30994
31074
  this.announcedTraits = JSON.stringify(this.transport.traits);
30995
31075
  this.uplink = options.uplink;
30996
31076
  this.routes = new Routes(options.uplink?.traits.ipv6 === true);