frogoe 0.3.0 → 0.3.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 (2) hide show
  1. package/dist/cli.js +55 -21
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -183,19 +183,18 @@ var init_init = __esm({
183
183
  // src/add.ts
184
184
  import { cpSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
185
185
  import path2 from "path";
186
- var STYLE_PATTERN, MARKUP_PATTERN, parseBlock, blockMarker, injectIntoHtml, addBlock;
186
+ var parseBlock, blockMarker, injectIntoHtml, addBlock;
187
187
  var init_add = __esm({
188
188
  "src/add.ts"() {
189
189
  "use strict";
190
190
  init_init();
191
- STYLE_PATTERN = /<style>([\s\S]*?)<\/style>/u;
192
- MARKUP_PATTERN = /<\/style>\s*([\s\S]*)$/u;
193
191
  parseBlock = (source) => {
194
- const styleMatch = STYLE_PATTERN.exec(source);
195
- const markupMatch = MARKUP_PATTERN.exec(source);
192
+ const styleOpen = source.indexOf("<style>");
193
+ const styleClose = source.indexOf("</style>");
194
+ const css = styleOpen === -1 || styleClose === -1 || styleClose < styleOpen ? null : source.slice(styleOpen + "<style>".length, styleClose);
196
195
  return {
197
- css: styleMatch?.[1]?.trim() ?? null,
198
- markup: (markupMatch?.[1] ?? "").trim()
196
+ css: css?.trim() ?? null,
197
+ markup: (styleClose === -1 ? "" : source.slice(styleClose + "</style>".length)).trim()
199
198
  };
200
199
  };
201
200
  blockMarker = (name) => `<!-- frogoe:block:${name} -->`;
@@ -723,11 +722,32 @@ var init_bundle2 = __esm({
723
722
  });
724
723
 
725
724
  // ../lint/src/brief.ts
726
- var stripComment, parseBrief;
725
+ var KEY_PATTERN, WS, stripComment, parseLine, parseBrief;
727
726
  var init_brief = __esm({
728
727
  "../lint/src/brief.ts"() {
729
728
  "use strict";
730
- stripComment = (value) => value.replace(/\s+#.*$/u, "").trim().replace(/^["']|["']$/gu, "");
729
+ KEY_PATTERN = /^[a-z-]+$/u;
730
+ WS = /\s/u;
731
+ stripComment = (value) => {
732
+ let cut = -1;
733
+ for (let i = 1; i < value.length; i += 1) {
734
+ if (value[i] === "#" && WS.test(value[i - 1] ?? "")) {
735
+ cut = i;
736
+ break;
737
+ }
738
+ }
739
+ return (cut === -1 ? value : value.slice(0, cut)).trim().replace(/^["']|["']$/gu, "");
740
+ };
741
+ parseLine = (line) => {
742
+ let indent = 0;
743
+ while (indent < line.length && line[indent] === " ") indent += 1;
744
+ const body = line.slice(indent);
745
+ const colon = body.indexOf(":");
746
+ if (colon === -1) return null;
747
+ const key = body.slice(0, colon);
748
+ if (!KEY_PATTERN.test(key)) return null;
749
+ return { indent, key, rest: body.slice(colon + 1) };
750
+ };
731
751
  parseBrief = (source) => {
732
752
  const match = /^---\r?\n([\s\S]*?)\r?\n---/u.exec(source);
733
753
  if (!match) {
@@ -739,20 +759,20 @@ var init_brief = __esm({
739
759
  if (rawLine.trim() === "") {
740
760
  continue;
741
761
  }
742
- const nested = /^\s{2,}([a-z-]+):\s*(.*)$/u.exec(rawLine);
743
- const top = /^([a-z-]+):\s*(.*)$/u.exec(rawLine);
744
- if (nested && section === "palette") {
745
- const key = nested[1];
746
- brief[key] = stripComment(nested[2] ?? "");
762
+ const parsed = parseLine(rawLine);
763
+ if (!parsed) {
764
+ continue;
765
+ }
766
+ if (parsed.indent >= 2 && section === "palette") {
767
+ brief[parsed.key] = stripComment(parsed.rest);
747
768
  continue;
748
769
  }
749
- if (top) {
750
- section = top[1] ?? "";
770
+ if (parsed.indent === 0) {
771
+ section = parsed.key;
751
772
  if (section === "palette") {
752
773
  continue;
753
774
  }
754
- const key = section;
755
- brief[key] = stripComment(top[2] ?? "");
775
+ brief[parsed.key] = stripComment(parsed.rest);
756
776
  }
757
777
  }
758
778
  return brief;
@@ -2799,12 +2819,21 @@ import { existsSync as existsSync6, mkdirSync as mkdirSync6, chmodSync, writeFil
2799
2819
  import os3 from "os";
2800
2820
  import path9 from "path";
2801
2821
  import { gunzipSync } from "zlib";
2802
- var URL_PATTERN, parseTunnelUrl, octalAt, extractSingleFile, ENV_PIN, assetName, binaryFileName, cacheBase, resolveLatestTag, mb, downloadWithProgress, binaryEchoes, resolveBinary, startTunnel;
2822
+ var URL_PATTERN, parseTunnelUrl, TAG_PATTERN, assertSafeTag, octalAt, extractSingleFile, ENV_PIN, assetName, binaryFileName, cacheBase, resolveLatestTag, mb, downloadWithProgress, binaryEchoes, resolveBinary, startTunnel;
2803
2823
  var init_tunnel = __esm({
2804
2824
  "src/net/tunnel.ts"() {
2805
2825
  "use strict";
2806
2826
  URL_PATTERN = /https:\/\/[a-z0-9-]+\.trycloudflare\.com/iu;
2807
2827
  parseTunnelUrl = (chunk) => URL_PATTERN.exec(chunk)?.[0];
2828
+ TAG_PATTERN = /^\d{4}\.\d+\.\d+(-[A-Za-z0-9.]+)?$/u;
2829
+ assertSafeTag = (tag) => {
2830
+ if (!TAG_PATTERN.test(tag)) {
2831
+ throw new Error(
2832
+ `cloudflared version "${tag}" is not a valid release tag (expected e.g. 2025.10.1)`
2833
+ );
2834
+ }
2835
+ return tag;
2836
+ };
2808
2837
  octalAt = (block, offset, length) => {
2809
2838
  const raw = block.subarray(offset, offset + length).toString("utf-8");
2810
2839
  const digits = raw.replace(/[\0 ]/gu, "");
@@ -2897,10 +2926,15 @@ var init_tunnel = __esm({
2897
2926
  `cloudflared publishes no build for ${platform}/${process.arch} \u2014 install it and put \`cloudflared\` on PATH`
2898
2927
  );
2899
2928
  }
2900
- const tag = process.env[ENV_PIN] ?? await resolveLatestTag();
2929
+ const tag = process.env[ENV_PIN] ? assertSafeTag(process.env[ENV_PIN]) : assertSafeTag(await resolveLatestTag());
2901
2930
  const root = path9.join(cacheBase(platform, process.env, os3.homedir()), "frogoe", "cloudflared");
2902
2931
  const dir = path9.join(root, tag);
2903
2932
  const bin = path9.join(dir, binaryFileName(platform));
2933
+ const rootResolved = path9.resolve(root);
2934
+ const binResolved = path9.resolve(bin);
2935
+ if (!binResolved.startsWith(rootResolved + path9.sep)) {
2936
+ throw new Error("cloudflared binary path escaped the frogoe cache \u2014 refusing to execute");
2937
+ }
2904
2938
  if (existsSync6(bin) && binaryEchoes(bin, tag)) return { downloaded: false, path: bin };
2905
2939
  onProgress?.(`downloading cloudflared ${tag} (~25 MB, once)\u2026`);
2906
2940
  const res = await fetch(
@@ -3601,7 +3635,7 @@ import { defineCommand as defineCommand9, runMain } from "citty";
3601
3635
  // package.json
3602
3636
  var package_default = {
3603
3637
  name: "frogoe",
3604
- version: "0.3.0",
3638
+ version: "0.3.1",
3605
3639
  description: "froge CLI \u2014 the agent's hands: init, add, run, check, bundle",
3606
3640
  homepage: "https://github.com/frogoe/engine#readme",
3607
3641
  bugs: "https://github.com/frogoe/engine/issues",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frogoe",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "froge CLI — the agent's hands: init, add, run, check, bundle",
5
5
  "homepage": "https://github.com/frogoe/engine#readme",
6
6
  "bugs": "https://github.com/frogoe/engine/issues",