@pretense/cli 0.6.18 → 0.6.19

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.
@@ -17,7 +17,7 @@ function versionFromPackageJson() {
17
17
  return void 0;
18
18
  }
19
19
  }
20
- var PRETENSE_VERSION = (true ? "0.6.18" : void 0) ?? versionFromPackageJson() ?? "0.0.0-unknown";
20
+ var PRETENSE_VERSION = (true ? "0.6.19" : void 0) ?? versionFromPackageJson() ?? "0.0.0-unknown";
21
21
 
22
22
  export {
23
23
  PRETENSE_VERSION
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  PRETENSE_VERSION
4
- } from "./chunk-QT5E625F.js";
4
+ } from "./chunk-XY4NRTOT.js";
5
5
  import {
6
6
  __commonJS,
7
7
  __toESM,
@@ -11952,6 +11952,48 @@ var EXTENDED_PATTERNS = [
11952
11952
  defaultAction: "block",
11953
11953
  pattern: /-----BEGIN (?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY(?: BLOCK)?-----[ \t]*\r?\n(?:[ \t]*\r?\n|[ \t]*[A-Za-z][A-Za-z0-9_-]{0,40}:[^\r\n]{0,1000}\r?\n){0,40}(?:[ \t]*[A-Za-z0-9+/=]{16,80}[ \t]*(?:\r?\n|$)){1,400}/g
11954
11954
  },
11955
+ // ESCAPED SINGLE-LINE PEM private key — the `.env` / JSON / k8s-secret / CI-var
11956
+ // idiom where the key is stored as ONE line with LITERAL `\n` (backslash-n)
11957
+ // escape sequences instead of real newlines:
11958
+ //
11959
+ // PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nMIIE…\n-----END RSA PRIVATE KEY-----"
11960
+ //
11961
+ // WHY THIS EXISTS (P0 egress, v0.6.19). Both END-anchored PEM detectors above
11962
+ // (`private-key-block`, `private-key-body`) require a REAL newline (`\r?\n`,
11963
+ // 0x0A) after the banner and a base64 body drawn from `[A-Za-z0-9+/=\s]`. In
11964
+ // the escaped form the separators are the two literal characters `\` + `n`,
11965
+ // and a backslash is in NEITHER body charset — so those detectors never match,
11966
+ // and only the banner-only `private-key` detector (patterns.ts) fires. That
11967
+ // spans just `-----BEGIN … KEY-----`; mutate/redact then rewrites the BANNER
11968
+ // and leaves the real base64 body verbatim on the wire, while `audit` reports
11969
+ // `detectorKinds:["private-key"]` — a FALSE assurance that the key was handled.
11970
+ // Confirmed leaking against the shipped 0.6.18 engine (mutate + proxy egress).
11971
+ //
11972
+ // This detector spans the WHOLE escaped block (banner → body → END) so the
11973
+ // mutator's PEM branch replaces the entire key, not just the marker. Being the
11974
+ // LONGER same-severity match it wins interval-dedup over the banner-only
11975
+ // `private-key`, exactly as `private-key-block` does for real multi-line keys.
11976
+ //
11977
+ // PRECISION / no prose-destruction. END-ANCHORED with a `\1` BACKREFERENCE, so
11978
+ // a `BEGIN RSA …` can only close on `-----END RSA …-----` (never a far-away
11979
+ // unrelated END). The body charset is base64 (`[A-Za-z0-9+/=]`) plus the
11980
+ // literal escape sequences `\n`/`\r`/`\t` and space/tab ONLY — ordinary prose
11981
+ // (`.`, `,`, `:`, other punctuation) STOPS the match at the first such char, so
11982
+ // this can never swallow a document. Real MULTI-LINE PEMs contain 0x0A newline
11983
+ // characters, which are in neither branch of the body class, so this detector
11984
+ // does NOT match them — they stay owned by `private-key-block`.
11985
+ //
11986
+ // ReDoS-safe: the two body alternatives are disjoint on their first character
11987
+ // (`\\[rnt]` begins with a backslash; the class excludes backslash), so every
11988
+ // position has exactly one parse; the quantifier is lazy, bounded at 8000, and
11989
+ // terminated by the required `-----END` anchor.
11990
+ {
11991
+ name: "private-key-escaped",
11992
+ category: "secret",
11993
+ severity: "critical",
11994
+ defaultAction: "block",
11995
+ pattern: /-----BEGIN ((?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY(?: BLOCK)?)-----(?:\\[rnt]|[A-Za-z0-9+/= \t]){1,8000}?-----END \1-----/g
11996
+ },
11955
11997
  // AWS *temporary* (STS) access key — `ASIA` + 16. STRICT by design (review
11956
11998
  // fix): the first cut widened the critical/BLOCK `aws-access-key` detector to
11957
11999
  // `(?:AKIA|ASIA)[0-9A-Z]{16}`, which hard-400'd benign traffic because `ASIA`
@@ -12308,6 +12350,32 @@ var SECRET_PATTERNS = [
12308
12350
  defaultAction: "block",
12309
12351
  pattern: /\brk_(?:test|live)_[A-Za-z0-9]{20,}\b/g
12310
12352
  },
12353
+ {
12354
+ // Pretense's OWN API key (`prtns_live_…` / `prtns_test_…`), minted by the
12355
+ // backend `/api/cli/auth/validate`. VALUE-DRIVEN by construction: the
12356
+ // `prtns_(live|test)_` prefix is matched on the LITERAL wherever it appears,
12357
+ // regardless of the assignee's name or the source language.
12358
+ //
12359
+ // WHY THIS DETECTOR EXISTS (P0 egress, v0.6.19). A live `prtns_live_` token
12360
+ // assigned to a variable whose name is NOT a recognised secret-label tail —
12361
+ // `INTERNAL_HMAC_KEY = "prtns_live_…"` (bare `key` and the compound
12362
+ // `hmac_key` are BOTH deliberately absent from SECRET_LABEL_TAILS), or
12363
+ // `InternalHmacKey = …` — matched NO named detector, so it egressed to the
12364
+ // LLM in cleartext and survived `mutate --stdout`. Only tokens that happened
12365
+ // to land in a `…token`/`…secret`/`…password`-suffixed binding were caught,
12366
+ // an inconsistency that depended on the variable name and therefore on the
12367
+ // language's naming convention. A credential must be caught on its own shape.
12368
+ //
12369
+ // Precision: the `prtns_(live|test)_` prefix plus a 16+ base62 body is a
12370
+ // near-zero-false-positive signal — nothing benign carries it — so this is
12371
+ // safe as an unlabelled, value-driven detector on the always-mutate egress
12372
+ // path, exactly like the Stripe `sk_live_` / GitHub `ghp_` prefixes above.
12373
+ name: "pretense-api-key",
12374
+ category: "secret",
12375
+ severity: "critical",
12376
+ defaultAction: "block",
12377
+ pattern: /\bprtns_(?:live|test)_[A-Za-z0-9]{16,}\b/g
12378
+ },
12311
12379
  // Communications
12312
12380
  {
12313
12381
  name: "slack-token",
@@ -12869,7 +12937,7 @@ var ENV_PATTERNS = [
12869
12937
  // specific env-var names rather than generic secret-label tails, so they do
12870
12938
  // not belong in the shared vocabulary.
12871
12939
  pattern: new RegExp(
12872
- `(?<![A-Za-z0-9])(?:[A-Z0-9]+[._-])*(?:${ENV_SECRET_LABEL_ALTERNATION}|DATABASE_URL|VAULT_TOKEN)\\s*[=:]\\s*(?!['"\\s])(?!\\$)(?!process\\.env)(?!os\\.environ)(?![A-Za-z][A-Za-z0-9+.-]*:\\/\\/)(?!sk[-_]|pk_|rk_|whsec_|xox[bpors]-|ghp_|gho_|ghs_|glpat-|hf_|AKIA|AIza)[A-Za-z0-9/+._@:!#%^&*?~-]{8,}`,
12940
+ `(?<![A-Za-z0-9])(?:[A-Z0-9]+[._-])*(?:${ENV_SECRET_LABEL_ALTERNATION}|DATABASE_URL|VAULT_TOKEN)\\s*[=:]\\s*(?!['"\\s])(?!\\$)(?!process\\.env)(?!os\\.environ)(?![A-Za-z][A-Za-z0-9+.-]*:\\/\\/)(?!sk[-_]|pk_|rk_|whsec_|xox[bpors]-|ghp_|gho_|ghs_|glpat-|hf_|prtns_(?:live|test)_|AKIA|AIza)[A-Za-z0-9/+._@:!#%^&*?~-]{8,}`,
12873
12941
  "gi"
12874
12942
  ),
12875
12943
  // PRECISION: reject `PASSWORD=changeme`, `PASSWORD=<your-password>` and
@@ -15633,7 +15701,7 @@ ${end}`;
15633
15701
  }
15634
15702
  const shaped = shapePreservingSynthetic(finding.type, v, digest);
15635
15703
  if (shaped !== null) return shaped;
15636
- const prefix = v.match(/^(?:sk_live_|sk_test_|pk_live_|pk_test_|ghp_|gho_|ghu_|ghs_|ghr_|AKIA|ASIA|AIza|xoxb-|xoxp-|xoxa-|xoxr-|hf_|eyJ)/)?.[0] ?? "";
15704
+ const prefix = v.match(/^(?:sk_live_|sk_test_|pk_live_|pk_test_|prtns_live_|prtns_test_|ghp_|gho_|ghu_|ghs_|ghr_|AKIA|ASIA|AIza|xoxb-|xoxp-|xoxa-|xoxr-|hf_|eyJ)/)?.[0] ?? "";
15637
15705
  const fillerLen = Math.max(1, v.length - prefix.length);
15638
15706
  const filler = digest.repeat(Math.ceil(fillerLen / digest.length)).slice(0, fillerLen);
15639
15707
  return prefix + filler;
@@ -16514,11 +16582,11 @@ function versionFromCliPackageJson() {
16514
16582
  return void 0;
16515
16583
  }
16516
16584
  function productVersion() {
16517
- return override ?? (true ? "0.6.18" : void 0) ?? versionFromCliPackageJson() ?? "0.0.0-unknown";
16585
+ return override ?? (true ? "0.6.19" : void 0) ?? versionFromCliPackageJson() ?? "0.0.0-unknown";
16518
16586
  }
16519
16587
  var UNKNOWN_COMMIT = "unknown";
16520
16588
  function bakedCommitSha() {
16521
- return "220d098b1829361f3d0043fb24275e5fdfb84429".length > 0 ? "220d098b1829361f3d0043fb24275e5fdfb84429" : UNKNOWN_COMMIT;
16589
+ return "79bc3b0f2c6a2ff139ae392d2de37679a06308a6".length > 0 ? "79bc3b0f2c6a2ff139ae392d2de37679a06308a6" : UNKNOWN_COMMIT;
16522
16590
  }
16523
16591
  var FEATURE_TIERS = {
16524
16592
  compliance_export: "pro",
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  PRETENSE_VERSION
4
- } from "./chunk-QT5E625F.js";
4
+ } from "./chunk-XY4NRTOT.js";
5
5
  import {
6
6
  init_esm_shims
7
7
  } from "./chunk-TWMRHZGM.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pretense/cli",
3
- "version": "0.6.18",
3
+ "version": "0.6.19",
4
4
  "description": "Local-first AI firewall that mutates proprietary code before sending to LLM APIs",
5
5
  "type": "module",
6
6
  "bin": {
@@ -24,8 +24,8 @@
24
24
  "typescript": "^5.4.0",
25
25
  "vitest": "^1.0.0",
26
26
  "@pretense/billing": "0.1.0",
27
- "@pretense/protocol": "0.1.0",
28
27
  "@pretense/compliance-engine": "0.1.0",
28
+ "@pretense/protocol": "0.1.0",
29
29
  "@pretense/learner": "0.2.0",
30
30
  "@pretense/mutator": "0.2.0",
31
31
  "@pretense/proxy": "0.1.0",