@jinn-network/core 0.1.0-canary.a8ebdb2a → 0.1.1-canary.7b188db5

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.
@@ -66,6 +66,23 @@ export function syntheticFixtures() {
66
66
  profile: 'seed',
67
67
  mustSurvive: true,
68
68
  },
69
+ // Hazard: GIT_CONFIG tutorial blocks are env-shaped but not secret dumps (#2005).
70
+ {
71
+ id: 'hazard-git-config-tutorial-survive',
72
+ text: [
73
+ 'export GIT_CONFIG_GLOBAL=/dev/null',
74
+ 'export GIT_CONFIG_SYSTEM=/dev/null',
75
+ 'export GIT_CONFIG_NOSYSTEM=1',
76
+ 'export GIT_CONFIG_COUNT=2',
77
+ 'export GIT_CONFIG_KEY_0=credential.helper',
78
+ 'export GIT_CONFIG_VALUE_0=',
79
+ 'export GIT_CONFIG_KEY_1=core.askPass',
80
+ 'export GIT_CONFIG_VALUE_1=/attempt/askpass',
81
+ ].join('\n'),
82
+ labels: [],
83
+ profile: 'seed',
84
+ mustSurvive: true,
85
+ },
69
86
  // Hazard: loopback IP must survive (illustrative config knowledge).
70
87
  {
71
88
  id: 'hazard-loopback-ip-survive',
@@ -25,6 +25,9 @@ const KEY_CONTEXT = /\b(?:private[_\s-]?key|privkey|secret[_\s-]?key|wallet[_\s-
25
25
  const HEX64 = /\b(?:0x)?([a-fA-F0-9]{64})\b/g;
26
26
  /** ENV-style assignment line. */
27
27
  const ENV_LINE = /^[A-Z][A-Z0-9_]*=.*$/;
28
+ const ENV_KEY = /^([A-Z][A-Z0-9_]*)=/;
29
+ /** Git's GIT_CONFIG_* override tutorial shape — not a secret dump (#2005). */
30
+ const GIT_CONFIG_ENV_KEY = /^GIT_CONFIG(?:_|$)/i;
28
31
  const MIN_ENV_RUN = 3;
29
32
  export function rejectClassesDetector(policy) {
30
33
  const meta = { name: 'reject-classes', version: VERSION };
@@ -156,7 +159,7 @@ function scanEnvBlocks(text, key, detector) {
156
159
  const trimmed = line.trim();
157
160
  // Allow optional leading export / whitespace.
158
161
  const candidate = trimmed.replace(/^export\s+/, '');
159
- if (ENV_LINE.test(candidate)) {
162
+ if (isEnvBlockAssignment(candidate)) {
160
163
  if (runStart < 0) {
161
164
  runStart = i;
162
165
  runStartOffset = offset + (line.length - line.trimStart().length);
@@ -164,9 +167,9 @@ function scanEnvBlocks(text, key, detector) {
164
167
  runCount += 1;
165
168
  runEndOffset = offset + line.length;
166
169
  }
167
- else if (trimmed === '' && runCount > 0) {
168
- // Blank line inside a dump still counts as continuing the block visually,
169
- // but does not increment — only flush on a non-env non-blank line.
170
+ else if ((trimmed === '' || isGitConfigEnvAssignment(candidate)) && runCount > 0) {
171
+ // Blank and GIT_CONFIG tutorial lines inside a dump keep the run open,
172
+ // but do not increment it — only flush on another non-env line.
170
173
  }
171
174
  else {
172
175
  flush();
@@ -176,3 +179,17 @@ function scanEnvBlocks(text, key, detector) {
176
179
  flush();
177
180
  return findings;
178
181
  }
182
+ function isEnvBlockAssignment(candidate) {
183
+ if (!ENV_LINE.test(candidate))
184
+ return false;
185
+ const keyMatch = ENV_KEY.exec(candidate);
186
+ if (!keyMatch)
187
+ return false;
188
+ return !GIT_CONFIG_ENV_KEY.test(keyMatch[1]);
189
+ }
190
+ function isGitConfigEnvAssignment(candidate) {
191
+ if (!ENV_LINE.test(candidate))
192
+ return false;
193
+ const keyMatch = ENV_KEY.exec(candidate);
194
+ return keyMatch !== null && GIT_CONFIG_ENV_KEY.test(keyMatch[1]);
195
+ }
@@ -11,7 +11,14 @@ export declare class RejectPublishError extends Error {
11
11
  readonly findings: Finding[];
12
12
  constructor(scrubClass: ScrubClass, findings?: Finding[]);
13
13
  }
14
- /** Findings whose policy disposition is reject-publish. */
14
+ /**
15
+ * Findings whose policy disposition is reject-publish.
16
+ *
17
+ * A5 `drop-key` findings are structural removals, not catastrophic content:
18
+ * the key-policy detector has already removed the entire attribute before
19
+ * this guard runs. Only content-level A5 findings (such as an env-block
20
+ * embedded in tool output) must abort the publish.
21
+ */
15
22
  export declare function rejectPublishFindings(findings: Finding[] | undefined, policy?: PolicyTable): Finding[];
16
23
  /**
17
24
  * Throw a class-named {@link RejectPublishError} when reject-publish fired.
@@ -17,11 +17,19 @@ export class RejectPublishError extends Error {
17
17
  this.findings = findings;
18
18
  }
19
19
  }
20
- /** Findings whose policy disposition is reject-publish. */
20
+ /**
21
+ * Findings whose policy disposition is reject-publish.
22
+ *
23
+ * A5 `drop-key` findings are structural removals, not catastrophic content:
24
+ * the key-policy detector has already removed the entire attribute before
25
+ * this guard runs. Only content-level A5 findings (such as an env-block
26
+ * embedded in tool output) must abort the publish.
27
+ */
21
28
  export function rejectPublishFindings(findings, policy = DEFAULT_POLICY) {
22
29
  if (!findings?.length)
23
30
  return [];
24
- return findings.filter((f) => resolveDisposition(f.class, f.confidence, policy) === 'reject-publish');
31
+ return findings.filter((f) => !f.evidence.includes('drop-key') &&
32
+ resolveDisposition(f.class, f.confidence, policy) === 'reject-publish');
25
33
  }
26
34
  /**
27
35
  * Throw a class-named {@link RejectPublishError} when reject-publish fired.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jinn-network/core",
3
- "version": "0.1.0-canary.a8ebdb2a",
3
+ "version": "0.1.1-canary.7b188db5",
4
4
  "description": "Domain core for Jinn — evidence/contribution stores, scrub, trajectory parsing, and corpus reads. Independent of client/src.",
5
5
  "type": "module",
6
6
  "packageManager": "yarn@4.13.0",
@@ -43,7 +43,7 @@
43
43
  },
44
44
  "dependencies": {
45
45
  "@huggingface/transformers": "^4.2.0",
46
- "@jinn-network/plugin": "0.1.0-canary.a8ebdb2a",
46
+ "@jinn-network/plugin": "0.1.1-canary.7b188db5",
47
47
  "@lmoe/gliner-onnx": "0.1.0",
48
48
  "@noble/hashes": "^2.2.0",
49
49
  "@secretlint/core": "^13.0.2",