hunter-harness 0.2.1 → 0.2.3
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/bin.js +37 -3
- package/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -2993,13 +2993,27 @@ function shannonEntropy(value) {
|
|
|
2993
2993
|
}
|
|
2994
2994
|
return entropy;
|
|
2995
2995
|
}
|
|
2996
|
+
var HEX_DIGEST = /^(?:[a-fA-F0-9]{32}|[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/;
|
|
2997
|
+
var STRUCTURED_LOWERCASE_ID = /^[a-z0-9]+(?:[.-][a-z0-9]+)+$/;
|
|
2998
|
+
function isBenignHighEntropyLookalike(value) {
|
|
2999
|
+
if (HEX_DIGEST.test(value)) {
|
|
3000
|
+
return true;
|
|
3001
|
+
}
|
|
3002
|
+
if (value.includes("/")) {
|
|
3003
|
+
return true;
|
|
3004
|
+
}
|
|
3005
|
+
if (STRUCTURED_LOWERCASE_ID.test(value) && (value.match(/\./g) ?? []).length >= 2) {
|
|
3006
|
+
return true;
|
|
3007
|
+
}
|
|
3008
|
+
return false;
|
|
3009
|
+
}
|
|
2996
3010
|
function highEntropyCandidates(content) {
|
|
2997
|
-
const matches = content.matchAll(/\b[A-Za-z0-9_
|
|
3011
|
+
const matches = content.matchAll(/\b[A-Za-z0-9_+.=\-]{24,}\b/g);
|
|
2998
3012
|
return [...matches].map((match) => ({
|
|
2999
3013
|
value: match[0],
|
|
3000
3014
|
offset: match.index,
|
|
3001
3015
|
entropy: shannonEntropy(match[0])
|
|
3002
|
-
})).filter((item2) => item2.entropy >= 4.5);
|
|
3016
|
+
})).filter((item2) => item2.entropy >= 4.5 && !isBenignHighEntropyLookalike(item2.value));
|
|
3003
3017
|
}
|
|
3004
3018
|
|
|
3005
3019
|
// ../core/dist/security/scanner.js
|
|
@@ -3084,7 +3098,11 @@ function scanSensitiveFiles(files, options = {}) {
|
|
|
3084
3098
|
for (const [inputPath, content] of Object.entries(files).sort(([a], [b]) => a.localeCompare(b))) {
|
|
3085
3099
|
const path = normalizeManagedPath(inputPath);
|
|
3086
3100
|
const ignores = parseInlineIgnores(content);
|
|
3101
|
+
const knowledgeMetadata = path === ".harness/knowledge" || path.startsWith(".harness/knowledge/");
|
|
3087
3102
|
for (const raw of rawFindings(content)) {
|
|
3103
|
+
if (knowledgeMetadata && raw.ruleId === "HH_WINDOWS_ABSOLUTE_PATH") {
|
|
3104
|
+
continue;
|
|
3105
|
+
}
|
|
3088
3106
|
const position = location(content, raw.offset);
|
|
3089
3107
|
const fingerprint = sha256Bytes([
|
|
3090
3108
|
SENSITIVE_SCANNER_VERSION,
|
|
@@ -5132,11 +5150,27 @@ async function resolveWorkflowResourcesRoot(options, argv = []) {
|
|
|
5132
5150
|
} catch (error) {
|
|
5133
5151
|
if (error instanceof WorkflowDataResolutionError) throw error;
|
|
5134
5152
|
throw new WorkflowDataResolutionError(
|
|
5135
|
-
|
|
5153
|
+
describeWorkflowDataFetchFailure(error, packageSpec),
|
|
5136
5154
|
"WORKFLOW_DATA_UNAVAILABLE"
|
|
5137
5155
|
);
|
|
5138
5156
|
}
|
|
5139
5157
|
}
|
|
5158
|
+
function describeWorkflowDataFetchFailure(error, packageSpec) {
|
|
5159
|
+
const detailRaw = error instanceof Error ? error.message : String(error);
|
|
5160
|
+
const detail = detailRaw.length > 240 ? detailRaw.slice(0, 240) + "\u2026" : detailRaw;
|
|
5161
|
+
const code = error !== null && typeof error === "object" && "code" in error ? String(error.code) : "";
|
|
5162
|
+
const hintRoot = "\u8BBE\u7F6E HUNTER_HARNESS_RESOURCES_ROOT \u6307\u5411\u542B harness/ \u7684\u76EE\u5F55";
|
|
5163
|
+
if (code === "ERR_MODULE_NOT_FOUND" || /Cannot find package ['"]pacote['"]/i.test(detailRaw)) {
|
|
5164
|
+
return `\u65E0\u6CD5\u83B7\u53D6\u5DE5\u4F5C\u6D41\u6570\u636E\u5305 ${packageSpec}\uFF1A\u7F3A\u5C11\u53EF\u9009\u4F9D\u8D56 pacote\uFF08npx/npm \u5B89\u88C5 CLI \u65F6\u672A\u88C5\u4E0A\uFF09\u3002\u8BF7\u91CD\u88C5 hunter-harness\uFF0C\u6216${hintRoot}\u3002\u539F\u56E0\uFF1A${detail}`;
|
|
5165
|
+
}
|
|
5166
|
+
if (code === "ECONNRESET" || code === "ETIMEDOUT" || code === "ENOTFOUND" || code === "EAI_AGAIN" || code === "ECONNREFUSED" || /ECONNRESET|ETIMEDOUT|socket disconnected|TLS connection/i.test(detailRaw)) {
|
|
5167
|
+
return `\u65E0\u6CD5\u83B7\u53D6\u5DE5\u4F5C\u6D41\u6570\u636E\u5305 ${packageSpec}\uFF1A\u4ECE npm \u4E0B\u8F7D\u5931\u8D25\uFF08\u7F51\u7EDC/TLS\uFF09\u3002\u53EF\u5148\u8BBE\u7F6E NODE_OPTIONS=--dns-result-order=ipv4first \u540E\u91CD\u8BD5\uFF0C\u6216${hintRoot}\u3002\u539F\u56E0\uFF1A${code !== "" ? code + " " : ""}${detail}`;
|
|
5168
|
+
}
|
|
5169
|
+
if (code === "E404" || /\b404\b|Not Found/i.test(detailRaw)) {
|
|
5170
|
+
return `\u65E0\u6CD5\u83B7\u53D6\u5DE5\u4F5C\u6D41\u6570\u636E\u5305 ${packageSpec}\uFF1Anpm \u4E0A\u627E\u4E0D\u5230\u8BE5\u5305\u6216\u65E0\u6743\u8BBF\u95EE\u3002\u8BF7\u786E\u8BA4\u5DF2\u53D1\u5E03\u5BF9\u5E94 scope \u7684 workflow \u6570\u636E\u5305\uFF0C\u6216${hintRoot}\u3002\u539F\u56E0\uFF1A${detail}`;
|
|
5171
|
+
}
|
|
5172
|
+
return `\u65E0\u6CD5\u83B7\u53D6\u5DE5\u4F5C\u6D41\u6570\u636E\u5305 ${packageSpec}\uFF1A\u672C\u5730\u7F13\u5B58\u4E0D\u5B58\u5728\u4E14\u83B7\u53D6\u5931\u8D25\u3002\u53EF${hintRoot}\u3002\u539F\u56E0\uFF1A${code !== "" ? code + " " : ""}${detail}`;
|
|
5173
|
+
}
|
|
5140
5174
|
async function readWorkflowFamilyManifest(resourcesRoot) {
|
|
5141
5175
|
const manifestPath = join16(resourcesRoot, "hunter-workflow-family.json");
|
|
5142
5176
|
if (!await pathExists3(manifestPath)) return {};
|
package/package.json
CHANGED