@moda-ai/cli 1.55.12 → 1.55.14
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/{agent-rd9deae9.js → agent-y47qgmf1.js} +3 -3
- package/dist/{cli-m0fa54ny.js → cli-k9nae6t9.js} +1136 -197
- package/dist/{cli-90hb4ng0.js → cli-ndn5m6wn.js} +3 -3
- package/dist/{cli-34zdvcpg.js → cli-weqp7xc1.js} +2 -2
- package/dist/cli.js +30 -17
- package/dist/{doctor-8yb6r66e.js → doctor-grvx6xx0.js} +3 -3
- package/dist/{fix-bt5zn07e.js → fix-91sr76gw.js} +2 -2
- package/dist/{harness-github-actions-nph5t2s7.js → harness-github-actions-tmy3gqwa.js} +1 -1
- package/dist/{harness-9psndqtm.js → harness-vm0xd80p.js} +1 -1
- package/dist/{index-qjaprhrv.js → index-f6cydfxg.js} +3 -3
- package/dist/prompt-source-mcp.js +1 -1
- package/dist/{prompts-mzazn8ce.js → prompts-kw5kzm39.js} +2 -2
- package/dist/{sync-gkwexz68.js → sync-xv04wnth.js} +2 -2
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
|
@@ -10304,7 +10304,7 @@ var require_typescript = __commonJS((exports, module) => {
|
|
|
10304
10304
|
identity: () => identity2,
|
|
10305
10305
|
identitySourceMapConsumer: () => identitySourceMapConsumer,
|
|
10306
10306
|
ignoreSourceNewlines: () => ignoreSourceNewlines,
|
|
10307
|
-
ignoredPaths: () =>
|
|
10307
|
+
ignoredPaths: () => ignoredPaths2,
|
|
10308
10308
|
importFromModuleSpecifier: () => importFromModuleSpecifier,
|
|
10309
10309
|
importSyntaxAffectsModuleResolution: () => importSyntaxAffectsModuleResolution,
|
|
10310
10310
|
indexOfAnyCharCode: () => indexOfAnyCharCode,
|
|
@@ -16689,7 +16689,7 @@ ${lanes.join(`
|
|
|
16689
16689
|
function getFileWatcherEventKind(oldTime, newTime) {
|
|
16690
16690
|
return oldTime === 0 ? 0 : newTime === 0 ? 2 : 1;
|
|
16691
16691
|
}
|
|
16692
|
-
var
|
|
16692
|
+
var ignoredPaths2 = ["/node_modules/.", "/.git", "/.#"];
|
|
16693
16693
|
var curSysLog = noop;
|
|
16694
16694
|
function sysLog(s) {
|
|
16695
16695
|
return curSysLog(s);
|
|
@@ -16907,7 +16907,7 @@ ${lanes.join(`
|
|
|
16907
16907
|
}
|
|
16908
16908
|
}
|
|
16909
16909
|
function isIgnoredPath(path, options) {
|
|
16910
|
-
return some(
|
|
16910
|
+
return some(ignoredPaths2, (searchPath) => isInPath(path, searchPath)) || isIgnoredByWatchOptions(path, options, useCaseSensitiveFileNames2, getCurrentDirectory);
|
|
16911
16911
|
}
|
|
16912
16912
|
function isInPath(path, searchPath) {
|
|
16913
16913
|
if (path.includes(searchPath))
|
|
@@ -31305,7 +31305,7 @@ ${lanes.join(`
|
|
|
31305
31305
|
}
|
|
31306
31306
|
}
|
|
31307
31307
|
function containsIgnoredPath(path) {
|
|
31308
|
-
return some(
|
|
31308
|
+
return some(ignoredPaths2, (p2) => path.includes(p2));
|
|
31309
31309
|
}
|
|
31310
31310
|
function getContainingNodeArray(node) {
|
|
31311
31311
|
if (!node.parent)
|
|
@@ -75258,11 +75258,11 @@ ${lanes.join(`
|
|
|
75258
75258
|
const resolved = resolveStructuredTypeMembers(type);
|
|
75259
75259
|
return !!(resolved.callSignatures.length || resolved.constructSignatures.length || resolved.members.get("bind") && isTypeSubtypeOf(type, globalFunctionType));
|
|
75260
75260
|
}
|
|
75261
|
-
function getTypeFacts(type,
|
|
75262
|
-
return getTypeFactsWorker(type,
|
|
75261
|
+
function getTypeFacts(type, mask22) {
|
|
75262
|
+
return getTypeFactsWorker(type, mask22) & mask22;
|
|
75263
75263
|
}
|
|
75264
|
-
function hasTypeFacts(type,
|
|
75265
|
-
return getTypeFacts(type,
|
|
75264
|
+
function hasTypeFacts(type, mask22) {
|
|
75265
|
+
return getTypeFacts(type, mask22) !== 0;
|
|
75266
75266
|
}
|
|
75267
75267
|
function getTypeFactsWorker(type, callerOnlyNeeds) {
|
|
75268
75268
|
if (type.flags & (2097152 | 465829888)) {
|
|
@@ -110604,14 +110604,14 @@ ${lanes.join(`
|
|
|
110604
110604
|
return factory2.createModifiersFromModifierFlags(newFlags);
|
|
110605
110605
|
}
|
|
110606
110606
|
function ensureModifierFlags(node) {
|
|
110607
|
-
let
|
|
110607
|
+
let mask22 = 131071 ^ (1 | 1024 | 16);
|
|
110608
110608
|
let additions = needsDeclare && !isAlwaysType(node) ? 128 : 0;
|
|
110609
110609
|
const parentIsFile = node.parent.kind === 308;
|
|
110610
110610
|
if (!parentIsFile || isBundledEmit && parentIsFile && isExternalModule(node.parent)) {
|
|
110611
|
-
|
|
110611
|
+
mask22 ^= 128;
|
|
110612
110612
|
additions = 0;
|
|
110613
110613
|
}
|
|
110614
|
-
return maskModifierFlags(node,
|
|
110614
|
+
return maskModifierFlags(node, mask22, additions);
|
|
110615
110615
|
}
|
|
110616
110616
|
function transformHeritageClauses(nodes) {
|
|
110617
110617
|
return factory2.createNodeArray(filter(map(nodes, (clause) => factory2.updateHeritageClause(clause, visitNodes2(factory2.createNodeArray(filter(clause.types, (t) => {
|
|
@@ -121243,7 +121243,7 @@ ${lanes.join(`
|
|
|
121243
121243
|
if (endsWith(path, "/node_modules/.staging")) {
|
|
121244
121244
|
return removeSuffix(path, "/.staging");
|
|
121245
121245
|
}
|
|
121246
|
-
return some(
|
|
121246
|
+
return some(ignoredPaths2, (searchPath) => path.includes(searchPath)) ? undefined : path;
|
|
121247
121247
|
}
|
|
121248
121248
|
function perceivedOsRootLengthForWatching(pathComponents2, length2) {
|
|
121249
121249
|
if (length2 <= 1)
|
|
@@ -163646,20 +163646,20 @@ ${options.prefix}` : `
|
|
|
163646
163646
|
return rulesMapCache;
|
|
163647
163647
|
}
|
|
163648
163648
|
function getRuleActionExclusion(ruleAction) {
|
|
163649
|
-
let
|
|
163649
|
+
let mask22 = 0;
|
|
163650
163650
|
if (ruleAction & 1) {
|
|
163651
|
-
|
|
163651
|
+
mask22 |= 28;
|
|
163652
163652
|
}
|
|
163653
163653
|
if (ruleAction & 2) {
|
|
163654
|
-
|
|
163654
|
+
mask22 |= 96;
|
|
163655
163655
|
}
|
|
163656
163656
|
if (ruleAction & 28) {
|
|
163657
|
-
|
|
163657
|
+
mask22 |= 28;
|
|
163658
163658
|
}
|
|
163659
163659
|
if (ruleAction & 96) {
|
|
163660
|
-
|
|
163660
|
+
mask22 |= 96;
|
|
163661
163661
|
}
|
|
163662
|
-
return
|
|
163662
|
+
return mask22;
|
|
163663
163663
|
}
|
|
163664
163664
|
function createRulesMap(rules) {
|
|
163665
163665
|
const map2 = buildMap(rules);
|
|
@@ -163704,7 +163704,7 @@ ${options.prefix}` : `
|
|
|
163704
163704
|
return row * mapRowLength + column;
|
|
163705
163705
|
}
|
|
163706
163706
|
var maskBitSize = 5;
|
|
163707
|
-
var
|
|
163707
|
+
var mask2 = 31;
|
|
163708
163708
|
var mapRowLength = 166 + 1;
|
|
163709
163709
|
var RulesPosition = ((RulesPosition2) => {
|
|
163710
163710
|
RulesPosition2[RulesPosition2["StopRulesSpecific"] = 0] = "StopRulesSpecific";
|
|
@@ -163724,15 +163724,15 @@ ${options.prefix}` : `
|
|
|
163724
163724
|
function getInsertionIndex(indexBitmap, maskPosition) {
|
|
163725
163725
|
let index = 0;
|
|
163726
163726
|
for (let pos = 0;pos <= maskPosition; pos += maskBitSize) {
|
|
163727
|
-
index += indexBitmap &
|
|
163727
|
+
index += indexBitmap & mask2;
|
|
163728
163728
|
indexBitmap >>= maskBitSize;
|
|
163729
163729
|
}
|
|
163730
163730
|
return index;
|
|
163731
163731
|
}
|
|
163732
163732
|
function increaseInsertionIndex(indexBitmap, maskPosition) {
|
|
163733
|
-
const value = (indexBitmap >> maskPosition &
|
|
163734
|
-
Debug.assert((value &
|
|
163735
|
-
return indexBitmap & ~(
|
|
163733
|
+
const value = (indexBitmap >> maskPosition & mask2) + 1;
|
|
163734
|
+
Debug.assert((value & mask2) === value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules.");
|
|
163735
|
+
return indexBitmap & ~(mask2 << maskPosition) | value << maskPosition;
|
|
163736
163736
|
}
|
|
163737
163737
|
function createTextRangeWithKind(pos, end, kind) {
|
|
163738
163738
|
const textRangeWithKind = { pos, end, kind };
|
|
@@ -166304,7 +166304,7 @@ ${options.prefix}` : `
|
|
|
166304
166304
|
identity: () => identity2,
|
|
166305
166305
|
identitySourceMapConsumer: () => identitySourceMapConsumer,
|
|
166306
166306
|
ignoreSourceNewlines: () => ignoreSourceNewlines,
|
|
166307
|
-
ignoredPaths: () =>
|
|
166307
|
+
ignoredPaths: () => ignoredPaths2,
|
|
166308
166308
|
importFromModuleSpecifier: () => importFromModuleSpecifier,
|
|
166309
166309
|
importSyntaxAffectsModuleResolution: () => importSyntaxAffectsModuleResolution,
|
|
166310
166310
|
indexOfAnyCharCode: () => indexOfAnyCharCode,
|
|
@@ -177901,7 +177901,7 @@ import {
|
|
|
177901
177901
|
lstatSync as lstatSync10,
|
|
177902
177902
|
mkdtempSync as mkdtempSync2,
|
|
177903
177903
|
mkdirSync as mkdirSync6,
|
|
177904
|
-
readFileSync as
|
|
177904
|
+
readFileSync as readFileSync16,
|
|
177905
177905
|
readdirSync as readdirSync4,
|
|
177906
177906
|
writeFileSync as writeFileSync6,
|
|
177907
177907
|
rmSync as rmSync4
|
|
@@ -180097,7 +180097,7 @@ async function remoteAnalyzeFetch(url, apiKey, init, timeoutMs) {
|
|
|
180097
180097
|
|
|
180098
180098
|
// src/harness-register/register.ts
|
|
180099
180099
|
import * as fs from "node:fs";
|
|
180100
|
-
import { mkdtempSync, readFileSync as
|
|
180100
|
+
import { mkdtempSync, readFileSync as readFileSync6, rmSync as rmSync3 } from "node:fs";
|
|
180101
180101
|
import { Readable as Readable2 } from "node:stream";
|
|
180102
180102
|
import { tmpdir } from "node:os";
|
|
180103
180103
|
import { basename as basename4, join as join8, resolve as resolve4 } from "node:path";
|
|
@@ -180105,7 +180105,7 @@ import { basename as basename4, join as join8, resolve as resolve4 } from "node:
|
|
|
180105
180105
|
// src/harness-register/collect-adapter.ts
|
|
180106
180106
|
import { createHash as createHash4 } from "node:crypto";
|
|
180107
180107
|
import { execFileSync } from "node:child_process";
|
|
180108
|
-
import { copyFileSync, createReadStream, existsSync as existsSync6, mkdirSync as mkdirSync4,
|
|
180108
|
+
import { copyFileSync, createReadStream, existsSync as existsSync6, mkdirSync as mkdirSync4, realpathSync as realpathSync4, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
180109
180109
|
import { dirname as dirname5, join as join7 } from "node:path";
|
|
180110
180110
|
|
|
180111
180111
|
// ../../packages/harness-bundle/src/contract.ts
|
|
@@ -185388,15 +185388,16 @@ var CACHE_FILE_PATTERNS = [
|
|
|
185388
185388
|
[/^\.yarn-integrity$/, "yarn_integrity"],
|
|
185389
185389
|
[/^install-state\.gz$/, "yarn_install_state"]
|
|
185390
185390
|
];
|
|
185391
|
-
var
|
|
185391
|
+
var ENV_TEMPLATE_WORDS = new Set(["example", "examples", "sample", "template", "dist", "tpl", "default", "defaults"]);
|
|
185392
185392
|
function isEnvExampleName(name) {
|
|
185393
185393
|
const lower = name.toLowerCase();
|
|
185394
|
-
|
|
185395
|
-
|
|
185396
|
-
|
|
185397
|
-
|
|
185398
|
-
return
|
|
185394
|
+
const base = /^(\.env|\.dev\.vars|env)\./.exec(lower);
|
|
185395
|
+
if (base)
|
|
185396
|
+
return lower.slice(base[0].length).split(".").some((part) => ENV_TEMPLATE_WORDS.has(part));
|
|
185397
|
+
const named = /^(.+)\.env$/.exec(lower);
|
|
185398
|
+
return named !== null && named[1].split(".").some((part) => ENV_TEMPLATE_WORDS.has(part));
|
|
185399
185399
|
}
|
|
185400
|
+
var ENV_VALUE_FILE_RULES = new Set(["dotenv", "direnv", "wrangler_dev_vars"]);
|
|
185400
185401
|
function secretPathRule(path) {
|
|
185401
185402
|
const name = basenameOf(path);
|
|
185402
185403
|
const lower = name.toLowerCase();
|
|
@@ -185417,7 +185418,7 @@ function secretPathRule(path) {
|
|
|
185417
185418
|
return "key_material_file";
|
|
185418
185419
|
if (/^id_(rsa|dsa|ecdsa|ed25519)/.test(lower))
|
|
185419
185420
|
return "ssh_key";
|
|
185420
|
-
if (
|
|
185421
|
+
if (/^credentials(\.(json|ya?ml|toml|conf|cfg|ini|txt|env|properties|xml|csv))?$/.test(lower) || /\.credentials$/.test(lower)) {
|
|
185421
185422
|
return "credentials_file";
|
|
185422
185423
|
}
|
|
185423
185424
|
if (/(^|\/)\.aws\/(credentials|config)$/.test(lowerPath))
|
|
@@ -185453,34 +185454,58 @@ function secretPathRule(path) {
|
|
|
185453
185454
|
return "secrets_file";
|
|
185454
185455
|
return null;
|
|
185455
185456
|
}
|
|
185456
|
-
|
|
185457
|
+
var PROVIDER_MARKER = /^(?:sk-ant-(?:api|admin|oat)\d{2}-|sk-or-v1-|sk-(?:proj|svcacct|admin)-|sk-|(?:sk|rk)_(?:live|test)_|gh[pousr]_|github_pat_|glpat-|xox[abposr]-|whsec_|gsk_|hf_|xai-|npm_|pypi-|do[opr]_v1_|shp(?:at|ca|pa|ss)_|moda_(?:sk|ct)_)/;
|
|
185458
|
+
function registryAuthFindings(path, text) {
|
|
185457
185459
|
const name = basenameOf(path).toLowerCase();
|
|
185458
185460
|
const literal = (value) => value.trim() !== "" && !/^["']?\$\{?[A-Za-z_]/.test(value.trim());
|
|
185459
|
-
|
|
185460
|
-
|
|
185461
|
-
|
|
185462
|
-
|
|
185463
|
-
|
|
185464
|
-
|
|
185465
|
-
|
|
185466
|
-
|
|
185467
|
-
|
|
185468
|
-
|
|
185469
|
-
|
|
185470
|
-
|
|
185471
|
-
|
|
185472
|
-
|
|
185473
|
-
|
|
185474
|
-
|
|
185461
|
+
const out = [];
|
|
185462
|
+
const scan = (pattern, rule2, check, yaml = false) => {
|
|
185463
|
+
for (const match of text.matchAll(pattern)) {
|
|
185464
|
+
if (!check(match[1] ?? ""))
|
|
185465
|
+
continue;
|
|
185466
|
+
const [from] = match.indices[1];
|
|
185467
|
+
let raw = match[1];
|
|
185468
|
+
if (yaml) {
|
|
185469
|
+
const quoted = /^\s*(?:"(?:[^"\\\n]|\\.)*"|'(?:[^'\n]|'')*')/.exec(raw);
|
|
185470
|
+
raw = quoted ? quoted[0] : raw.replace(/\s+#.*$/, "");
|
|
185471
|
+
}
|
|
185472
|
+
const lead = raw.length - raw.replace(/^[\s"']+/, "").length;
|
|
185473
|
+
const value = raw.replace(/[\s"']+$/, "");
|
|
185474
|
+
if (value.length <= lead)
|
|
185475
|
+
continue;
|
|
185476
|
+
out.push({ rule: rule2, line: 0, start: from + lead, end: from + value.length });
|
|
185475
185477
|
}
|
|
185476
|
-
}
|
|
185478
|
+
};
|
|
185479
|
+
if (name === ".npmrc")
|
|
185480
|
+
scan(/(?:_authToken|_auth|_password)\s*=\s*(.*)/dg, "npmrc_auth_token", literal);
|
|
185481
|
+
if (name === ".yarnrc.yml" || name === ".yarnrc")
|
|
185482
|
+
scan(/npmAuth(?:Token|Ident)\s*:\s*(.*)/dg, "yarnrc_auth_token", literal, name === ".yarnrc.yml");
|
|
185483
|
+
if (name === ".pypirc")
|
|
185484
|
+
scan(/^\s*password\s*[=:]\s*(.*)$/dgm, "pypirc_password", literal);
|
|
185477
185485
|
if (name === "pip.conf" || name === "pip.ini" || name === "poetry.toml" || name === "bunfig.toml" || name === ".condarc") {
|
|
185478
|
-
|
|
185479
|
-
|
|
185486
|
+
scan(/https?:\/\/[^\s/:@]+:([^\s/?#]+)@[^\s/?#@]+/dg, "registry_url_credentials", (value) => !value.startsWith("$"));
|
|
185487
|
+
}
|
|
185488
|
+
if (name === "settings.xml")
|
|
185489
|
+
scan(/<password>(?!\s*\$\{)([^<]+)<\/password>/dg, "maven_settings_password", () => true);
|
|
185490
|
+
out.sort((a, b) => a.start - b.start);
|
|
185491
|
+
let line = 1;
|
|
185492
|
+
let cursor = 0;
|
|
185493
|
+
for (const finding of out) {
|
|
185494
|
+
for (;cursor < finding.start; cursor += 1)
|
|
185495
|
+
if (text.charCodeAt(cursor) === 10)
|
|
185496
|
+
line += 1;
|
|
185497
|
+
finding.line = line;
|
|
185480
185498
|
}
|
|
185481
|
-
|
|
185482
|
-
|
|
185483
|
-
|
|
185499
|
+
return out;
|
|
185500
|
+
}
|
|
185501
|
+
function registryAuthRule(path, text) {
|
|
185502
|
+
return registryAuthFindings(path, text)[0]?.rule ?? null;
|
|
185503
|
+
}
|
|
185504
|
+
var LOG_DIRS = new Set(["logs", ".logs"]);
|
|
185505
|
+
function runtimeLogRule(path, status) {
|
|
185506
|
+
if (status === "tracked")
|
|
185507
|
+
return null;
|
|
185508
|
+
return /\.log(\.\d+)?$/i.test(basenameOf(path)) ? { reason: "regenerable_output", rule: "runtime_log" } : null;
|
|
185484
185509
|
}
|
|
185485
185510
|
function dirRule(dirPath, status) {
|
|
185486
185511
|
const name = basenameOf(dirPath);
|
|
@@ -185491,6 +185516,8 @@ function dirRule(dirPath, status) {
|
|
|
185491
185516
|
}
|
|
185492
185517
|
if (status === "tracked")
|
|
185493
185518
|
return null;
|
|
185519
|
+
if (LOG_DIRS.has(name))
|
|
185520
|
+
return { reason: "regenerable_output", rule: "runtime_log" };
|
|
185494
185521
|
if (DEPENDENCY_DIRS.has(name) || DEPENDENCY_DIR_SUFFIXES.some((s) => hasSuffix(dirPath, s))) {
|
|
185495
185522
|
return { reason: "dependency_install", rule: name };
|
|
185496
185523
|
}
|
|
@@ -186222,12 +186249,21 @@ class EnvCollector {
|
|
|
186222
186249
|
}
|
|
186223
186250
|
}
|
|
186224
186251
|
scanDotenv(path, lines) {
|
|
186252
|
+
let open = null;
|
|
186225
186253
|
lines.forEach((line, index) => {
|
|
186254
|
+
if (open) {
|
|
186255
|
+
if (closesQuote(line, open, 0))
|
|
186256
|
+
open = null;
|
|
186257
|
+
return;
|
|
186258
|
+
}
|
|
186226
186259
|
const m = line.match(new RegExp(`^\\s*(?:export\\s+)?(${NAME})\\s*=\\s*(.*)$`));
|
|
186227
186260
|
if (!m)
|
|
186228
186261
|
return;
|
|
186229
|
-
|
|
186230
|
-
|
|
186262
|
+
this.add(m[1], `${path}:${index + 1}`, false);
|
|
186263
|
+
const value = m[2] ?? "";
|
|
186264
|
+
const quote = value[0];
|
|
186265
|
+
if ((quote === '"' || quote === "'" || quote === "`") && !closesQuote(value, quote, 1))
|
|
186266
|
+
open = quote;
|
|
186231
186267
|
});
|
|
186232
186268
|
}
|
|
186233
186269
|
scanDestructuring(path, line, lineNo) {
|
|
@@ -186468,6 +186504,15 @@ function shellExpandable(line) {
|
|
|
186468
186504
|
}
|
|
186469
186505
|
return out;
|
|
186470
186506
|
}
|
|
186507
|
+
function closesQuote(text, quote, from) {
|
|
186508
|
+
for (let i = from;i < text.length; i += 1) {
|
|
186509
|
+
if (text[i] === "\\" && quote !== "'")
|
|
186510
|
+
i += 1;
|
|
186511
|
+
else if (text[i] === quote)
|
|
186512
|
+
return true;
|
|
186513
|
+
}
|
|
186514
|
+
return false;
|
|
186515
|
+
}
|
|
186471
186516
|
function stripInlineValue(raw) {
|
|
186472
186517
|
let value = raw.trim();
|
|
186473
186518
|
if (/^["']/.test(value)) {
|
|
@@ -186587,6 +186632,24 @@ function lsFiles(root, args) {
|
|
|
186587
186632
|
throw new Error(`git ls-files ${args.join(" ")} failed in ${root}`);
|
|
186588
186633
|
return result.stdout.split("\x00").filter((entry) => entry !== "");
|
|
186589
186634
|
}
|
|
186635
|
+
function ignoredPaths(root) {
|
|
186636
|
+
const result = git(root, ["status", "--porcelain=v1", "-z", "--ignored=matching", "--untracked-files=all"]);
|
|
186637
|
+
if (!result.ok)
|
|
186638
|
+
throw new Error(`git status --ignored failed in ${root}`);
|
|
186639
|
+
const out = [];
|
|
186640
|
+
const fields = result.stdout.split("\x00");
|
|
186641
|
+
for (let i = 0;i < fields.length; i += 1) {
|
|
186642
|
+
const field = fields[i];
|
|
186643
|
+
if (field.length < 4)
|
|
186644
|
+
continue;
|
|
186645
|
+
const code = field.slice(0, 2);
|
|
186646
|
+
if (code === "!!")
|
|
186647
|
+
out.push(field.slice(3));
|
|
186648
|
+
else if (code[0] === "R" || code[0] === "C")
|
|
186649
|
+
i += 1;
|
|
186650
|
+
}
|
|
186651
|
+
return out;
|
|
186652
|
+
}
|
|
186590
186653
|
function gitMetadata(root) {
|
|
186591
186654
|
const commit = git(root, ["rev-parse", "--verify", "-q", "HEAD"]);
|
|
186592
186655
|
const branch = git(root, ["symbolic-ref", "--short", "-q", "HEAD"]);
|
|
@@ -186877,7 +186940,6 @@ function shannonEntropy(value) {
|
|
|
186877
186940
|
return entropy;
|
|
186878
186941
|
}
|
|
186879
186942
|
var notPlaceholder = (value) => !looksLikePlaceholder(value);
|
|
186880
|
-
var LOCAL_HOSTS = /^(localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\]|::1|host\.docker\.internal|[a-z0-9_-]+)(:\d+)?$/i;
|
|
186881
186943
|
var WEAK_PASSWORDS = new Set([
|
|
186882
186944
|
"password",
|
|
186883
186945
|
"pass",
|
|
@@ -186903,9 +186965,20 @@ var WEAK_PASSWORDS = new Set([
|
|
|
186903
186965
|
var SECRET_RULES = [
|
|
186904
186966
|
{
|
|
186905
186967
|
name: "private_key_block",
|
|
186906
|
-
pattern: /-----BEGIN (?:[A-Z0-9]+ )*PRIVATE KEY(?: BLOCK)?-----(?:(?:\r?\n|(?:\\r)?\\n)[A-Za-z][A-Za-z0-9-]*:[^\r\n\\]*)*(?:\\n|\\r|\s)+([A-Za-z0-9+/=]{32,})/g,
|
|
186968
|
+
pattern: /-----BEGIN (?:[A-Z0-9]+ )*PRIVATE KEY(?: BLOCK)?-----(?:(?:\r?\n|(?:\\r)?\\n)[A-Za-z][A-Za-z0-9-]*:[^\r\n\\]*)*(?:\\n|\\r|\s)+([A-Za-z0-9+/=]{32,8192})/g,
|
|
186907
186969
|
group: 1,
|
|
186908
|
-
accept: notPlaceholder
|
|
186970
|
+
accept: notPlaceholder,
|
|
186971
|
+
withholdFile: true
|
|
186972
|
+
},
|
|
186973
|
+
{
|
|
186974
|
+
name: "private_key_block",
|
|
186975
|
+
pattern: /-----BEGIN (?:[A-Z0-9]+ )*PRIVATE KEY(?: BLOCK)?-----([^-]{1,8192}?)-----END (?:[A-Z0-9]+ )*PRIVATE KEY(?: BLOCK)?-----/g,
|
|
186976
|
+
group: 1,
|
|
186977
|
+
accept: (body) => {
|
|
186978
|
+
const compact = body.replace(/\\[rn]|\s/g, "");
|
|
186979
|
+
return compact.length >= 16 && /^[A-Za-z0-9+/=:,-]+$/.test(compact) && !/x{4,}|X{4,}|\.\.\./.test(compact);
|
|
186980
|
+
},
|
|
186981
|
+
withholdFile: true
|
|
186909
186982
|
},
|
|
186910
186983
|
{
|
|
186911
186984
|
name: "aws_access_key_id",
|
|
@@ -186919,57 +186992,60 @@ var SECRET_RULES = [
|
|
|
186919
186992
|
group: 1,
|
|
186920
186993
|
accept: (value) => !/EXAMPLE/.test(value) && notPlaceholder(value)
|
|
186921
186994
|
},
|
|
186922
|
-
{ name: "anthropic_api_key", pattern: /\bsk-ant-(?:api|admin|oat)\d{2}-([A-Za-z0-9_-]{32,})/g, group: 1, accept: (v) => randomLooking(v, 32) },
|
|
186923
|
-
{ name: "openrouter_api_key", pattern: /\bsk-or-v1-[a-f0-9]{48,}\b/g, accept: notPlaceholder },
|
|
186995
|
+
{ name: "anthropic_api_key", pattern: /\bsk-ant-(?:api|admin|oat)\d{2}-([A-Za-z0-9_-]{32,512})(?![A-Za-z0-9_-])/g, group: 1, accept: (v) => randomLooking(v, 32) },
|
|
186996
|
+
{ name: "openrouter_api_key", pattern: /\bsk-or-v1-[a-f0-9]{48,512}\b/g, accept: notPlaceholder },
|
|
186924
186997
|
{
|
|
186925
186998
|
name: "openai_api_key",
|
|
186926
|
-
pattern: /\bsk-(?!ant-|or-)(?:proj-|svcacct-|admin-|None-)?([A-Za-z0-9_-]{32,})/g,
|
|
186999
|
+
pattern: /\bsk-(?!ant-|or-)(?:proj-|svcacct-|admin-|None-)?([A-Za-z0-9_-]{32,512})(?![A-Za-z0-9_-])/g,
|
|
186927
187000
|
group: 1,
|
|
186928
187001
|
accept: (value) => randomLooking(value, 32)
|
|
186929
187002
|
},
|
|
186930
|
-
{ name: "groq_api_key", pattern: /\bgsk_[A-Za-z0-9]{40,}\b/g, accept: notPlaceholder },
|
|
187003
|
+
{ name: "groq_api_key", pattern: /\bgsk_[A-Za-z0-9]{40,512}\b/g, accept: notPlaceholder },
|
|
186931
187004
|
{ name: "google_api_key", pattern: /\bAIza[0-9A-Za-z_-]{35}\b/g, accept: notPlaceholder },
|
|
186932
|
-
{ name: "huggingface_token", pattern: /\bhf_[A-Za-z0-9]{30,}\b/g, accept: notPlaceholder },
|
|
186933
|
-
{ name: "xai_api_key", pattern: /\bxai-[A-Za-z0-9]{40,}\b/g, accept: notPlaceholder },
|
|
186934
|
-
{ name: "github_token", pattern: /\b(?:gh[pousr]_([A-Za-z0-9]{36,})|github_pat_([A-Za-z0-9_]{60,}))\b/g, accept: (_v, m) => randomLooking(m[1] ?? m[2] ?? "", 36) },
|
|
186935
|
-
{ name: "gitlab_token", pattern: /\bglpat-[A-Za-z0-9_-]{20,}\b/g, accept: notPlaceholder },
|
|
186936
|
-
{ name: "slack_token", pattern: /\bxox[abposr]-[A-Za-z0-9-]{10,}/g, accept: notPlaceholder },
|
|
187005
|
+
{ name: "huggingface_token", pattern: /\bhf_[A-Za-z0-9]{30,512}\b/g, accept: notPlaceholder },
|
|
187006
|
+
{ name: "xai_api_key", pattern: /\bxai-[A-Za-z0-9]{40,512}\b/g, accept: notPlaceholder },
|
|
187007
|
+
{ name: "github_token", pattern: /\b(?:gh[pousr]_([A-Za-z0-9]{36,512})|github_pat_([A-Za-z0-9_]{60,512}))\b/g, accept: (_v, m) => randomLooking(m[1] ?? m[2] ?? "", 36) },
|
|
187008
|
+
{ name: "gitlab_token", pattern: /\bglpat-[A-Za-z0-9_-]{20,512}\b/g, accept: notPlaceholder },
|
|
187009
|
+
{ name: "slack_token", pattern: /\bxox[abposr]-[A-Za-z0-9-]{10,512}(?![A-Za-z0-9-])/g, accept: notPlaceholder },
|
|
186937
187010
|
{
|
|
186938
187011
|
name: "slack_webhook",
|
|
186939
|
-
pattern: /https:\/\/hooks\.slack\.com\/services\/T[A-Z0-9]+\/B[A-Z0-9]+\/[A-Za-z0-9]{16,}/g,
|
|
187012
|
+
pattern: /https:\/\/hooks\.slack\.com\/services\/T[A-Z0-9]+\/B[A-Z0-9]+\/[A-Za-z0-9]{16,512}/g,
|
|
186940
187013
|
accept: notPlaceholder
|
|
186941
187014
|
},
|
|
186942
|
-
{ name: "stripe_secret_key", pattern: /\b(?:sk|rk)_(?:live|test)_([A-Za-z0-9]{20,})\b/g, group: 1, accept: (v) => randomLooking(v, 20) },
|
|
186943
|
-
{ name: "stripe_webhook_secret", pattern: /\bwhsec_[A-Za-z0-9]{24,}\b/g, accept: notPlaceholder },
|
|
187015
|
+
{ name: "stripe_secret_key", pattern: /\b(?:sk|rk)_(?:live|test)_([A-Za-z0-9]{20,512})\b/g, group: 1, accept: (v) => randomLooking(v, 20) },
|
|
187016
|
+
{ name: "stripe_webhook_secret", pattern: /\bwhsec_[A-Za-z0-9]{24,512}\b/g, accept: notPlaceholder },
|
|
186944
187017
|
{ name: "sendgrid_api_key", pattern: /\bSG\.[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43}\b/g, accept: notPlaceholder },
|
|
186945
187018
|
{ name: "npm_token", pattern: /\bnpm_[A-Za-z0-9]{36}\b/g, accept: notPlaceholder },
|
|
186946
|
-
{ name: "pypi_token", pattern: /\bpypi-AgEIcHlwaS5vcmc[A-Za-z0-9_-]{50,}/g, accept: notPlaceholder },
|
|
187019
|
+
{ name: "pypi_token", pattern: /\bpypi-AgEIcHlwaS5vcmc[A-Za-z0-9_-]{50,512}(?![A-Za-z0-9_-])/g, accept: notPlaceholder },
|
|
186947
187020
|
{ name: "digitalocean_token", pattern: /\bdo[opr]_v1_[a-f0-9]{64}\b/g, accept: notPlaceholder },
|
|
186948
187021
|
{ name: "shopify_token", pattern: /\bshp(?:at|ca|pa|ss)_[a-fA-F0-9]{32}\b/g, accept: notPlaceholder },
|
|
186949
187022
|
{ name: "databricks_token", pattern: /\bdapi[a-f0-9]{32}\b/g, accept: notPlaceholder },
|
|
186950
|
-
{ name: "moda_api_key", pattern: /\bmoda_(?:sk|ct)_([A-Za-z0-9_-]{32,})/g, group: 1, accept: (v) => randomLooking(v, 32) },
|
|
187023
|
+
{ name: "moda_api_key", pattern: /\bmoda_(?:sk|ct)_([A-Za-z0-9_-]{32,512})(?![A-Za-z0-9_-])/g, group: 1, accept: (v) => randomLooking(v, 32) },
|
|
186951
187024
|
{
|
|
186952
187025
|
name: "jwt",
|
|
186953
|
-
pattern: /\b(eyJ[A-Za-z0-9_-]{10,})\.eyJ[A-Za-z0-9_-]{10,}\.([A-Za-z0-9_-]{16,})/g,
|
|
187026
|
+
pattern: /\b(eyJ[A-Za-z0-9_-]{10,1024})\.eyJ[A-Za-z0-9_-]{10,65536}\.([A-Za-z0-9_-]{16,1024})(?![A-Za-z0-9_-])/g,
|
|
186954
187027
|
accept: (_v, m) => isJwtHeader(m[1] ?? "") && !KNOWN_SAMPLE_JWT_SIGNATURES.has(m[2] ?? "") && notPlaceholder(m[2] ?? "")
|
|
186955
187028
|
},
|
|
187029
|
+
{
|
|
187030
|
+
name: "bearer_token",
|
|
187031
|
+
pattern: /\bBearer[ \t]+([A-Za-z0-9._~+/=-]{20,65536})(?![A-Za-z0-9._~+/=-])/g,
|
|
187032
|
+
group: 1,
|
|
187033
|
+
accept: (value) => !looksLikePlaceholder(value) && /[0-9]/.test(value) && /[A-Za-z]/.test(value)
|
|
187034
|
+
},
|
|
186956
187035
|
{
|
|
186957
187036
|
name: "url_embedded_credentials",
|
|
186958
|
-
pattern: /\b(?:postgres(?:ql)?|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?|mssql|sqlserver|clickhouse|https?):\/\/([^:\s/@'"]
|
|
187037
|
+
pattern: /\b(?:postgres(?:ql)?|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?|mssql|sqlserver|clickhouse|https?):\/\/([^:\s/@'"]{1,256}):([^\s/?#'"]{3,65536})@([^/\s'"?#@]+)/g,
|
|
186959
187038
|
group: 2,
|
|
186960
|
-
accept: (password
|
|
186961
|
-
const host = match[3] ?? "";
|
|
187039
|
+
accept: (password) => {
|
|
186962
187040
|
if (WEAK_PASSWORDS.has(password.toLowerCase()))
|
|
186963
187041
|
return false;
|
|
186964
|
-
|
|
186965
|
-
return false;
|
|
186966
|
-
return !LOCAL_HOSTS.test(host);
|
|
187042
|
+
return !looksLikePlaceholder(password) && !/^[$%:{]/.test(password);
|
|
186967
187043
|
}
|
|
186968
187044
|
},
|
|
186969
187045
|
{
|
|
186970
187046
|
name: "generic_secret_assignment",
|
|
186971
187047
|
heuristic: true,
|
|
186972
|
-
pattern: /\b([A-Za-z][A-Za-z0-9_-]
|
|
187048
|
+
pattern: /\b([A-Za-z][A-Za-z0-9_-]{0,127})["']?[ \t]*[:=][ \t]*(["'`])([A-Za-z0-9+/=_\-.~]{16,})\2/g,
|
|
186973
187049
|
group: 3,
|
|
186974
187050
|
accept: (value, match) => isSecretName(match[1] ?? "") && isSecretLikeValue(value)
|
|
186975
187051
|
},
|
|
@@ -186977,7 +187053,7 @@ var SECRET_RULES = [
|
|
|
186977
187053
|
name: "generic_secret_assignment",
|
|
186978
187054
|
heuristic: true,
|
|
186979
187055
|
configOnly: true,
|
|
186980
|
-
pattern:
|
|
187056
|
+
pattern: /^[ \t]*(?:export[ \t]+)?([A-Za-z][A-Za-z0-9_-]{0,127})[ \t]*[:=][ \t]*([A-Za-z0-9+/=_\-.~]{16,512})[ \t]*(?:#.*)?$/gm,
|
|
186981
187057
|
group: 2,
|
|
186982
187058
|
accept: (value, match) => isSecretName(match[1] ?? "") && isSecretLikeValue(value)
|
|
186983
187059
|
}
|
|
@@ -187035,6 +187111,842 @@ function scanForSecrets(text, opts) {
|
|
|
187035
187111
|
}
|
|
187036
187112
|
return null;
|
|
187037
187113
|
}
|
|
187114
|
+
var INDEXED = new Map;
|
|
187115
|
+
function withIndices(pattern) {
|
|
187116
|
+
let indexed = INDEXED.get(pattern);
|
|
187117
|
+
if (!indexed) {
|
|
187118
|
+
indexed = new RegExp(pattern.source, `${pattern.flags.replace("d", "")}d`);
|
|
187119
|
+
INDEXED.set(pattern, indexed);
|
|
187120
|
+
}
|
|
187121
|
+
return indexed;
|
|
187122
|
+
}
|
|
187123
|
+
function findSecretSpans(text, opts) {
|
|
187124
|
+
const spans = [];
|
|
187125
|
+
for (const rule2 of SECRET_RULES) {
|
|
187126
|
+
if (rule2.heuristic && !opts.heuristics)
|
|
187127
|
+
continue;
|
|
187128
|
+
if (rule2.configOnly && !opts.config)
|
|
187129
|
+
continue;
|
|
187130
|
+
const pattern = withIndices(rule2.pattern);
|
|
187131
|
+
pattern.lastIndex = 0;
|
|
187132
|
+
for (const match of text.matchAll(pattern)) {
|
|
187133
|
+
const group = rule2.group ?? 0;
|
|
187134
|
+
const value = match[group] ?? "";
|
|
187135
|
+
if (rule2.accept && !rule2.accept(value, match))
|
|
187136
|
+
continue;
|
|
187137
|
+
const range = match.indices?.[group] ?? [match.index ?? 0, (match.index ?? 0) + match[0].length];
|
|
187138
|
+
spans.push({ rule: rule2.name, start: range[0], end: range[1], withholdFile: rule2.withholdFile === true });
|
|
187139
|
+
}
|
|
187140
|
+
}
|
|
187141
|
+
return spans;
|
|
187142
|
+
}
|
|
187143
|
+
|
|
187144
|
+
// ../../packages/harness-bundle/src/collect/redact.ts
|
|
187145
|
+
var CONFIG_EXT = /\.(ya?ml|toml|json|jsonc|json5|properties|ini|cfg|conf|env|tfvars|hcl|cnf|nix)$/i;
|
|
187146
|
+
var CONFIG_NAMES = /^(\.npmrc|\.yarnrc|\.yarnrc\.yml|\.pypirc|pip\.conf|pip\.ini|\.condarc|\.netrc|\.envrc|\.dev\.vars.*|\.env.*|[^/]*\.env|dockerfile.*|containerfile.*|.*\.dockerfile|procfile|settings\.xml)$/i;
|
|
187147
|
+
function isConfigLike(path) {
|
|
187148
|
+
const name = basenameOf(path);
|
|
187149
|
+
return CONFIG_EXT.test(name) || CONFIG_NAMES.test(name);
|
|
187150
|
+
}
|
|
187151
|
+
var CREDENTIAL_WORDS = new Set([
|
|
187152
|
+
"token",
|
|
187153
|
+
"secret",
|
|
187154
|
+
"password",
|
|
187155
|
+
"passwd",
|
|
187156
|
+
"pwd",
|
|
187157
|
+
"passphrase",
|
|
187158
|
+
"credential",
|
|
187159
|
+
"credentials",
|
|
187160
|
+
"dsn",
|
|
187161
|
+
"apikey"
|
|
187162
|
+
]);
|
|
187163
|
+
var NOT_CREDENTIAL_WORDS = new Set([
|
|
187164
|
+
"public",
|
|
187165
|
+
"publishable",
|
|
187166
|
+
"anon",
|
|
187167
|
+
"primary",
|
|
187168
|
+
"foreign",
|
|
187169
|
+
"sort",
|
|
187170
|
+
"partition",
|
|
187171
|
+
"cache",
|
|
187172
|
+
"idempotency",
|
|
187173
|
+
"dedup",
|
|
187174
|
+
"lookup",
|
|
187175
|
+
"index",
|
|
187176
|
+
"hash",
|
|
187177
|
+
"column",
|
|
187178
|
+
"cursor",
|
|
187179
|
+
"row",
|
|
187180
|
+
"composite",
|
|
187181
|
+
"unique",
|
|
187182
|
+
"map",
|
|
187183
|
+
"dict"
|
|
187184
|
+
]);
|
|
187185
|
+
var KEY_QUALIFIERS = new Set([
|
|
187186
|
+
"api",
|
|
187187
|
+
"access",
|
|
187188
|
+
"secret",
|
|
187189
|
+
"private",
|
|
187190
|
+
"signing",
|
|
187191
|
+
"encryption",
|
|
187192
|
+
"enc",
|
|
187193
|
+
"master",
|
|
187194
|
+
"service",
|
|
187195
|
+
"auth",
|
|
187196
|
+
"client",
|
|
187197
|
+
"license",
|
|
187198
|
+
"app",
|
|
187199
|
+
"webhook",
|
|
187200
|
+
"session",
|
|
187201
|
+
"jwt",
|
|
187202
|
+
"hmac",
|
|
187203
|
+
"admin",
|
|
187204
|
+
"bearer",
|
|
187205
|
+
"account",
|
|
187206
|
+
"subscription",
|
|
187207
|
+
"crypto",
|
|
187208
|
+
"cipher",
|
|
187209
|
+
"root",
|
|
187210
|
+
"role",
|
|
187211
|
+
"write",
|
|
187212
|
+
"read",
|
|
187213
|
+
"deploy",
|
|
187214
|
+
"gateway",
|
|
187215
|
+
"aes",
|
|
187216
|
+
"creds",
|
|
187217
|
+
"credential",
|
|
187218
|
+
"credentials",
|
|
187219
|
+
"pat",
|
|
187220
|
+
"sas",
|
|
187221
|
+
"shared"
|
|
187222
|
+
]);
|
|
187223
|
+
var IDENTIFIER_KEY_WORDS = new Set([
|
|
187224
|
+
"s3",
|
|
187225
|
+
"r2",
|
|
187226
|
+
"gcs",
|
|
187227
|
+
"blob",
|
|
187228
|
+
"object",
|
|
187229
|
+
"output",
|
|
187230
|
+
"path",
|
|
187231
|
+
"plugin",
|
|
187232
|
+
"file",
|
|
187233
|
+
"prompt",
|
|
187234
|
+
"config",
|
|
187235
|
+
"json",
|
|
187236
|
+
"user",
|
|
187237
|
+
"storage",
|
|
187238
|
+
"routing",
|
|
187239
|
+
"shard",
|
|
187240
|
+
"message",
|
|
187241
|
+
"event",
|
|
187242
|
+
"bucket",
|
|
187243
|
+
"record",
|
|
187244
|
+
"i18n",
|
|
187245
|
+
"translation",
|
|
187246
|
+
"metric",
|
|
187247
|
+
"label",
|
|
187248
|
+
"group",
|
|
187249
|
+
"state",
|
|
187250
|
+
"query",
|
|
187251
|
+
"field",
|
|
187252
|
+
"attribute",
|
|
187253
|
+
"property",
|
|
187254
|
+
"tag",
|
|
187255
|
+
"header",
|
|
187256
|
+
"item",
|
|
187257
|
+
"table",
|
|
187258
|
+
"range",
|
|
187259
|
+
"prefix",
|
|
187260
|
+
"ssh",
|
|
187261
|
+
"gpg",
|
|
187262
|
+
"pgp",
|
|
187263
|
+
"idem",
|
|
187264
|
+
"sort",
|
|
187265
|
+
"partition",
|
|
187266
|
+
"cache",
|
|
187267
|
+
"lookup",
|
|
187268
|
+
"index",
|
|
187269
|
+
"hash",
|
|
187270
|
+
"column",
|
|
187271
|
+
"row",
|
|
187272
|
+
"map",
|
|
187273
|
+
"dict",
|
|
187274
|
+
"composite",
|
|
187275
|
+
"unique"
|
|
187276
|
+
]);
|
|
187277
|
+
function isCredentialName(rawName) {
|
|
187278
|
+
const name = rawName.split(/[./:\\]/).filter(Boolean).pop() ?? rawName;
|
|
187279
|
+
const words = name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").split(/[_\-\s]+/).filter(Boolean).map((w) => w.toLowerCase());
|
|
187280
|
+
const last = words[words.length - 1];
|
|
187281
|
+
const previous = words[words.length - 2];
|
|
187282
|
+
if (!last || words.slice(0, -1).some((w) => NOT_CREDENTIAL_WORDS.has(w)))
|
|
187283
|
+
return false;
|
|
187284
|
+
if (CREDENTIAL_WORDS.has(last))
|
|
187285
|
+
return true;
|
|
187286
|
+
if (/^_auth$/i.test(name) || last === "ident" && previous === "auth")
|
|
187287
|
+
return true;
|
|
187288
|
+
if (last !== "key" || !previous)
|
|
187289
|
+
return false;
|
|
187290
|
+
if (KEY_QUALIFIERS.has(previous))
|
|
187291
|
+
return true;
|
|
187292
|
+
return /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)+$/.test(name) && !IDENTIFIER_KEY_WORDS.has(previous);
|
|
187293
|
+
}
|
|
187294
|
+
function isCredentialValue(raw) {
|
|
187295
|
+
const value = raw.trim();
|
|
187296
|
+
if (value.length < 4 || /[\s\p{C}]/u.test(value))
|
|
187297
|
+
return false;
|
|
187298
|
+
if (/^(true|false|null|none|nil|undefined|yes|no|on|off|~)$/i.test(value))
|
|
187299
|
+
return false;
|
|
187300
|
+
if (/^\$\{?[A-Za-z_]/.test(value) || /\$\{\{|\{\{|%\(|^\$\(/.test(value))
|
|
187301
|
+
return false;
|
|
187302
|
+
if (/^(?:os\.environ(?:\.get)?|os\.getenv|process\.env|import\.meta\.env|Deno\.env\.get|System\.getenv|getenv|ENV)(?:\(.*\)|\[.*\]|\.[A-Za-z_]\w*)$/.test(value))
|
|
187303
|
+
return false;
|
|
187304
|
+
if (/^(env|secret|vault|op|arn|ssm|awssecretsmanager|azurekeyvault|sm|gcpsm|projects)[:(/]/i.test(value) || /^@Microsoft\.KeyVault/i.test(value))
|
|
187305
|
+
return false;
|
|
187306
|
+
if (/^<.*>$/.test(value) || /^#\//.test(value))
|
|
187307
|
+
return false;
|
|
187308
|
+
if (/^(\/|\.\.?\/|~\/|[A-Za-z]:\\)/.test(value))
|
|
187309
|
+
return false;
|
|
187310
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value) && !/^[a-z][a-z0-9+.-]*:\/\/[^/@\s]+@/i.test(value))
|
|
187311
|
+
return false;
|
|
187312
|
+
if (/^[-+]?\d*\.?\d+(e[-+]?\d+)?$/i.test(value))
|
|
187313
|
+
return false;
|
|
187314
|
+
if (/^[\^~<>=v]*\d+(\.(\d+|x|\*)){0,3}([-+.][\w.-]+)?$/i.test(value))
|
|
187315
|
+
return false;
|
|
187316
|
+
if (/^(workspace|npm|file|link|portal|patch|catalog|git\+\w+|github|gitlab):/i.test(value) || /^(latest|next|canary|beta|\*)$/i.test(value))
|
|
187317
|
+
return false;
|
|
187318
|
+
if (WEAK_PASSWORDS.has(value.toLowerCase()))
|
|
187319
|
+
return false;
|
|
187320
|
+
if (/^(.)\1+$/.test(value) || sequentialRuns(value) >= 2)
|
|
187321
|
+
return false;
|
|
187322
|
+
if (/x{4,}|X{4,}|\*{3,}|\.\.\.|(^|[-_.])your[-_.]|changeme|change[-_]me|placeholder|example|replace[-_]?me|redacted|dummy|(^|[-_.])(fake|mock|sample|test|demo)([-_.]|$)/i.test(value))
|
|
187323
|
+
return false;
|
|
187324
|
+
const classes = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^A-Za-z0-9]/].filter((re) => re.test(value)).length;
|
|
187325
|
+
return /[0-9]/.test(value) || value.length >= 20 && classes >= 3;
|
|
187326
|
+
}
|
|
187327
|
+
var PREFIX = String.raw`[ \t]*(?:-[ \t]+)?(?:export[ \t]+|ENV[ \t]+|ARG[ \t]+)?`;
|
|
187328
|
+
var EQUALS_LINE = new RegExp(String.raw`^(${PREFIX})(["']?)([A-Za-z_@/][\w.\-/:@]*)\2[ \t]*=[ \t]*(.*)$`, "gm");
|
|
187329
|
+
var COLON_LINE = new RegExp(String.raw`^(${PREFIX})(["']?)([A-Za-z_@][\w.\-/@]*)\2[ \t]*:(?:[ \t]+|(?=["']))(.*)$`, "gm");
|
|
187330
|
+
function closingQuote(text, open, lineEnd) {
|
|
187331
|
+
const quote = text[open];
|
|
187332
|
+
for (let i = open + 1;i < lineEnd; i += 1) {
|
|
187333
|
+
if (text[i] === "\\" && quote === '"') {
|
|
187334
|
+
i += 1;
|
|
187335
|
+
continue;
|
|
187336
|
+
}
|
|
187337
|
+
if (quote === "'" && text[i] === quote && text[i + 1] === quote) {
|
|
187338
|
+
i += 1;
|
|
187339
|
+
continue;
|
|
187340
|
+
}
|
|
187341
|
+
if (text[i] === quote)
|
|
187342
|
+
return i;
|
|
187343
|
+
}
|
|
187344
|
+
return -1;
|
|
187345
|
+
}
|
|
187346
|
+
function isDockerfile(path) {
|
|
187347
|
+
const name = basenameOf(path);
|
|
187348
|
+
return /^(dockerfile|containerfile)/i.test(name) || /\.dockerfile$/i.test(name);
|
|
187349
|
+
}
|
|
187350
|
+
function valueEnds(path, envFile) {
|
|
187351
|
+
const chars = isDockerfile(path) ? "\\s" : envFile ? "\\s;" : "\\s,;)\\]}";
|
|
187352
|
+
return { terminator: new RegExp(`[${chars}]`), segmentEnd: new RegExp(`[${chars}"'\`]`) };
|
|
187353
|
+
}
|
|
187354
|
+
function dockerfileEnvSpans(source, detected) {
|
|
187355
|
+
const directives = /^(?:[ \t]*#[ \t]*[A-Za-z]+[ \t]*=[^\n]*\n)*/.exec(source)[0];
|
|
187356
|
+
const backtick = /^[ \t]*#[ \t]*escape[ \t]*=[ \t]*`[ \t]*\r?$/im.test(directives);
|
|
187357
|
+
const text = backtick ? source.replace(/[`\\]/g, (ch) => ch === "`" ? "\\" : "`") : source;
|
|
187358
|
+
const spans = [];
|
|
187359
|
+
const known = [...detected].sort((a, b) => a.start - b.start);
|
|
187360
|
+
let nextKnown = 0;
|
|
187361
|
+
let knownEnd = -1;
|
|
187362
|
+
let covered = -1;
|
|
187363
|
+
const skipIgnored = (from) => {
|
|
187364
|
+
let q = from;
|
|
187365
|
+
while (q < text.length) {
|
|
187366
|
+
const lineEnd = text.indexOf(`
|
|
187367
|
+
`, q) === -1 ? text.length : text.indexOf(`
|
|
187368
|
+
`, q);
|
|
187369
|
+
if (!/^[ \t]*(?:#.*)?\r?$/.test(text.slice(q, lineEnd)) || lineEnd === text.length)
|
|
187370
|
+
break;
|
|
187371
|
+
q = lineEnd + 1;
|
|
187372
|
+
}
|
|
187373
|
+
return q;
|
|
187374
|
+
};
|
|
187375
|
+
for (const m of text.matchAll(/^[ \t]*(ENV|ARG)[ \t]+/gim)) {
|
|
187376
|
+
if (m.index < covered)
|
|
187377
|
+
continue;
|
|
187378
|
+
let p2 = m.index + m[0].length;
|
|
187379
|
+
let instructionEnd = text.indexOf(`
|
|
187380
|
+
`, p2);
|
|
187381
|
+
while (instructionEnd !== -1) {
|
|
187382
|
+
let slash = instructionEnd - (text[instructionEnd - 1] === "\r" ? 1 : 0);
|
|
187383
|
+
const end = slash;
|
|
187384
|
+
while (slash > p2 && text[slash - 1] === "\\")
|
|
187385
|
+
slash -= 1;
|
|
187386
|
+
if ((end - slash) % 2 === 0)
|
|
187387
|
+
break;
|
|
187388
|
+
instructionEnd = text.indexOf(`
|
|
187389
|
+
`, skipIgnored(instructionEnd + 1));
|
|
187390
|
+
}
|
|
187391
|
+
if (instructionEnd === -1)
|
|
187392
|
+
instructionEnd = text.length;
|
|
187393
|
+
covered = instructionEnd;
|
|
187394
|
+
let first = true;
|
|
187395
|
+
for (;; ) {
|
|
187396
|
+
for (;; ) {
|
|
187397
|
+
if (text[p2] === " " || text[p2] === "\t" || text[p2] === "\r")
|
|
187398
|
+
p2 += 1;
|
|
187399
|
+
else if (text.startsWith("\\\n", p2))
|
|
187400
|
+
p2 = skipIgnored(p2 + 2);
|
|
187401
|
+
else if (text.startsWith(`\\\r
|
|
187402
|
+
`, p2))
|
|
187403
|
+
p2 = skipIgnored(p2 + 3);
|
|
187404
|
+
else
|
|
187405
|
+
break;
|
|
187406
|
+
}
|
|
187407
|
+
const rest = text.slice(p2, Math.min(p2 + 256, instructionEnd));
|
|
187408
|
+
let name = /^(["']?)([A-Za-z_][\w.-]*)\1=/.exec(rest);
|
|
187409
|
+
const legacy = !name && first && m[1].toUpperCase() === "ENV";
|
|
187410
|
+
if (legacy)
|
|
187411
|
+
name = /^(["']?)([A-Za-z_][\w.-]*)\1[ \t]+/.exec(rest);
|
|
187412
|
+
if (!name)
|
|
187413
|
+
break;
|
|
187414
|
+
first = false;
|
|
187415
|
+
p2 += name[0].length;
|
|
187416
|
+
const valueStart = p2;
|
|
187417
|
+
const parts = [];
|
|
187418
|
+
const addPart = (start, end) => {
|
|
187419
|
+
let from = start;
|
|
187420
|
+
for (const continuation of text.slice(start, end).matchAll(/\\\r?\n/g)) {
|
|
187421
|
+
const stop = start + continuation.index;
|
|
187422
|
+
if (stop > from)
|
|
187423
|
+
parts.push({ start: from, end: stop, rule: "credential_assignment" });
|
|
187424
|
+
from = stop + continuation[0].length;
|
|
187425
|
+
}
|
|
187426
|
+
if (end > from)
|
|
187427
|
+
parts.push({ start: from, end, rule: "credential_assignment" });
|
|
187428
|
+
};
|
|
187429
|
+
let literal = "";
|
|
187430
|
+
while (p2 < instructionEnd && (legacy || !/\s/.test(text[p2]))) {
|
|
187431
|
+
const q = text[p2];
|
|
187432
|
+
if (q === '"' || q === "'") {
|
|
187433
|
+
const close = closingQuote(text, p2, instructionEnd);
|
|
187434
|
+
const end = close === -1 ? instructionEnd : close;
|
|
187435
|
+
addPart(p2 + 1, end);
|
|
187436
|
+
literal += text.slice(p2 + 1, end);
|
|
187437
|
+
p2 = close === -1 ? instructionEnd : close + 1;
|
|
187438
|
+
} else {
|
|
187439
|
+
let e = p2;
|
|
187440
|
+
while (e < instructionEnd && !(legacy ? /["']/ : /[\s"']/).test(text[e])) {
|
|
187441
|
+
if (text[e] === "\\" && e + 1 < instructionEnd)
|
|
187442
|
+
e += text.startsWith(`\\\r
|
|
187443
|
+
`, e) ? 3 : 2;
|
|
187444
|
+
else
|
|
187445
|
+
e += 1;
|
|
187446
|
+
}
|
|
187447
|
+
addPart(p2, e);
|
|
187448
|
+
literal += text.slice(p2, e);
|
|
187449
|
+
p2 = e;
|
|
187450
|
+
}
|
|
187451
|
+
}
|
|
187452
|
+
while (nextKnown < known.length && known[nextKnown].start < valueStart) {
|
|
187453
|
+
knownEnd = Math.max(knownEnd, known[nextKnown++].end);
|
|
187454
|
+
}
|
|
187455
|
+
const hasSecret = knownEnd > valueStart || nextKnown < known.length && known[nextKnown].start < p2;
|
|
187456
|
+
const value = literal.replace(/\\\r?\n/g, "").replace(/\\(.)/g, "$1").trim();
|
|
187457
|
+
if (isCredentialName(name[2]) && (hasSecret || value.split(/[ \t]+/).some(isCredentialValue)))
|
|
187458
|
+
for (const part of parts)
|
|
187459
|
+
spans.push(part);
|
|
187460
|
+
if (legacy)
|
|
187461
|
+
break;
|
|
187462
|
+
}
|
|
187463
|
+
}
|
|
187464
|
+
return spans;
|
|
187465
|
+
}
|
|
187466
|
+
function assignmentSpans(text, everyValue, path, ends) {
|
|
187467
|
+
const toml = /\.toml$/i.test(path);
|
|
187468
|
+
const spans = [];
|
|
187469
|
+
const seenLines = new Set;
|
|
187470
|
+
for (const pattern of [EQUALS_LINE, COLON_LINE]) {
|
|
187471
|
+
pattern.lastIndex = 0;
|
|
187472
|
+
for (const m of text.matchAll(pattern)) {
|
|
187473
|
+
const lineStart = m.index ?? 0;
|
|
187474
|
+
if (seenLines.has(lineStart))
|
|
187475
|
+
continue;
|
|
187476
|
+
seenLines.add(lineStart);
|
|
187477
|
+
const name = m[3];
|
|
187478
|
+
const rest = m[4];
|
|
187479
|
+
const restStart = lineStart + m[0].length - rest.length;
|
|
187480
|
+
let value = valueBounds(rest, everyValue, toml) ?? multilineQuoted(text, restStart, toml);
|
|
187481
|
+
if (!value && everyValue && rest.trim() !== "")
|
|
187482
|
+
value = { start: 0, end: rest.replace(/[ \t]+$/, "").length };
|
|
187483
|
+
if (!value)
|
|
187484
|
+
continue;
|
|
187485
|
+
const extra = [];
|
|
187486
|
+
if (value.start > 0) {
|
|
187487
|
+
const lineEnd = text.indexOf(`
|
|
187488
|
+
`, restStart + value.end) === -1 ? text.length : text.indexOf(`
|
|
187489
|
+
`, restStart + value.end);
|
|
187490
|
+
let p2 = restStart + value.end + value.start;
|
|
187491
|
+
while (p2 < lineEnd && !ends.terminator.test(text[p2])) {
|
|
187492
|
+
const q = text[p2];
|
|
187493
|
+
if (q === '"' || q === "'" || q === "`") {
|
|
187494
|
+
const close = closingQuote(text, p2, lineEnd);
|
|
187495
|
+
const contentEnd = close === -1 ? lineEnd : close;
|
|
187496
|
+
if (contentEnd > p2 + 1)
|
|
187497
|
+
extra.push({ start: p2 + 1, end: contentEnd, rule: "" });
|
|
187498
|
+
p2 = close === -1 ? lineEnd : close + 1;
|
|
187499
|
+
} else {
|
|
187500
|
+
let e = p2;
|
|
187501
|
+
while (e < lineEnd && !ends.segmentEnd.test(text[e]))
|
|
187502
|
+
e += 1;
|
|
187503
|
+
extra.push({ start: p2, end: e, rule: "" });
|
|
187504
|
+
p2 = e;
|
|
187505
|
+
}
|
|
187506
|
+
}
|
|
187507
|
+
if (everyValue && p2 < lineEnd) {
|
|
187508
|
+
const line = text.slice(p2, lineEnd);
|
|
187509
|
+
const comment = line.search(/[ \t]+#/);
|
|
187510
|
+
const body = (comment === -1 ? line : line.slice(0, comment)).replace(/[ \t\r]+$/, "");
|
|
187511
|
+
const lead = body.length - body.replace(/^[\s,;)\]}]+/, "").length;
|
|
187512
|
+
if (body.length > lead)
|
|
187513
|
+
extra.push({ start: p2 + lead, end: p2 + body.length, rule: "" });
|
|
187514
|
+
}
|
|
187515
|
+
}
|
|
187516
|
+
const joined = extra.length > 0;
|
|
187517
|
+
const rule2 = everyValue ? "env_value" : "credential_assignment";
|
|
187518
|
+
const literal = rest.slice(value.start, Math.min(value.end, rest.length)) + (value.end > rest.length ? text.slice(restStart + rest.length, restStart + value.end) : "");
|
|
187519
|
+
if (!everyValue && /\.(hcl|tfvars)$/i.test(path) && value.start === 0 && /^[A-Za-z_]\w*(?:\.|\[|\()/.test(literal))
|
|
187520
|
+
continue;
|
|
187521
|
+
if (everyValue ? literal.trim() === "" : !(isCredentialName(name) && (joined || isCredentialValue(literal))))
|
|
187522
|
+
continue;
|
|
187523
|
+
spans.push({ start: restStart + value.start, end: restStart + value.end, rule: rule2 });
|
|
187524
|
+
for (const span of extra)
|
|
187525
|
+
spans.push({ ...span, rule: rule2 });
|
|
187526
|
+
}
|
|
187527
|
+
}
|
|
187528
|
+
return spans;
|
|
187529
|
+
}
|
|
187530
|
+
function unparsedEnvLines(text, covered) {
|
|
187531
|
+
const out = [];
|
|
187532
|
+
const assignment = new RegExp(String.raw`^${PREFIX}(["']?)[A-Za-z_@/][\w.\-/:@]*\1[ \t]*[=:]`);
|
|
187533
|
+
const spans = [...covered].sort((a, b) => a.start - b.start);
|
|
187534
|
+
let next = 0;
|
|
187535
|
+
let reach = -1;
|
|
187536
|
+
let offset = 0;
|
|
187537
|
+
for (const line of text.split(`
|
|
187538
|
+
`)) {
|
|
187539
|
+
const start = offset;
|
|
187540
|
+
const end = start + Math.max(line.length, 1);
|
|
187541
|
+
offset += line.length + 1;
|
|
187542
|
+
while (next < spans.length && spans[next].start < end)
|
|
187543
|
+
reach = Math.max(reach, spans[next++].end);
|
|
187544
|
+
if (reach > start)
|
|
187545
|
+
continue;
|
|
187546
|
+
const trimmed = line.trim();
|
|
187547
|
+
if (trimmed === "" || trimmed.startsWith("#") || assignment.test(line))
|
|
187548
|
+
continue;
|
|
187549
|
+
const lead = line.length - line.trimStart().length;
|
|
187550
|
+
out.push({ start: start + lead, end: start + line.replace(/[ \t\r]+$/, "").length, rule: "env_value" });
|
|
187551
|
+
}
|
|
187552
|
+
return out;
|
|
187553
|
+
}
|
|
187554
|
+
function tripleQuoted(text, from) {
|
|
187555
|
+
const delim = text.slice(from, from + 3);
|
|
187556
|
+
if (delim !== '"""' && delim !== "'''")
|
|
187557
|
+
return null;
|
|
187558
|
+
for (let i = from + 3;i < text.length; i += 1) {
|
|
187559
|
+
if (text[i] === "\\" && delim === '"""') {
|
|
187560
|
+
i += 1;
|
|
187561
|
+
continue;
|
|
187562
|
+
}
|
|
187563
|
+
if (text.startsWith(delim, i)) {
|
|
187564
|
+
let close = i;
|
|
187565
|
+
while (close - i < 2 && text[close + 3] === delim[0])
|
|
187566
|
+
close += 1;
|
|
187567
|
+
return close > from + 3 ? { start: 3, end: close - from } : null;
|
|
187568
|
+
}
|
|
187569
|
+
}
|
|
187570
|
+
return null;
|
|
187571
|
+
}
|
|
187572
|
+
function multilineQuoted(text, restStart, toml) {
|
|
187573
|
+
const quote = text[restStart];
|
|
187574
|
+
if (quote !== '"' && quote !== "'" && quote !== "`")
|
|
187575
|
+
return null;
|
|
187576
|
+
if (toml && quote !== "`" && text.startsWith(quote.repeat(3), restStart))
|
|
187577
|
+
return tripleQuoted(text, restStart);
|
|
187578
|
+
for (let i = restStart + 1;i < text.length; i += 1) {
|
|
187579
|
+
if (text[i] === "\\" && quote !== "'") {
|
|
187580
|
+
i += 1;
|
|
187581
|
+
continue;
|
|
187582
|
+
}
|
|
187583
|
+
if (quote === "'" && text[i] === quote && text[i + 1] === quote) {
|
|
187584
|
+
i += 1;
|
|
187585
|
+
continue;
|
|
187586
|
+
}
|
|
187587
|
+
if (text[i] === quote)
|
|
187588
|
+
return i > restStart + 1 ? { start: 1, end: i - restStart } : null;
|
|
187589
|
+
}
|
|
187590
|
+
return null;
|
|
187591
|
+
}
|
|
187592
|
+
function valueBounds(rest, envFile, toml) {
|
|
187593
|
+
if (rest === "" || /^[{[|>]/.test(rest))
|
|
187594
|
+
return null;
|
|
187595
|
+
const quote = rest[0];
|
|
187596
|
+
if (quote === '"' || quote === "'" || quote === "`") {
|
|
187597
|
+
if (toml && quote !== "`" && rest.startsWith(quote.repeat(3)))
|
|
187598
|
+
return tripleQuoted(rest, 0);
|
|
187599
|
+
for (let i = 1;i < rest.length; i += 1) {
|
|
187600
|
+
if (rest[i] === "\\" && quote === '"') {
|
|
187601
|
+
i += 1;
|
|
187602
|
+
continue;
|
|
187603
|
+
}
|
|
187604
|
+
if (quote === "'" && rest[i] === quote && rest[i + 1] === quote) {
|
|
187605
|
+
i += 1;
|
|
187606
|
+
continue;
|
|
187607
|
+
}
|
|
187608
|
+
if (rest[i] === quote)
|
|
187609
|
+
return i > 1 ? { start: 1, end: i } : null;
|
|
187610
|
+
}
|
|
187611
|
+
return null;
|
|
187612
|
+
}
|
|
187613
|
+
let end = rest.length;
|
|
187614
|
+
const comment = rest.search(envFile ? /[ \t]+#/ : /[ \t]+[#;]/);
|
|
187615
|
+
if (comment !== -1)
|
|
187616
|
+
end = comment;
|
|
187617
|
+
const trimmed = rest.slice(0, end).replace(envFile ? /[ \t]+$/ : /[ \t,]+$/, "");
|
|
187618
|
+
return trimmed === "" ? null : { start: 0, end: trimmed.length };
|
|
187619
|
+
}
|
|
187620
|
+
function xmlSpans(text) {
|
|
187621
|
+
const spans = [];
|
|
187622
|
+
for (const m of text.matchAll(/<(password|passphrase|privateKey|secret|token|apiKey|accessKey|secretKey)>([^<]+)<\/\1>/dgi)) {
|
|
187623
|
+
const value = m[2].trim();
|
|
187624
|
+
if (value === "" || /^\$\{/.test(value))
|
|
187625
|
+
continue;
|
|
187626
|
+
const [start, end] = m.indices[2];
|
|
187627
|
+
spans.push({ start, end, rule: "credential_assignment" });
|
|
187628
|
+
}
|
|
187629
|
+
return spans;
|
|
187630
|
+
}
|
|
187631
|
+
function inlinePairSpans(text, path) {
|
|
187632
|
+
const cComments = /\.json5$/i.test(path);
|
|
187633
|
+
const toml = /\.toml$/i.test(path);
|
|
187634
|
+
const yaml = /\.ya?ml$/i.test(path);
|
|
187635
|
+
const spans = [];
|
|
187636
|
+
const tomlKey = /[ \t]*(["']?)([A-Za-z_@][\w.\-/@]{0,127})\1[ \t]*=[ \t]*("""|''')/y;
|
|
187637
|
+
const pair = /[ \t]*(["']?)([A-Za-z_@][\w.\-/@]{0,127})\1[ \t]*[:=][ \t]*(?:"((?:[^"\\\n]|\\.)*)"|'((?:[^'\n]|'')*)'|([^,{}[\]\s"'][^,{}\n]*))/dy;
|
|
187638
|
+
let depth = 0;
|
|
187639
|
+
let quote = "";
|
|
187640
|
+
let previous = `
|
|
187641
|
+
`;
|
|
187642
|
+
let expectKey = false;
|
|
187643
|
+
for (let i = 0;i < text.length; i += 1) {
|
|
187644
|
+
const ch = text[i];
|
|
187645
|
+
if (quote) {
|
|
187646
|
+
if (ch === "\\" && quote === '"')
|
|
187647
|
+
i += 1;
|
|
187648
|
+
else if (quote === "'" && ch === "'" && text[i + 1] === "'")
|
|
187649
|
+
i += 1;
|
|
187650
|
+
else if (ch === quote || ch === `
|
|
187651
|
+
` && !yaml)
|
|
187652
|
+
quote = "";
|
|
187653
|
+
continue;
|
|
187654
|
+
}
|
|
187655
|
+
if (ch === " " || ch === "\t" || ch === "\r")
|
|
187656
|
+
continue;
|
|
187657
|
+
if (ch === `
|
|
187658
|
+
`) {
|
|
187659
|
+
previous = ch;
|
|
187660
|
+
continue;
|
|
187661
|
+
}
|
|
187662
|
+
if (cComments && ch === "/" && (text[i + 1] === "/" || text[i + 1] === "*") && /[\s{,[]/.test(text[i - 1] ?? `
|
|
187663
|
+
`)) {
|
|
187664
|
+
const close = text[i + 1] === "*" ? text.indexOf("*/", i + 2) : text.indexOf(`
|
|
187665
|
+
`, i);
|
|
187666
|
+
i = close === -1 ? text.length : text[i + 1] === "*" ? close + 1 : close - 1;
|
|
187667
|
+
continue;
|
|
187668
|
+
}
|
|
187669
|
+
if (ch === "#" && /\s/.test(text[i - 1] ?? `
|
|
187670
|
+
`)) {
|
|
187671
|
+
const lineEnd = text.indexOf(`
|
|
187672
|
+
`, i);
|
|
187673
|
+
i = (lineEnd === -1 ? text.length : lineEnd) - 1;
|
|
187674
|
+
continue;
|
|
187675
|
+
}
|
|
187676
|
+
if (expectKey) {
|
|
187677
|
+
expectKey = false;
|
|
187678
|
+
if (toml) {
|
|
187679
|
+
tomlKey.lastIndex = i;
|
|
187680
|
+
const k = tomlKey.exec(text);
|
|
187681
|
+
if (k) {
|
|
187682
|
+
const open = k.index + k[0].length - 3;
|
|
187683
|
+
const bounds = tripleQuoted(text, open);
|
|
187684
|
+
if (!bounds) {
|
|
187685
|
+
const close = text.indexOf(k[3], open + 3);
|
|
187686
|
+
i = close === -1 ? text.length - 1 : close + 2;
|
|
187687
|
+
} else {
|
|
187688
|
+
const from = open + bounds.start;
|
|
187689
|
+
const to = open + bounds.end;
|
|
187690
|
+
if (isCredentialName(k[2]) && text.slice(from, to).trim().split(/\s+/).some(isCredentialValue)) {
|
|
187691
|
+
spans.push({ start: from, end: to, rule: "credential_assignment" });
|
|
187692
|
+
}
|
|
187693
|
+
i = to + 2;
|
|
187694
|
+
while (text[i + 1] === k[3][0])
|
|
187695
|
+
i += 1;
|
|
187696
|
+
}
|
|
187697
|
+
previous = text[i];
|
|
187698
|
+
continue;
|
|
187699
|
+
}
|
|
187700
|
+
}
|
|
187701
|
+
pair.lastIndex = i;
|
|
187702
|
+
const m = pair.exec(text);
|
|
187703
|
+
if (m) {
|
|
187704
|
+
const group = m[3] !== undefined ? 3 : m[4] !== undefined ? 4 : 5;
|
|
187705
|
+
const value = m[group];
|
|
187706
|
+
if (isCredentialName(m[2]) && isCredentialValue(value)) {
|
|
187707
|
+
const [from] = m.indices[group];
|
|
187708
|
+
spans.push({ start: from, end: from + value.replace(/[ \t]+$/, "").length, rule: "credential_assignment" });
|
|
187709
|
+
}
|
|
187710
|
+
i = m.index + m[0].length - 1;
|
|
187711
|
+
previous = text[i];
|
|
187712
|
+
continue;
|
|
187713
|
+
}
|
|
187714
|
+
}
|
|
187715
|
+
if ((ch === '"' || ch === "'") && /[\n:=,{[(]/.test(previous)) {
|
|
187716
|
+
if (toml && text.startsWith(ch.repeat(3), i)) {
|
|
187717
|
+
const close = tripleQuoted(text, i);
|
|
187718
|
+
const end = close === null ? text.indexOf(ch.repeat(3), i + 3) : i + close.end;
|
|
187719
|
+
i = end === -1 ? text.length : end + 2;
|
|
187720
|
+
while (text[i + 1] === ch)
|
|
187721
|
+
i += 1;
|
|
187722
|
+
previous = ch;
|
|
187723
|
+
continue;
|
|
187724
|
+
}
|
|
187725
|
+
quote = ch;
|
|
187726
|
+
previous = ch;
|
|
187727
|
+
continue;
|
|
187728
|
+
}
|
|
187729
|
+
previous = ch;
|
|
187730
|
+
if (ch === "{")
|
|
187731
|
+
depth += 1;
|
|
187732
|
+
else if (ch === "}" && depth > 0)
|
|
187733
|
+
depth -= 1;
|
|
187734
|
+
if ((ch === "{" || ch === ",") && depth > 0)
|
|
187735
|
+
expectKey = true;
|
|
187736
|
+
}
|
|
187737
|
+
return spans;
|
|
187738
|
+
}
|
|
187739
|
+
function jsonSpans(text) {
|
|
187740
|
+
const spans = [];
|
|
187741
|
+
for (const m of text.matchAll(/"([^"\\\n]{1,128})"\s*:\s*"((?:[^"\\\n]|\\.)*)"/dg)) {
|
|
187742
|
+
if (!isCredentialName(m[1]) || !isCredentialValue(m[2]))
|
|
187743
|
+
continue;
|
|
187744
|
+
const [start, end] = m.indices[2];
|
|
187745
|
+
spans.push({ start, end, rule: "credential_assignment" });
|
|
187746
|
+
}
|
|
187747
|
+
return spans;
|
|
187748
|
+
}
|
|
187749
|
+
var GENERIC_RULES = new Set(["generic_secret_assignment", "credential_assignment", "env_value", "url_embedded_credentials", "bearer_token"]);
|
|
187750
|
+
var SEPARATOR2 = /[-_./:@+=,;]/;
|
|
187751
|
+
function mask(value) {
|
|
187752
|
+
const marker = PROVIDER_MARKER.exec(value)?.[0] ?? "";
|
|
187753
|
+
const keep = marker.length <= value.length - 8 ? marker : "";
|
|
187754
|
+
const body = value.slice(keep.length);
|
|
187755
|
+
const hasContent = /[\p{L}\p{N}]/u.test(body);
|
|
187756
|
+
let out = "";
|
|
187757
|
+
for (let i = 0;i < body.length; i += 1) {
|
|
187758
|
+
const ch = body[i];
|
|
187759
|
+
if (ch === "\\" && i + 1 < body.length && body[i + 1] !== `
|
|
187760
|
+
` && body[i + 1] !== "\r") {
|
|
187761
|
+
out += "xx";
|
|
187762
|
+
i += 1;
|
|
187763
|
+
continue;
|
|
187764
|
+
}
|
|
187765
|
+
if (ch === `
|
|
187766
|
+
` || ch === "\r")
|
|
187767
|
+
out += ch;
|
|
187768
|
+
else if (hasContent && SEPARATOR2.test(ch))
|
|
187769
|
+
out += ch;
|
|
187770
|
+
else
|
|
187771
|
+
out += "x";
|
|
187772
|
+
}
|
|
187773
|
+
return keep + out;
|
|
187774
|
+
}
|
|
187775
|
+
function propertiesContinuations(text, spans) {
|
|
187776
|
+
const out = [];
|
|
187777
|
+
const visited = new Set;
|
|
187778
|
+
const lineEndAt = (i) => text.indexOf(`
|
|
187779
|
+
`, i) === -1 ? text.length : text.indexOf(`
|
|
187780
|
+
`, i);
|
|
187781
|
+
const continuation = (from, end) => {
|
|
187782
|
+
let contentEnd = end;
|
|
187783
|
+
if (text[contentEnd - 1] === "\r")
|
|
187784
|
+
contentEnd -= 1;
|
|
187785
|
+
let run = contentEnd;
|
|
187786
|
+
while (run > from && text[run - 1] === "\\")
|
|
187787
|
+
run -= 1;
|
|
187788
|
+
return (contentEnd - run) % 2 === 1 ? contentEnd - 1 : -1;
|
|
187789
|
+
};
|
|
187790
|
+
const comments = new Set;
|
|
187791
|
+
let continued = false;
|
|
187792
|
+
for (let from = 0;from < text.length; ) {
|
|
187793
|
+
const end = lineEndAt(from);
|
|
187794
|
+
const comment = !continued && /^[ \t\f]*[#!]/.test(text.slice(from, end));
|
|
187795
|
+
if (comment)
|
|
187796
|
+
comments.add(end);
|
|
187797
|
+
continued = !comment && continuation(from, end) !== -1;
|
|
187798
|
+
from = end + 1;
|
|
187799
|
+
}
|
|
187800
|
+
for (const span of spans) {
|
|
187801
|
+
let end = lineEndAt(span.start);
|
|
187802
|
+
if (comments.has(end))
|
|
187803
|
+
continue;
|
|
187804
|
+
let slash = continuation(span.start, end);
|
|
187805
|
+
if (slash === -1)
|
|
187806
|
+
continue;
|
|
187807
|
+
if (span.end > slash)
|
|
187808
|
+
span.end = slash;
|
|
187809
|
+
while (slash !== -1 && end < text.length && !visited.has(end)) {
|
|
187810
|
+
visited.add(end);
|
|
187811
|
+
const from = end + 1;
|
|
187812
|
+
end = lineEndAt(from);
|
|
187813
|
+
let start = from;
|
|
187814
|
+
while (start < end && (text[start] === " " || text[start] === "\t"))
|
|
187815
|
+
start += 1;
|
|
187816
|
+
slash = continuation(start, end);
|
|
187817
|
+
const stop = slash === -1 ? text[end - 1] === "\r" ? end - 1 : end : slash;
|
|
187818
|
+
if (stop > start)
|
|
187819
|
+
out.push({ start, end: stop, rule: span.rule });
|
|
187820
|
+
}
|
|
187821
|
+
}
|
|
187822
|
+
return out;
|
|
187823
|
+
}
|
|
187824
|
+
function yamlValueSpans(text, spans, everyValue) {
|
|
187825
|
+
if (spans.length === 0) {
|
|
187826
|
+
let candidate = false;
|
|
187827
|
+
COLON_LINE.lastIndex = 0;
|
|
187828
|
+
for (const match of text.matchAll(COLON_LINE)) {
|
|
187829
|
+
if (!isCredentialName(match[3]))
|
|
187830
|
+
continue;
|
|
187831
|
+
const rest = match[4].replace(/\r$/, "");
|
|
187832
|
+
const lineEnd = match.index + match[0].length;
|
|
187833
|
+
const nextLine = /^\n([ \t]*)\S/.exec(text.slice(lineEnd, lineEnd + 512));
|
|
187834
|
+
const indent = /^[ \t]*/.exec(match[0])[0].length;
|
|
187835
|
+
if (/^[&!]/.test(rest) || /(?:^|[ \t])[|>][-+1-9]*[ \t]*(?:#.*)?$/.test(rest) || /^"(?:[^"\\]|\\.)*$/.test(rest) || /^'(?:[^']|'')*$/.test(rest) || rest.trim() !== "" && !/^["'{[]/.test(rest) && nextLine !== null && nextLine[1].length > indent) {
|
|
187836
|
+
candidate = true;
|
|
187837
|
+
break;
|
|
187838
|
+
}
|
|
187839
|
+
}
|
|
187840
|
+
if (!candidate)
|
|
187841
|
+
return [];
|
|
187842
|
+
} else if (!/[|>&!]/.test(text) && !/[\r\n][^\r\n]/.test(text))
|
|
187843
|
+
return [];
|
|
187844
|
+
const out = [];
|
|
187845
|
+
const sorted = [...spans].sort((a, b) => a.start - b.start);
|
|
187846
|
+
let next = 0;
|
|
187847
|
+
let reach = -1;
|
|
187848
|
+
let reachRule = "";
|
|
187849
|
+
for (const doc of $parseAllDocuments(text, { keepSourceTokens: true, prettyErrors: false })) {
|
|
187850
|
+
if (doc.errors.length > 0)
|
|
187851
|
+
throw new Error("YAML value bounds are unavailable");
|
|
187852
|
+
$visit(doc, (_key, node, path) => {
|
|
187853
|
+
if (!$isScalar(node) || !node.srcToken || !("source" in node.srcToken) || !node.range)
|
|
187854
|
+
return;
|
|
187855
|
+
const block = node.srcToken.type === "block-scalar";
|
|
187856
|
+
const quoted = node.type === "QUOTE_SINGLE" || node.type === "QUOTE_DOUBLE";
|
|
187857
|
+
const raw = node.srcToken.source;
|
|
187858
|
+
if (!block && !node.anchor && !node.tag && !/[\r\n]/.test(raw))
|
|
187859
|
+
return;
|
|
187860
|
+
const source = quoted ? raw.slice(1, -1) : raw;
|
|
187861
|
+
const to = node.range[1] - (quoted ? 1 : 0);
|
|
187862
|
+
const from = to - source.length;
|
|
187863
|
+
const parent = path[path.length - 1];
|
|
187864
|
+
const name = $isPair(parent) && $isScalar(parent.key) ? String(parent.key.value) : "";
|
|
187865
|
+
while (next < sorted.length && sorted[next].start < from) {
|
|
187866
|
+
if (sorted[next].end > reach)
|
|
187867
|
+
[reach, reachRule] = [sorted[next].end, sorted[next].rule];
|
|
187868
|
+
next += 1;
|
|
187869
|
+
}
|
|
187870
|
+
const inside = reach > from ? reachRule : next < sorted.length && sorted[next].start < to ? sorted[next].rule : "";
|
|
187871
|
+
const credential = isCredentialName(name) && String(node.value).trim().split(/[ \t\r\n]+/).some(isCredentialValue);
|
|
187872
|
+
if (!inside && !everyValue && !credential)
|
|
187873
|
+
return;
|
|
187874
|
+
const rule2 = inside || (everyValue ? "env_value" : "credential_assignment");
|
|
187875
|
+
for (const line of source.matchAll(/[^\r\n]+/g)) {
|
|
187876
|
+
const lead = /^[ \t]*/.exec(line[0])[0].length;
|
|
187877
|
+
if (lead < line[0].length)
|
|
187878
|
+
out.push({ start: from + line.index + lead, end: from + line.index + line[0].length, rule: rule2 });
|
|
187879
|
+
}
|
|
187880
|
+
});
|
|
187881
|
+
}
|
|
187882
|
+
return out;
|
|
187883
|
+
}
|
|
187884
|
+
function redactText(path, text, categories, opts) {
|
|
187885
|
+
const heuristics = !categories.includes("lockfile") && !/\.min\.(js|css)$|\.map$/.test(path);
|
|
187886
|
+
const config = isConfigLike(path);
|
|
187887
|
+
const found = findSecretSpans(text, { heuristics, config: !categories.includes("source") });
|
|
187888
|
+
const withhold = found.find((s) => s.withholdFile);
|
|
187889
|
+
if (withhold)
|
|
187890
|
+
return { text, redactions: [], ranges: [], withholdRule: withhold.rule };
|
|
187891
|
+
const spans = found.map(({ start, end, rule: rule2 }) => ({ start, end, rule: rule2 }));
|
|
187892
|
+
const lockfile = categories.includes("lockfile");
|
|
187893
|
+
if (opts.envFile) {
|
|
187894
|
+
spans.push(...assignmentSpans(text, true, path, valueEnds(path, true)));
|
|
187895
|
+
spans.push(...unparsedEnvLines(text, spans));
|
|
187896
|
+
} else if (config && !lockfile && !isDockerfile(path))
|
|
187897
|
+
spans.push(...assignmentSpans(text, false, path, valueEnds(path, false)));
|
|
187898
|
+
if (isDockerfile(path))
|
|
187899
|
+
for (const span of dockerfileEnvSpans(text, spans))
|
|
187900
|
+
spans.push(span);
|
|
187901
|
+
if (config && !lockfile && /\.json[c5]?$/i.test(path))
|
|
187902
|
+
spans.push(...jsonSpans(text));
|
|
187903
|
+
if (config && !lockfile && !opts.envFile && !/\.jsonc?$/i.test(path))
|
|
187904
|
+
spans.push(...inlinePairSpans(text, path));
|
|
187905
|
+
if (!lockfile && /\.xml$/i.test(path))
|
|
187906
|
+
spans.push(...xmlSpans(text));
|
|
187907
|
+
if (/\.properties$/i.test(path))
|
|
187908
|
+
spans.push(...propertiesContinuations(text, spans));
|
|
187909
|
+
if (/\.ya?ml$/i.test(path)) {
|
|
187910
|
+
try {
|
|
187911
|
+
spans.push(...yamlValueSpans(text, spans, opts.envFile));
|
|
187912
|
+
} catch {
|
|
187913
|
+
return { text, redactions: [], ranges: [], withholdRule: "credential_assignment" };
|
|
187914
|
+
}
|
|
187915
|
+
}
|
|
187916
|
+
if (spans.length === 0)
|
|
187917
|
+
return { text, redactions: [], ranges: [] };
|
|
187918
|
+
spans.sort((a, b) => a.start - b.start || b.end - a.end);
|
|
187919
|
+
const merged = [];
|
|
187920
|
+
for (const span of spans) {
|
|
187921
|
+
if (span.end <= span.start)
|
|
187922
|
+
continue;
|
|
187923
|
+
const last = merged[merged.length - 1];
|
|
187924
|
+
if (last && span.start < last.end) {
|
|
187925
|
+
last.end = Math.max(last.end, span.end);
|
|
187926
|
+
if (GENERIC_RULES.has(last.rule) && !GENERIC_RULES.has(span.rule))
|
|
187927
|
+
last.rule = span.rule;
|
|
187928
|
+
} else {
|
|
187929
|
+
merged.push({ ...span });
|
|
187930
|
+
}
|
|
187931
|
+
}
|
|
187932
|
+
let out = "";
|
|
187933
|
+
let cursor = 0;
|
|
187934
|
+
let lineNo = 1;
|
|
187935
|
+
let lineCursor = 0;
|
|
187936
|
+
const redactions = [];
|
|
187937
|
+
for (const span of merged) {
|
|
187938
|
+
for (let i = lineCursor;i < span.start; i += 1)
|
|
187939
|
+
if (text.charCodeAt(i) === 10)
|
|
187940
|
+
lineNo += 1;
|
|
187941
|
+
lineCursor = span.start;
|
|
187942
|
+
const value = text.slice(span.start, span.end);
|
|
187943
|
+
out += text.slice(cursor, span.start) + mask(value);
|
|
187944
|
+
cursor = span.end;
|
|
187945
|
+
redactions.push({ line: lineNo, rule: span.rule, length: value.length });
|
|
187946
|
+
}
|
|
187947
|
+
out += text.slice(cursor);
|
|
187948
|
+
return { text: out, redactions, ranges: merged.map((span) => [span.start, span.end]) };
|
|
187949
|
+
}
|
|
187038
187950
|
|
|
187039
187951
|
// ../../packages/harness-bundle/src/collect/toolchain.ts
|
|
187040
187952
|
function isToolchainFile(path) {
|
|
@@ -187735,6 +188647,7 @@ class Collector {
|
|
|
187735
188647
|
texts = new Map;
|
|
187736
188648
|
env = new EnvCollector;
|
|
187737
188649
|
parentCache = new Map;
|
|
188650
|
+
redactions = [];
|
|
187738
188651
|
listedArtifacts = new Map;
|
|
187739
188652
|
constructor(repoRoot, opts) {
|
|
187740
188653
|
this.opts = opts;
|
|
@@ -187793,7 +188706,7 @@ class Collector {
|
|
|
187793
188706
|
const withPrefix = (p2) => prefix === "" ? p2 : `${prefix}/${p2}`;
|
|
187794
188707
|
const tracked = [...new Set(lsFiles(dir, ["--cached"]))].sort().map(withPrefix);
|
|
187795
188708
|
const untracked = lsFiles(dir, ["--others", "--exclude-standard"]).sort().map(withPrefix);
|
|
187796
|
-
const ignored =
|
|
188709
|
+
const ignored = ignoredPaths(dir).sort().map(withPrefix);
|
|
187797
188710
|
const ignoredDirs = ignored.filter((p2) => p2.endsWith("/"));
|
|
187798
188711
|
const ignoredRuleFiles = lsFiles(dir, ["--others", "--ignored", "--exclude-standard", "--", ":(glob)**/.modaignore"]).map(withPrefix).filter((p2) => !ignoredDirs.some((d) => p2.startsWith(d))).filter((p2) => {
|
|
187799
188712
|
const excluded = this.ancestorMatch(p2, "ignored");
|
|
@@ -187962,13 +188875,14 @@ class Collector {
|
|
|
187962
188875
|
this.addToAggregate(ancestor.dir, ancestor.rule, path, isDir);
|
|
187963
188876
|
return;
|
|
187964
188877
|
}
|
|
188878
|
+
const collectAll = this.opts.collectIgnored !== false;
|
|
187965
188879
|
if (isDir) {
|
|
187966
188880
|
const rule3 = this.dirMatch(path, "ignored");
|
|
187967
188881
|
if (rule3) {
|
|
187968
188882
|
this.recordDirOrFile(path, rule3);
|
|
187969
188883
|
return;
|
|
187970
188884
|
}
|
|
187971
|
-
if (this.includeIgnoredRules.size > 0 && this.includeIgnoredRules.matchesWithAncestors(path, true)) {
|
|
188885
|
+
if (collectAll || this.includeIgnoredRules.size > 0 && this.includeIgnoredRules.matchesWithAncestors(path, true)) {
|
|
187972
188886
|
this.walk(path, "ignored", null);
|
|
187973
188887
|
return;
|
|
187974
188888
|
}
|
|
@@ -187988,7 +188902,7 @@ class Collector {
|
|
|
187988
188902
|
this.excludeFile(path, "user_exclude", "modaignore", this.sizeOf(path));
|
|
187989
188903
|
return;
|
|
187990
188904
|
}
|
|
187991
|
-
if (this.includeIgnoredRules.size > 0 && this.includeIgnoredRules.matchesWithAncestors(path, false)) {
|
|
188905
|
+
if (collectAll || this.includeIgnoredRules.size > 0 && this.includeIgnoredRules.matchesWithAncestors(path, false)) {
|
|
187992
188906
|
this.consider(path, "ignored");
|
|
187993
188907
|
return;
|
|
187994
188908
|
}
|
|
@@ -188074,8 +188988,9 @@ class Collector {
|
|
|
188074
188988
|
}
|
|
188075
188989
|
return;
|
|
188076
188990
|
}
|
|
188077
|
-
const pathRule = fileRule(path);
|
|
188078
|
-
|
|
188991
|
+
const pathRule = fileRule(path) ?? runtimeLogRule(path, status);
|
|
188992
|
+
const envValueFile = pathRule?.reason === "secret_path" && ENV_VALUE_FILE_RULES.has(pathRule.rule) && status === "tracked";
|
|
188993
|
+
if (pathRule && !envValueFile) {
|
|
188079
188994
|
this.excludeFile(path, pathRule.reason, pathRule.rule, st.size);
|
|
188080
188995
|
return;
|
|
188081
188996
|
}
|
|
@@ -188106,20 +189021,48 @@ class Collector {
|
|
|
188106
189021
|
const text = encoding === "text" ? buf.toString("utf8") : undefined;
|
|
188107
189022
|
const categoryText = text !== undefined && /^(package\.json|pyproject\.toml|Cargo\.toml)$/.test(basenameOf(path)) ? text : undefined;
|
|
188108
189023
|
const categories = categorize({ path, encoding, head: text?.slice(0, 1024), text: categoryText });
|
|
188109
|
-
|
|
188110
|
-
|
|
188111
|
-
|
|
188112
|
-
|
|
189024
|
+
if (envValueFile && !categories.includes("env_example"))
|
|
189025
|
+
categories.push("env_example");
|
|
189026
|
+
const envFile = envValueFile || categories.includes("env_example");
|
|
189027
|
+
let shipped = buf;
|
|
189028
|
+
if (text !== undefined) {
|
|
189029
|
+
const redacted = redactText(path, text, categories, { envFile });
|
|
189030
|
+
if (redacted.withholdRule) {
|
|
189031
|
+
this.excludeFile(path, "secret_content", redacted.withholdRule, buf.length);
|
|
189032
|
+
return;
|
|
189033
|
+
}
|
|
189034
|
+
const credential = redacted.redactions.find((r) => r.rule !== "env_value");
|
|
189035
|
+
if (credential && status !== "tracked" && !categories.includes("env_example")) {
|
|
189036
|
+
this.excludeFile(path, "secret_content", credential.rule, buf.length);
|
|
189037
|
+
return;
|
|
189038
|
+
}
|
|
189039
|
+
const unmasked = registryAuthFindings(path, text).find((finding) => !rangeCovered(redacted.ranges, finding.start, finding.end));
|
|
189040
|
+
if (unmasked) {
|
|
189041
|
+
this.excludeFile(path, "secret_path", unmasked.rule, buf.length);
|
|
189042
|
+
return;
|
|
189043
|
+
}
|
|
189044
|
+
if (redacted.redactions.length > 0) {
|
|
189045
|
+
shipped = Buffer.from(redacted.text, "utf8");
|
|
189046
|
+
for (const r of redacted.redactions)
|
|
189047
|
+
this.redactions.push({ path, ...r });
|
|
189048
|
+
}
|
|
189049
|
+
} else {
|
|
189050
|
+
const finding = contentSecretFinding(path, buf, text, categories);
|
|
189051
|
+
if (finding) {
|
|
189052
|
+
this.excludeFile(path, finding.reason, finding.rule, buf.length);
|
|
189053
|
+
return;
|
|
189054
|
+
}
|
|
188113
189055
|
}
|
|
188114
189056
|
this.included.set(path, {
|
|
188115
189057
|
path,
|
|
188116
|
-
bytes:
|
|
188117
|
-
sha256: sha256(
|
|
189058
|
+
bytes: shipped.length,
|
|
189059
|
+
sha256: sha256(shipped),
|
|
188118
189060
|
executable: (st.mode & 73) !== 0,
|
|
188119
189061
|
encoding,
|
|
188120
|
-
categories,
|
|
189062
|
+
categories: [...categories].sort(),
|
|
188121
189063
|
git: status,
|
|
188122
|
-
absolutePath: abs
|
|
189064
|
+
absolutePath: abs,
|
|
189065
|
+
...shipped !== buf ? { redaction: { envFile }, sourceSha256: sha256(buf) } : {}
|
|
188123
189066
|
});
|
|
188124
189067
|
if (text !== undefined) {
|
|
188125
189068
|
if (isToolchainFile(path))
|
|
@@ -188304,7 +189247,15 @@ class Collector {
|
|
|
188304
189247
|
].sort((a, b) => compare(a.path, b.path) || compare(a.reason, b.reason));
|
|
188305
189248
|
const textOf = (path) => this.texts.get(path);
|
|
188306
189249
|
const toolchain = detectToolchain(files.map((f) => f.path), textOf, harnessRel);
|
|
188307
|
-
const manifestFiles = files.map(({
|
|
189250
|
+
const manifestFiles = files.map(({
|
|
189251
|
+
absolutePath: _absolutePath,
|
|
189252
|
+
linkTargetOnDisk: _linkTargetOnDisk,
|
|
189253
|
+
redaction: _redaction,
|
|
189254
|
+
sourceSha256: _sourceSha256,
|
|
189255
|
+
...file
|
|
189256
|
+
}) => file);
|
|
189257
|
+
const shippedPaths = new Set(manifestFiles.map((f) => f.path));
|
|
189258
|
+
const redactions = this.redactions.filter((r) => shippedPaths.has(r.path)).sort((a, b) => compare(a.path, b.path) || a.line - b.line);
|
|
188308
189259
|
const bytes = manifestFiles.reduce((sum, f) => sum + f.bytes, 0);
|
|
188309
189260
|
const manifest = {
|
|
188310
189261
|
schema: HARNESS_BUNDLE_SCHEMA,
|
|
@@ -188326,6 +189277,7 @@ class Collector {
|
|
|
188326
189277
|
totals: { files: manifestFiles.length, bytes, excluded: excluded.length },
|
|
188327
189278
|
files: manifestFiles,
|
|
188328
189279
|
excluded,
|
|
189280
|
+
...redactions.length > 0 ? { redactions } : {},
|
|
188329
189281
|
ignoredPresent: this.collapseIgnored(),
|
|
188330
189282
|
toolchain,
|
|
188331
189283
|
env: this.env.finalize(new Set(manifestFiles.map((f) => f.path))),
|
|
@@ -188471,6 +189423,19 @@ function isOutside(rel2) {
|
|
|
188471
189423
|
function stripUndefined(value) {
|
|
188472
189424
|
return Object.fromEntries(Object.entries(value).filter(([, v]) => v !== undefined));
|
|
188473
189425
|
}
|
|
189426
|
+
function rangeCovered(ranges, start, end) {
|
|
189427
|
+
let at = start;
|
|
189428
|
+
for (const [s, e] of ranges) {
|
|
189429
|
+
if (e <= at)
|
|
189430
|
+
continue;
|
|
189431
|
+
if (s > at)
|
|
189432
|
+
return false;
|
|
189433
|
+
at = e;
|
|
189434
|
+
if (at >= end)
|
|
189435
|
+
return true;
|
|
189436
|
+
}
|
|
189437
|
+
return at >= end;
|
|
189438
|
+
}
|
|
188474
189439
|
// ../../packages/harness-bundle/src/collect/write.ts
|
|
188475
189440
|
import { createHash as createHash3, randomUUID } from "node:crypto";
|
|
188476
189441
|
import { createWriteStream, existsSync as existsSync5, lstatSync as lstatSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync3, readFileSync as readFileSync5, readlinkSync as readlinkSync2, realpathSync as realpathSync3, renameSync, rmSync, statSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
@@ -188634,6 +189599,14 @@ function replaceTogether(moves, token) {
|
|
|
188634
189599
|
for (const [backup] of backups)
|
|
188635
189600
|
rmSync(backup, { force: true });
|
|
188636
189601
|
}
|
|
189602
|
+
function shippedBody(file, disk = readFileSync5(file.absolutePath)) {
|
|
189603
|
+
if (!file.redaction)
|
|
189604
|
+
return disk;
|
|
189605
|
+
const body = Buffer.from(redactText(file.path, disk.toString("utf8"), file.categories, file.redaction).text, "utf8");
|
|
189606
|
+
if (sha256(body) !== file.sha256)
|
|
189607
|
+
throw new Error(`${file.path} changed after collection; re-run the collector`);
|
|
189608
|
+
return body;
|
|
189609
|
+
}
|
|
188637
189610
|
function* tarChunks(files) {
|
|
188638
189611
|
const sorted = [...files].sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
188639
189612
|
for (const file of sorted) {
|
|
@@ -188652,10 +189625,10 @@ function* tarChunks(files) {
|
|
|
188652
189625
|
} else {
|
|
188653
189626
|
const body = readFileSync5(file.absolutePath);
|
|
188654
189627
|
const executableNow = (statSync(file.absolutePath).mode & 73) !== 0;
|
|
188655
|
-
if (sha256(body) !== file.sha256 || executableNow !== file.executable) {
|
|
189628
|
+
if (sha256(body) !== (file.sourceSha256 ?? file.sha256) || executableNow !== file.executable) {
|
|
188656
189629
|
throw new Error(`${file.path} changed after collection; re-run the collector`);
|
|
188657
189630
|
}
|
|
188658
|
-
entry = { path: file.path, type: "file", mode: file.executable ? 493 : 420, body };
|
|
189631
|
+
entry = { path: file.path, type: "file", mode: file.executable ? 493 : 420, body: shippedBody(file, body) };
|
|
188659
189632
|
}
|
|
188660
189633
|
yield* encodeEntry(entry);
|
|
188661
189634
|
}
|
|
@@ -188689,7 +189662,6 @@ async function collectRegistration(request) {
|
|
|
188689
189662
|
throw new Error(`Git could not list this checkout, so the bundle would ignore .gitignore; nothing was collected. ${gitFailure ?? "Check that git works here (safe.directory, a readable index)."}`);
|
|
188690
189663
|
}
|
|
188691
189664
|
const deployArtifacts = request.imageRef ? [{ producedBy: "customer", kind: "oci_image", digest: request.imageRef.slice(request.imageRef.lastIndexOf("@") + 1), imageRef: request.imageRef }] : [];
|
|
188692
|
-
redactEnvExamples(result, join7(request.outDir, "redacted"));
|
|
188693
189665
|
const written = await writeBundle(result, request.outDir, { deployArtifacts: async () => deployArtifacts });
|
|
188694
189666
|
const stage = join7(request.outDir, "stage");
|
|
188695
189667
|
let dependencyMap;
|
|
@@ -188701,6 +189673,7 @@ async function collectRegistration(request) {
|
|
|
188701
189673
|
} finally {
|
|
188702
189674
|
rmSync2(stage, { recursive: true, force: true });
|
|
188703
189675
|
}
|
|
189676
|
+
keepRedactedExamplesFalse(dependencyMap, written.manifest);
|
|
188704
189677
|
const mapPath = join7(request.outDir, "dependency-map.json");
|
|
188705
189678
|
writeFileSync4(mapPath, `${JSON.stringify(dependencyMap, null, 2)}
|
|
188706
189679
|
`);
|
|
@@ -188713,64 +189686,20 @@ async function collectRegistration(request) {
|
|
|
188713
189686
|
dependencyMapFile: await digestFile(mapPath)
|
|
188714
189687
|
};
|
|
188715
189688
|
}
|
|
188716
|
-
|
|
188717
|
-
|
|
188718
|
-
const
|
|
188719
|
-
|
|
188720
|
-
|
|
188721
|
-
|
|
188722
|
-
|
|
188723
|
-
|
|
188724
|
-
const
|
|
188725
|
-
|
|
188726
|
-
mkdirSync4(dirname5(target), { recursive: true });
|
|
188727
|
-
writeFileSync4(target, body, { mode: file.executable ? 493 : 420 });
|
|
188728
|
-
const sha2562 = createHash4("sha256").update(body).digest("hex");
|
|
188729
|
-
Object.assign(file, { absolutePath: target, sha256: sha2562, bytes: body.byteLength });
|
|
188730
|
-
const listed = byPath.get(file.path);
|
|
188731
|
-
if (listed)
|
|
188732
|
-
Object.assign(listed, { sha256: sha2562, bytes: body.byteLength });
|
|
188733
|
-
}
|
|
188734
|
-
result.manifest.totals.bytes = result.manifest.files.reduce((sum, file) => sum + file.bytes, 0);
|
|
188735
|
-
if (redacted) {
|
|
188736
|
-
const env = new EnvCollector;
|
|
188737
|
-
for (const file of result.files) {
|
|
188738
|
-
if (file.encoding !== "text" || file.symlinkTarget !== undefined || file.bytes > MAX_ENV_RESCAN_BYTES)
|
|
188739
|
-
continue;
|
|
188740
|
-
env.scanFile(file.path, readFileSync6(file.absolutePath, "utf8"), file.categories);
|
|
188741
|
-
}
|
|
188742
|
-
result.manifest.env = env.finalize(new Set(result.files.map((file) => file.path)));
|
|
188743
|
-
}
|
|
188744
|
-
}
|
|
188745
|
-
function envNamesOnly(text) {
|
|
188746
|
-
const names = [];
|
|
188747
|
-
let open = null;
|
|
188748
|
-
for (const line of text.split(`
|
|
188749
|
-
`)) {
|
|
188750
|
-
if (open) {
|
|
188751
|
-
if (closes(line, open, 0))
|
|
188752
|
-
open = null;
|
|
188753
|
-
continue;
|
|
188754
|
-
}
|
|
188755
|
-
const match = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(line);
|
|
188756
|
-
if (!match)
|
|
189689
|
+
function keepRedactedExamplesFalse(map, manifest) {
|
|
189690
|
+
const redactedPaths = new Set((manifest.redactions ?? []).map((r) => r.path));
|
|
189691
|
+
const redactedEnvFiles = new Set(manifest.files.filter((file) => file.categories.includes("env_example") && redactedPaths.has(file.path)).map((file) => file.path));
|
|
189692
|
+
if (redactedEnvFiles.size === 0)
|
|
189693
|
+
return;
|
|
189694
|
+
const collected = new Map(manifest.env.map((ref) => [ref.name, ref]));
|
|
189695
|
+
const sourcePath = (source) => source.replace(/:\d+$/, "");
|
|
189696
|
+
for (const ref of map.env) {
|
|
189697
|
+
const seen = collected.get(ref.name);
|
|
189698
|
+
if (!seen || seen.hasExampleValue || !ref.hasExampleValue)
|
|
188757
189699
|
continue;
|
|
188758
|
-
|
|
188759
|
-
|
|
188760
|
-
if ((quote === '"' || quote === "'" || quote === "`") && !closes(match[2], quote, 1))
|
|
188761
|
-
open = quote;
|
|
188762
|
-
}
|
|
188763
|
-
return names.map((name) => `${name}=
|
|
188764
|
-
`).join("");
|
|
188765
|
-
}
|
|
188766
|
-
function closes(text, quote, from) {
|
|
188767
|
-
for (let i = from;i < text.length; i++) {
|
|
188768
|
-
if (text[i] === "\\" && quote !== "'")
|
|
188769
|
-
i++;
|
|
188770
|
-
else if (text[i] === quote)
|
|
188771
|
-
return true;
|
|
189700
|
+
if (seen.sources.some((source) => redactedEnvFiles.has(sourcePath(source))))
|
|
189701
|
+
ref.hasExampleValue = false;
|
|
188772
189702
|
}
|
|
188773
|
-
return false;
|
|
188774
189703
|
}
|
|
188775
189704
|
function insideCheckout(dir) {
|
|
188776
189705
|
for (let current = realpathSync4(dir);; current = dirname5(current)) {
|
|
@@ -188983,7 +189912,7 @@ function parseRegisterOptions(context, argv) {
|
|
|
188983
189912
|
}
|
|
188984
189913
|
function defaultHarnessName(root) {
|
|
188985
189914
|
try {
|
|
188986
|
-
const name = JSON.parse(
|
|
189915
|
+
const name = JSON.parse(readFileSync6(join8(root, "package.json"), "utf8")).name;
|
|
188987
189916
|
if (typeof name === "string" && name)
|
|
188988
189917
|
return sanitizeName(name.replace(/^@[^/]+\//, ""));
|
|
188989
189918
|
} catch {}
|
|
@@ -189019,6 +189948,7 @@ function buildRegisterReport(collected) {
|
|
|
189019
189948
|
byCategory: [...byCategory].map(([category, entry]) => ({ category, ...entry })).sort((a, b) => b.bytes - a.bytes)
|
|
189020
189949
|
},
|
|
189021
189950
|
excluded: manifest.excluded,
|
|
189951
|
+
redactions: manifest.redactions ?? [],
|
|
189022
189952
|
ignoredPresent: manifest.ignoredPresent,
|
|
189023
189953
|
env,
|
|
189024
189954
|
toolchain: manifest.toolchain,
|
|
@@ -189133,6 +190063,15 @@ function renderRegisterReport(report, registration) {
|
|
|
189133
190063
|
const rule2 = item.rule ? `, rule ${item.rule}` : "";
|
|
189134
190064
|
lines.push(` ${pad(item.path, 40)} ${item.reason}: ${EXCLUSION_REASONS[item.reason] ?? item.reason}${rule2}${size}`);
|
|
189135
190065
|
}
|
|
190066
|
+
if (report.redactions.length > 0) {
|
|
190067
|
+
lines.push("");
|
|
190068
|
+
lines.push(`Redacted: ${report.redactions.length} value(s) masked in place. The files ship; the values never leave this machine.`);
|
|
190069
|
+
for (const item of report.redactions.slice(0, 40)) {
|
|
190070
|
+
lines.push(` ${pad(`${item.path}:${item.line}`, 40)} ${item.rule} (${item.length} chars)`);
|
|
190071
|
+
}
|
|
190072
|
+
if (report.redactions.length > 40)
|
|
190073
|
+
lines.push(` ... ${report.redactions.length - 40} more (see the manifest)`);
|
|
190074
|
+
}
|
|
189136
190075
|
if (report.ignoredPresent.length > 0) {
|
|
189137
190076
|
lines.push("");
|
|
189138
190077
|
lines.push(`Git-ignored but present, not uploaded (names only): ${report.ignoredPresent.length}`);
|
|
@@ -189239,7 +190178,7 @@ function formatBytes(bytes) {
|
|
|
189239
190178
|
}
|
|
189240
190179
|
|
|
189241
190180
|
// src/harness-artifact-bodies.ts
|
|
189242
|
-
import { existsSync as existsSync7, lstatSync as lstatSync5, readFileSync as
|
|
190181
|
+
import { existsSync as existsSync7, lstatSync as lstatSync5, readFileSync as readFileSync7, realpathSync as realpathSync5 } from "node:fs";
|
|
189243
190182
|
import { basename as basename5, dirname as dirname6, isAbsolute as isAbsolute3, relative as relative4, resolve as resolve5 } from "node:path";
|
|
189244
190183
|
var MAX_SCANNED_FILE_BYTES2 = 512 * 1024;
|
|
189245
190184
|
var SNAPSHOT_BUDGET_SKIP_REASONS = new Set([
|
|
@@ -189303,7 +190242,7 @@ function readBoundedRepoText(absPath, rootDir) {
|
|
|
189303
190242
|
return;
|
|
189304
190243
|
}
|
|
189305
190244
|
try {
|
|
189306
|
-
return
|
|
190245
|
+
return readFileSync7(absPath, "utf8");
|
|
189307
190246
|
} catch {
|
|
189308
190247
|
return;
|
|
189309
190248
|
}
|
|
@@ -189854,9 +190793,9 @@ function detectPromptLiterals(file, out) {
|
|
|
189854
190793
|
});
|
|
189855
190794
|
};
|
|
189856
190795
|
if (ext === ".py") {
|
|
189857
|
-
const
|
|
190796
|
+
const tripleQuoted2 = /("""|''')([\s\S]*?)\1/g;
|
|
189858
190797
|
let match;
|
|
189859
|
-
while ((match =
|
|
190798
|
+
while ((match = tripleQuoted2.exec(file.text)) !== null) {
|
|
189860
190799
|
record(match.index, match.index + match[0].length - 1, match[2], "python.triple_quoted_string");
|
|
189861
190800
|
}
|
|
189862
190801
|
return;
|
|
@@ -190036,7 +190975,7 @@ import { extname as extname8 } from "node:path";
|
|
|
190036
190975
|
// src/prompt-sources.ts
|
|
190037
190976
|
var import_typescript2 = __toESM(require_typescript(), 1);
|
|
190038
190977
|
import { createHash as createHash5 } from "node:crypto";
|
|
190039
|
-
import { lstatSync as lstatSync7, readFileSync as
|
|
190978
|
+
import { lstatSync as lstatSync7, readFileSync as readFileSync10, realpathSync as realpathSync8 } from "node:fs";
|
|
190040
190979
|
import { extname as extname3, isAbsolute as isAbsolute4, relative as relative5, resolve as resolve9 } from "node:path";
|
|
190041
190980
|
|
|
190042
190981
|
// src/prompt-frameworks.ts
|
|
@@ -190058,7 +190997,7 @@ var TYPESCRIPT_AGENT_MODULES = [
|
|
|
190058
190997
|
|
|
190059
190998
|
// src/prompt-source-code.ts
|
|
190060
190999
|
var import_typescript = __toESM(require_typescript(), 1);
|
|
190061
|
-
import { existsSync as existsSync8, lstatSync as lstatSync6, readFileSync as
|
|
191000
|
+
import { existsSync as existsSync8, lstatSync as lstatSync6, readFileSync as readFileSync8, realpathSync as realpathSync6 } from "node:fs";
|
|
190062
191001
|
import { dirname as dirname8, extname as extname2, join as join9, resolve as resolve7 } from "node:path";
|
|
190063
191002
|
var EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
190064
191003
|
var MAX_BYTES = 2 * 1024 * 1024;
|
|
@@ -190099,7 +191038,7 @@ function parseFile(filePath, state) {
|
|
|
190099
191038
|
const cached = state.parsed.get(path);
|
|
190100
191039
|
if (cached)
|
|
190101
191040
|
return cached;
|
|
190102
|
-
const text =
|
|
191041
|
+
const text = readFileSync8(path, "utf8");
|
|
190103
191042
|
state.bytesRead += Buffer.byteLength(text);
|
|
190104
191043
|
state.files.push(path);
|
|
190105
191044
|
const scriptKind = extname2(path) === ".json" ? import_typescript.default.ScriptKind.JSON : /\.tsx?$/.test(extname2(path)) ? import_typescript.default.ScriptKind.TSX : import_typescript.default.ScriptKind.JSX;
|
|
@@ -190537,7 +191476,7 @@ function referenceNames(node) {
|
|
|
190537
191476
|
|
|
190538
191477
|
// src/prompt-source-python.ts
|
|
190539
191478
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
190540
|
-
import { readFileSync as
|
|
191479
|
+
import { readFileSync as readFileSync9, realpathSync as realpathSync7 } from "node:fs";
|
|
190541
191480
|
import { resolve as resolve8 } from "node:path";
|
|
190542
191481
|
var PYTHON_AGENT_MODULES_LITERAL = JSON.stringify(PYTHON_AGENT_MODULES);
|
|
190543
191482
|
var SELECTOR_HELPER = String.raw`import ast,json,os,sys
|
|
@@ -191004,7 +191943,7 @@ except Exception as e:
|
|
|
191004
191943
|
function extractPythonSource(rootDir, sourcePath, symbol, _forceDependencyGraph = false) {
|
|
191005
191944
|
let raw = "";
|
|
191006
191945
|
try {
|
|
191007
|
-
raw =
|
|
191946
|
+
raw = readFileSync9(sourcePath, "utf8");
|
|
191008
191947
|
} catch {}
|
|
191009
191948
|
const result = spawnSync2("python3", ["-I", "-c", HELPER], {
|
|
191010
191949
|
input: JSON.stringify({ root: rootDir, path: sourcePath, symbol, force: _forceDependencyGraph }),
|
|
@@ -191098,7 +192037,7 @@ function resolvePromptSource(rootDir, source) {
|
|
|
191098
192037
|
} else if (source.selector?.symbol) {
|
|
191099
192038
|
throw new Error(`${sourcePath}: symbol selectors require a JavaScript, TypeScript, or Python source file`);
|
|
191100
192039
|
} else if (ext === ".json" || ext === ".yaml" || ext === ".yml" || hasPointer || source.kind === "messages") {
|
|
191101
|
-
const parsed = parseStructured(
|
|
192040
|
+
const parsed = parseStructured(readFileSync10(sourceAbs, "utf8"), sourcePath, ext);
|
|
191102
192041
|
const selected = hasPointer ? jsonPointer(parsed, source.selector.pointer, sourcePath) : parsed;
|
|
191103
192042
|
const selectedField = source.selector?.pointer?.split("/").at(-1)?.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
191104
192043
|
const inferredKind = !source.kind && selectedField && /^(?:template|system_template|instance_template)$/.test(selectedField) ? "template" : source.kind;
|
|
@@ -191108,7 +192047,7 @@ function resolvePromptSource(rootDir, source) {
|
|
|
191108
192047
|
messages = structured.messages;
|
|
191109
192048
|
kind = structured.kind;
|
|
191110
192049
|
} else {
|
|
191111
|
-
const raw =
|
|
192050
|
+
const raw = readFileSync10(sourceAbs, "utf8");
|
|
191112
192051
|
if (ext === ".md" && /\.prompt\.md$/i.test(sourcePath)) {
|
|
191113
192052
|
const legacy = parseLegacyMarkdown(raw);
|
|
191114
192053
|
content = legacy.content;
|
|
@@ -191131,7 +192070,7 @@ function resolvePromptSource(rootDir, source) {
|
|
|
191131
192070
|
const depAbs = safePath(root, dependency.path);
|
|
191132
192071
|
files.add(depAbs);
|
|
191133
192072
|
if (typeof dependency.selector?.pointer === "string") {
|
|
191134
|
-
const parsed = parseStructured(
|
|
192073
|
+
const parsed = parseStructured(readFileSync10(depAbs, "utf8"), dependency.path, extname3(depAbs).toLowerCase());
|
|
191135
192074
|
jsonPointer(parsed, dependency.selector.pointer, dependency.path);
|
|
191136
192075
|
} else if (dependency.selector?.symbol && CODE_EXTENSIONS2.has(extname3(depAbs).toLowerCase())) {
|
|
191137
192076
|
const dep = extname3(depAbs).toLowerCase() === ".py" ? extractPythonSource(root, depAbs, dependency.selector.symbol) : extractCodeSource(root, depAbs, dependency.selector.symbol);
|
|
@@ -191154,7 +192093,7 @@ function resolvePromptSource(rootDir, source) {
|
|
|
191154
192093
|
assertSafeMaterializedContent(content, sourcePath);
|
|
191155
192094
|
else
|
|
191156
192095
|
assertSafeMaterializedContent(materialized, sourcePath);
|
|
191157
|
-
const dependencies = [...files].sort().map((path) => ({ path: relative5(root, path).replaceAll("\\", "/"), contentHash: sha2562(
|
|
192096
|
+
const dependencies = [...files].sort().map((path) => ({ path: relative5(root, path).replaceAll("\\", "/"), contentHash: sha2562(readFileSync10(path)) }));
|
|
191158
192097
|
const sourceHash = sha2562(JSON.stringify({ kind, content, systemPrompt: systemPrompt ?? null, messages: messages ?? null }));
|
|
191159
192098
|
const sourceDefinition = {
|
|
191160
192099
|
schemaVersion: 1,
|
|
@@ -191224,7 +192163,7 @@ function discoverStructuredPromptSources(rootDir, sourcePath) {
|
|
|
191224
192163
|
const ext = extname3(file).toLowerCase();
|
|
191225
192164
|
if (![".json", ".yaml", ".yml"].includes(ext))
|
|
191226
192165
|
return [];
|
|
191227
|
-
const value = parseStructured(
|
|
192166
|
+
const value = parseStructured(readFileSync10(file, "utf8"), sourcePath, ext);
|
|
191228
192167
|
const sources = [];
|
|
191229
192168
|
const base = sourcePath.replace(/\.[^.]+$/, "").replace(/[^A-Za-z0-9_.-]+/g, ".");
|
|
191230
192169
|
const dedicatedPath = /(^|\/)prompts?(?:\/|\.[^/]+$)|\.prompt\.[^.]+$/i.test(sourcePath);
|
|
@@ -191300,14 +192239,14 @@ function discoverCodePromptCandidates(rootDir, sourcePath) {
|
|
|
191300
192239
|
addName(candidate.symbol, candidate.knownBuilder === true);
|
|
191301
192240
|
modelInputs.add(candidate.symbol);
|
|
191302
192241
|
}
|
|
191303
|
-
for (const match of
|
|
192242
|
+
for (const match of readFileSync10(file, "utf8").matchAll(/^(?:(?:async\s+)?def\s+([A-Za-z_]\w*)|([A-Za-z_]\w*)\s*=\s*([^\n#]+))/gm)) {
|
|
191304
192243
|
const name = match[1] ?? match[2];
|
|
191305
192244
|
const rhs = match[3] ?? "";
|
|
191306
192245
|
if (name && isPromptName2(name) && (match[1] || /['"`\[({+]/.test(rhs) || /^[A-Za-z_]\w*\s*$/.test(rhs)))
|
|
191307
192246
|
addName(name, Boolean(match[1]));
|
|
191308
192247
|
}
|
|
191309
192248
|
} else {
|
|
191310
|
-
const sf = import_typescript2.default.createSourceFile(file,
|
|
192249
|
+
const sf = import_typescript2.default.createSourceFile(file, readFileSync10(file, "utf8"), import_typescript2.default.ScriptTarget.Latest, true, import_typescript2.default.ScriptKind.TSX);
|
|
191311
192250
|
const agentConstructors = new Set;
|
|
191312
192251
|
for (const statement of sf.statements) {
|
|
191313
192252
|
if (!import_typescript2.default.isImportDeclaration(statement) || !import_typescript2.default.isStringLiteral(statement.moduleSpecifier) || !TYPESCRIPT_AGENT_MODULES.includes(statement.moduleSpecifier.text))
|
|
@@ -191541,7 +192480,7 @@ function sha2562(input) {
|
|
|
191541
192480
|
}
|
|
191542
192481
|
|
|
191543
192482
|
// src/prompt-source-verification/index.ts
|
|
191544
|
-
import { readFileSync as
|
|
192483
|
+
import { readFileSync as readFileSync14 } from "node:fs";
|
|
191545
192484
|
import { z } from "zod";
|
|
191546
192485
|
|
|
191547
192486
|
// src/prompt-source-validation.ts
|
|
@@ -191630,7 +192569,7 @@ function isPromptDefinitionPath(path) {
|
|
|
191630
192569
|
}
|
|
191631
192570
|
|
|
191632
192571
|
// src/prompt-source-verification/evidence.ts
|
|
191633
|
-
import { readFileSync as
|
|
192572
|
+
import { readFileSync as readFileSync13 } from "node:fs";
|
|
191634
192573
|
import { extname as extname7 } from "node:path";
|
|
191635
192574
|
|
|
191636
192575
|
// src/prompt-source-verification/paths.ts
|
|
@@ -191660,14 +192599,14 @@ function safePromptEvidencePath(rootDir, path) {
|
|
|
191660
192599
|
var import_typescript3 = __toESM(require_typescript(), 1);
|
|
191661
192600
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
191662
192601
|
import { extname as extname5 } from "node:path";
|
|
191663
|
-
import { readFileSync as
|
|
192602
|
+
import { readFileSync as readFileSync11 } from "node:fs";
|
|
191664
192603
|
function proveSink(root, sink) {
|
|
191665
192604
|
const file = safePromptEvidencePath(root, sink.path);
|
|
191666
192605
|
const cache = new Map;
|
|
191667
192606
|
if (!cache.has(file)) {
|
|
191668
192607
|
if (extname5(file) === ".py") {
|
|
191669
192608
|
try {
|
|
191670
|
-
const rows = JSON.parse(execFileSync2("python3", ["-I", "-c", PYTHON_PROOF], { input:
|
|
192609
|
+
const rows = JSON.parse(execFileSync2("python3", ["-I", "-c", PYTHON_PROOF], { input: readFileSync11(file, "utf8"), encoding: "utf8", timeout: 1e4, maxBuffer: 2 * 1024 * 1024 }));
|
|
191671
192610
|
cache.set(file, new Map(Object.entries(rows).map(([line, proof]) => [Number(line), proof])));
|
|
191672
192611
|
} catch {
|
|
191673
192612
|
cache.set(file, new Map);
|
|
@@ -191834,7 +192773,7 @@ print(json.dumps(rows))
|
|
|
191834
192773
|
`;
|
|
191835
192774
|
|
|
191836
192775
|
// src/prompt-source-location.ts
|
|
191837
|
-
import { readFileSync as
|
|
192776
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
191838
192777
|
import { extname as extname6 } from "node:path";
|
|
191839
192778
|
function structuredExcerpt(text, source) {
|
|
191840
192779
|
if (source.selector?.pointer === undefined)
|
|
@@ -191888,7 +192827,7 @@ function promptDefinitionExcerpt(rootDir, source) {
|
|
|
191888
192827
|
return;
|
|
191889
192828
|
return { ...extraction.range, text: extraction.sourceText, ...extraction.declarationKind ? { declarationKind: extraction.declarationKind } : {} };
|
|
191890
192829
|
}
|
|
191891
|
-
const text =
|
|
192830
|
+
const text = readFileSync12(file, "utf8");
|
|
191892
192831
|
return structuredExcerpt(text, source);
|
|
191893
192832
|
}
|
|
191894
192833
|
function promptDefinitionRange(rootDir, source) {
|
|
@@ -191915,7 +192854,7 @@ function reviewEvidence(rootDir, source, evidence) {
|
|
|
191915
192854
|
for (const item of evidence) {
|
|
191916
192855
|
let text;
|
|
191917
192856
|
try {
|
|
191918
|
-
text =
|
|
192857
|
+
text = readFileSync13(safePromptEvidencePath(rootDir, item.path), "utf8");
|
|
191919
192858
|
} catch (error) {
|
|
191920
192859
|
if (item.kind === "model_endpoint")
|
|
191921
192860
|
return { valid: false, endpointVerified: false, reason: error instanceof Error ? error.message : String(error) };
|
|
@@ -192030,7 +192969,7 @@ async function independentlyVerifyPromptSource(rootDir, source, verifier) {
|
|
|
192030
192969
|
let priorJudgment;
|
|
192031
192970
|
try {
|
|
192032
192971
|
const before = JSON.stringify(checked.resolved.sourceDefinition);
|
|
192033
|
-
const sourceBytes =
|
|
192972
|
+
const sourceBytes = readFileSync14(safePromptEvidencePath(rootDir, source.path), "utf8");
|
|
192034
192973
|
const instruction = promptVerificationInstruction(checked.source, checked.sourceHash, promptDefinitionExcerpt(rootDir, checked.source));
|
|
192035
192974
|
for (let attempt = 0;attempt < 2; attempt++) {
|
|
192036
192975
|
const repair = attempt ? `
|
|
@@ -192061,7 +193000,7 @@ ${output}` : "";
|
|
|
192061
193000
|
}
|
|
192062
193001
|
if (reviewed.truncated || reviewed.sourceHash !== checked.sourceHash)
|
|
192063
193002
|
return pending("Verifier output is truncated or cites a different source hash", reviewed.evidence, reviewed.role, normalizeUsage(undefined, false));
|
|
192064
|
-
if (before !== snapshot() ||
|
|
193003
|
+
if (before !== snapshot() || readFileSync14(safePromptEvidencePath(rootDir, source.path), "utf8") !== sourceBytes)
|
|
192065
193004
|
return pending("Source changed during verification", reviewed.evidence, reviewed.role, normalizeUsage(undefined, false));
|
|
192066
193005
|
if (reviewed.role === "non_prompt")
|
|
192067
193006
|
return { status: "rejected", reason: reviewed.reason, evidence: reviewed.evidence, sourceHash: checked.sourceHash, role: reviewed.role, usage: normalizeUsage(undefined, false) };
|
|
@@ -192421,7 +193360,7 @@ function applyPromptDiscovery(graph, discovery) {
|
|
|
192421
193360
|
}
|
|
192422
193361
|
|
|
192423
193362
|
// src/harness-candidate-promotion.ts
|
|
192424
|
-
import { readFileSync as
|
|
193363
|
+
import { readFileSync as readFileSync15 } from "node:fs";
|
|
192425
193364
|
import { resolve as resolve12 } from "node:path";
|
|
192426
193365
|
var PROMOTED_CONFIDENCE = {
|
|
192427
193366
|
high: 0.85,
|
|
@@ -192452,7 +193391,7 @@ function readFileLines(rootDir, path, cache) {
|
|
|
192452
193391
|
return cached;
|
|
192453
193392
|
let lines;
|
|
192454
193393
|
try {
|
|
192455
|
-
lines =
|
|
193394
|
+
lines = readFileSync15(resolve12(rootDir, path), "utf8").split(/\r?\n/);
|
|
192456
193395
|
} catch {
|
|
192457
193396
|
lines = null;
|
|
192458
193397
|
}
|
|
@@ -193996,7 +194935,7 @@ async function runHarnessCommand(context) {
|
|
|
193996
194935
|
throw new CliInputError("Focused remote prompt analysis is not supported yet.", "Use local --analyst=claude|codex|cursor|local-scan, or drop --concern for a full remote report.");
|
|
193997
194936
|
}
|
|
193998
194937
|
if (context.flags["github-actions"] === "true") {
|
|
193999
|
-
const { runGithubActionsAnalyze } = await import("./harness-github-actions-
|
|
194938
|
+
const { runGithubActionsAnalyze } = await import("./harness-github-actions-tmy3gqwa.js");
|
|
194000
194939
|
const result = await runGithubActionsAnalyze(rootDir, {
|
|
194001
194940
|
writeReport: (report2) => {
|
|
194002
194941
|
const normalized = normalizeHarnessReport(report2);
|
|
@@ -194330,7 +195269,7 @@ async function runPromptConcernAnalysis(context, rootDir, scanPlan, tenant) {
|
|
|
194330
195269
|
const manifest = join10(rootDir, ".moda/prompts.yml");
|
|
194331
195270
|
let existing = [];
|
|
194332
195271
|
if (existsSync10(manifest)) {
|
|
194333
|
-
const document = $parseDocument(
|
|
195272
|
+
const document = $parseDocument(readFileSync16(manifest, "utf8"));
|
|
194334
195273
|
if (document.errors.length)
|
|
194335
195274
|
throw new CliInputError("Invalid prompt manifest.", document.errors[0].message);
|
|
194336
195275
|
existing = document.toJS({ maxAliasCount: 20 })?.sources ?? [];
|
|
@@ -194801,7 +195740,7 @@ function repairCitationLines(report, rootDir) {
|
|
|
194801
195740
|
continue;
|
|
194802
195741
|
let text;
|
|
194803
195742
|
try {
|
|
194804
|
-
text =
|
|
195743
|
+
text = readFileSync16(candidatePath, "utf8");
|
|
194805
195744
|
} catch {
|
|
194806
195745
|
continue;
|
|
194807
195746
|
}
|
|
@@ -196018,7 +196957,7 @@ function collectSnapshotInputs(rootDir, maxFiles, maxTextBytes) {
|
|
|
196018
196957
|
let text = "";
|
|
196019
196958
|
if (isTextFile(path)) {
|
|
196020
196959
|
try {
|
|
196021
|
-
text =
|
|
196960
|
+
text = readFileSync16(current, "utf8");
|
|
196022
196961
|
inventoryTextBytes += Buffer.byteLength(text, "utf8");
|
|
196023
196962
|
} catch {
|
|
196024
196963
|
return;
|
|
@@ -196258,7 +197197,7 @@ function readHarnessSyncState(rootDir) {
|
|
|
196258
197197
|
if (!existsSync10(path))
|
|
196259
197198
|
return;
|
|
196260
197199
|
try {
|
|
196261
|
-
const parsed = JSON.parse(
|
|
197200
|
+
const parsed = JSON.parse(readFileSync16(path, "utf8"));
|
|
196262
197201
|
if (!isRecord4(parsed) || parsed.schemaVersion !== "sync_state.v0.1") {
|
|
196263
197202
|
return;
|
|
196264
197203
|
}
|
|
@@ -196392,7 +197331,7 @@ function warnFresherSubdirHarnessReports(context, rootDir, explicitReport) {
|
|
|
196392
197331
|
writeHarnessNotice(context, `A fresher harness report exists at ${newest.path} (this directory has ${rootState}). If you meant that report, re-run with --path=${subdir}.`);
|
|
196393
197332
|
}
|
|
196394
197333
|
function readHarnessGraph(manifestPath) {
|
|
196395
|
-
return JSON.parse(
|
|
197334
|
+
return JSON.parse(readFileSync16(manifestPath, "utf8"));
|
|
196396
197335
|
}
|
|
196397
197336
|
function writeHarnessArtifacts(graph, rootDir, options = {}) {
|
|
196398
197337
|
const modaDir = join10(rootDir, MODA_DIR);
|
|
@@ -196631,7 +197570,7 @@ function inventoryFiles(rootDir, skipped, options = {}) {
|
|
|
196631
197570
|
recordSkipped(skipped, { path: rel2, reason: "scan text budget exceeded" });
|
|
196632
197571
|
} else {
|
|
196633
197572
|
try {
|
|
196634
|
-
item.text =
|
|
197573
|
+
item.text = readFileSync16(current, "utf8");
|
|
196635
197574
|
textBytes += Buffer.byteLength(item.text, "utf8");
|
|
196636
197575
|
} catch {
|
|
196637
197576
|
recordSkipped(skipped, { path: rel2, reason: "text read failed" });
|
|
@@ -196938,7 +197877,7 @@ function maybeAddPromptArtifact(graph, file) {
|
|
|
196938
197877
|
if (!isPrompt)
|
|
196939
197878
|
return;
|
|
196940
197879
|
const id = stableId2("prompt", file.path);
|
|
196941
|
-
const text = file.text ??
|
|
197880
|
+
const text = file.text ?? readFileSync16(file.absPath, "utf8");
|
|
196942
197881
|
upsertArtifact(graph, {
|
|
196943
197882
|
id,
|
|
196944
197883
|
type: "prompt",
|
|
@@ -197519,7 +198458,7 @@ function detectProviderPackagesInManifests(rootDir) {
|
|
|
197519
198458
|
const packageJsonPath = join10(rootDir, "package.json");
|
|
197520
198459
|
if (existsSync10(packageJsonPath)) {
|
|
197521
198460
|
try {
|
|
197522
|
-
const deps = packageDependencyNames(
|
|
198461
|
+
const deps = packageDependencyNames(readFileSync16(packageJsonPath, "utf8"));
|
|
197523
198462
|
for (const provider of PROVIDER_CATALOG) {
|
|
197524
198463
|
for (const name of provider.packageNames) {
|
|
197525
198464
|
if (deps.has(name))
|
|
@@ -197531,7 +198470,7 @@ function detectProviderPackagesInManifests(rootDir) {
|
|
|
197531
198470
|
const pyprojectPath = join10(rootDir, "pyproject.toml");
|
|
197532
198471
|
if (existsSync10(pyprojectPath)) {
|
|
197533
198472
|
try {
|
|
197534
|
-
const deps = pyprojectDependencyNames(
|
|
198473
|
+
const deps = pyprojectDependencyNames(readFileSync16(pyprojectPath, "utf8"));
|
|
197535
198474
|
for (const provider of PROVIDER_CATALOG) {
|
|
197536
198475
|
for (const name of provider.packageNames) {
|
|
197537
198476
|
if (deps.has(name.toLowerCase()))
|
|
@@ -197948,7 +198887,7 @@ function readSmallTextFileForHash(absPath, rootDir) {
|
|
|
197948
198887
|
if (!isTextFile(rel2))
|
|
197949
198888
|
return;
|
|
197950
198889
|
try {
|
|
197951
|
-
return
|
|
198890
|
+
return readFileSync16(absPath, "utf8");
|
|
197952
198891
|
} catch {
|
|
197953
198892
|
return;
|
|
197954
198893
|
}
|