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.
Files changed (2) hide show
  1. package/dist/bin.js +37 -3
  2. 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_+/.=-]{24,}\b/g);
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
- "\u65E0\u6CD5\u83B7\u53D6\u5DE5\u4F5C\u6D41\u6570\u636E\u5305\uFF1A\u65E0\u7F51\u7EDC\u4E14\u672C\u5730\u7F13\u5B58\u4E0D\u5B58\u5728\u3002\u8BF7\u5148\u5728\u6709\u7F51\u7EDC\u7684\u73AF\u5883\u8FD0\u884C hunter-harness\uFF0C\u6216\u8BBE\u7F6E HUNTER_HARNESS_RESOURCES_ROOT \u6307\u5411\u542B harness/ \u7684\u76EE\u5F55\u3002",
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
@@ -1,6 +1,6 @@
1
- {
1
+ {
2
2
  "name": "hunter-harness",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Local-first, server-governed agent harness",
5
5
  "license": "MIT",
6
6
  "type": "module",