@7nsane/zift 2.2.0 → 3.0.0

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/README.md CHANGED
@@ -1,103 +1,52 @@
1
- # 🛡️ Zift (v2.0.0)
1
+ # 🛡️ Zift (v3.0.0)
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@7nsane/zift.svg?style=flat-square)](https://www.npmjs.com/package/@7nsane/zift)
4
4
  [![License](https://img.shields.io/npm/l/@7nsane/zift.svg?style=flat-square)](https://www.npmjs.com/package/@7nsane/zift)
5
5
  [![Build Status](https://img.shields.io/badge/CI-passing-brightgreen?style=flat-square)](https://github.com/7nsane/zift)
6
6
 
7
- **The Deterministic Pre-install Security Gate for JavaScript Projects.** By using deterministic AST analysis and lightweight variable propagation, Zift identifies potential credential exfiltration, malicious persistence, and obfuscated execution with extreme precision.
7
+ **The Intelligent Ecosystem Security Engine for JavaScript.**
8
8
 
9
- ## Installation
9
+ Zift v3.0 is a massive leap forward, moving beyond static analysis into **Cross-File Intelligence** and **Runtime Protection**. It is designed to identify and stop advanced supply-chain attacks (credential exfiltration, reverse-shell droppers) before they hit your production environment.
10
10
 
11
- ```bash
12
- # Install globally to use the 'zift' command anywhere
13
- npm install -g @7nsane/zift
14
- ```
11
+ ## 🚀 Major Features (v3.0.0)
15
12
 
16
- ## 🛡️ Secure Your Workflow (Recommended)
13
+ - **🌍 Cross-File Taint Tracking**: Tracks sensitive data (e.g., `process.env.TOKEN`) across `import/export` and `require` boundaries.
14
+ - **🧠 VM-Based De-obfuscation**: Safe, sandboxed evaluation of string manipulation logic (e.g., character arrays, reverse/join) to reveal hidden malicious signals.
15
+ - **🛡️ Zift Shield (Runtime Guard)**: A real-time audit layer for network and shell activity. Run `zift protect` to monitor your app's dependencies in real-world conditions.
16
+ - **🔒 Lockfile Security**: Automatic auditing of `package-lock.json` and `yarn.lock` for registry confusion.
17
17
 
18
- Set up the **Secure npm Wrapper** to audit packages automatically every time you install something.
18
+ ## 📦 Quick Start
19
19
 
20
20
  ```bash
21
- # 1. Run the setup
22
- zift setup
23
-
24
- # 2. Reload your terminal (or run the command provided by setup)
25
-
26
- # 3. Use the --zift flag with your normal npm commands
27
- npm install <package-name> --zift
28
- ```
29
-
30
- ## 🔍 Limitations & Blind Spots (v2.0.0)
31
-
32
- To maintain a zero-false-positive baseline and high performance, Zift v2 focus on **deterministic behavioral patterns**. It does NOT currently cover:
33
-
34
- - **Cross-file Taint**: Taint tracking is limited to intra-file propagation.
35
- - **Runtime Decryption**: Logic that decrypts and executes memory-only payloads at runtime.
36
- - **VM-based Execution**: Malicious payloads executed inside isolated virtual machine environments.
37
- - **Multi-stage Loaders**: Sophisticated multi-hop obfuscation that reconstructs logic over several cycles.
38
- - **Post-install Generation**: Malicious code generated or downloaded *after* the initial install/preinstall phase.
39
-
40
- **Positioning**: Zift is a *Deterministic Pre-install Behavioral Security Gate*. It is designed to catch the most common and damaging malware patterns instantly, not to serve as a complete, multi-layer supply-chain defense.
41
-
42
- ## License
43
- MIT
44
- ## Usage
45
-
46
- ### 🚀 Secure Installer Mode
47
- Use Zift as a security gate. It will pre-audit the package source into a sandbox, show you the risk score, and ask for permission before the official installation begins.
48
-
49
- ```bash
50
- # With the --zift alias (Recommended)
51
- npm install axios --zift
52
-
53
- # Directly using Zift
54
- zift install gsap
55
- ```
21
+ # 1. Install Zift
22
+ npm install -g @7nsane/zift
56
23
 
57
- ### 🔍 Advanced Scanning
58
- Scan local directories or existing dependencies in your `node_modules`.
24
+ # 2. Setup Secure Wrappers (adds --zift flag to npm/bun/pnpm)
25
+ zift setup
59
26
 
60
- ```bash
61
- # Scan current directory
27
+ # 3. Audit a local project
62
28
  zift .
63
29
 
64
- # Scan a specific folder or dependency
65
- zift ./node_modules/example-pkg
66
-
67
- # CI/CD Mode (JSON output + Non-zero exit on high risk)
68
- zift . --format json
30
+ # 4. Run your application with Active Shield
31
+ zift protect index.js
69
32
  ```
70
33
 
71
- ## Rule Transparency
72
-
73
- Zift uses a multi-phase engine:
74
- 1. **Collection**: Single-pass AST traversal to gather facts (sources, sinks, flows).
75
- 2. **Evaluation**: Deterministic rule matching against collected facts.
76
-
77
- ### Rule IDs:
78
- - **ZFT-001 (ENV_EXFILTRATION)**: Detection of environment variables being read and sent over the network.
79
- - **ZFT-002 (SENSITIVE_FILE_EXFILTRATION)**: Detection of sensitive files (e.g., `.ssh`, `.env`) being read and sent over the network.
80
- - **ZFT-003 (PERSISTENCE_ATTEMPT)**: Detection of attempts to write to startup directories.
81
- - **ZFT-004 (OBFUSCATED_EXECUTION)**: Detection of high-entropy strings executed via dynamic constructors.
82
-
83
- ## Key Features
84
- - **Deterministic AST Analysis**: O(n) complexity, single-pass scanner.
85
- - **Zero False Positives**: Verified against React, Express, and ESLint (0.0% FP rate).
86
- - **Lifecycle Awareness**: Identifies if suspicious code is slated to run during `postinstall`.
87
- - **Credential Protection**: Detects exfiltration of `process.env` (AWS, SSH keys, etc.) over network sinks.
88
-
89
- ## Limitations
34
+ ## 🔍 How It Works
90
35
 
91
- Transparency is key to trust. As a V1 static analysis tool, Zift has the following scope boundaries:
36
+ Zift uses a **Deterministic AST Analysis** engine. Unlike regex-based scanners, Zift understands the structure of your code. It tracks the flow of data from sensitive **Sources** (like `process.env`) to dangerous **Sinks** (like `fetch` or `child_process.exec`).
92
37
 
93
- - **No Interprocedural Flow**: Variable tracking is restricted to function scope; it does not track data across function boundaries.
94
- - **No Cross-File Propagation**: Analysis is performed on a per-file basis.
95
- - **No Dynamic Runtime Analysis**: Zift does not execute code; it cannot detect evasion techniques that only trigger during execution.
38
+ - **Collection**: Single-pass O(n) traversal.
39
+ - **Evaluation**: Priority-based rule matching.
40
+ - **Intelligence**: Cross-file propagation and VM-based reveal.
96
41
 
97
- ## Performance Guarantees
42
+ ## 🛠️ Commands
98
43
 
99
- - **File Cap**: Files larger than **512KB** are skipped to ensure predictable scan times.
100
- - **String Cap**: Entropy calculation is skipped for literal strings longer than **2048 characters**.
44
+ | Command | Description |
45
+ | --- | --- |
46
+ | `zift .` | Deep scan of the current directory |
47
+ | `zift install <pkg>` | Pre-audit and install a package securely |
48
+ | `zift protect <app>` | Launch application with **Zift Shield** runtime auditing |
49
+ | `zift setup` | Configure shell aliases for secure package management |
101
50
 
102
51
  ---
103
- **Build with confidence. Scan with Zift.** 🛡️
52
+ **Build with confidence. Secure with Zift.** 🛡️
package/bin/zift.js CHANGED
@@ -23,6 +23,10 @@ async function main() {
23
23
  runInit();
24
24
  return;
25
25
  }
26
+ if (args[0] === 'protect') {
27
+ runShield(args.slice(1));
28
+ return;
29
+ }
26
30
 
27
31
  // 2. Detection for bun/pnpm usage
28
32
  if (args.includes('--bun')) installer = 'bun';
@@ -238,10 +242,11 @@ function runInit() {
238
242
  }
239
243
 
240
244
  function showHelp() {
241
- console.log(chalk.blue.bold('\n🛡️ Zift v2.0.0 - Intelligent Pre-install Security Gate\n'));
245
+ console.log(chalk.blue.bold('\n🛡️ Zift v3.0.0 - Intelligent Ecosystem Security\n'));
242
246
  console.log('Usage:');
243
247
  console.log(' zift setup Secure npm, bun, and pnpm');
244
248
  console.log(' zift init Initialize configuration');
249
+ console.log(' zift protect <app> Run application with Zift Shield');
245
250
  console.log(' zift install <pkg> Scan and install package');
246
251
  console.log(' zift . Scan current directory');
247
252
  console.log('\nOptions:');
@@ -272,4 +277,18 @@ function printSummary(findings) {
272
277
  console.log(chalk.red(` Critical: ${s.Critical}\n High: ${s.High}`));
273
278
  }
274
279
 
280
+ function runShield(appArgs) {
281
+ if (appArgs.length === 0) {
282
+ console.error(chalk.red('❌ Error: Specify an application to protect (e.g., zift protect main.js)'));
283
+ process.exit(1);
284
+ }
285
+
286
+ const shieldPath = path.join(__dirname, '../src/shield.js');
287
+ const nodeArgs = ['-r', shieldPath, ...appArgs];
288
+
289
+ console.log(chalk.blue(`\n🛡️ Launching with Zift Shield...`));
290
+ const child = cp.spawn('node', nodeArgs, { stdio: 'inherit' });
291
+ child.on('exit', (code) => process.exit(code));
292
+ }
293
+
275
294
  main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7nsane/zift",
3
- "version": "2.2.0",
3
+ "version": "3.0.0",
4
4
  "description": "A high-performance, deterministic security scanner for npm packages.",
5
5
  "main": "src/scanner.js",
6
6
  "bin": {
package/src/collector.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const acorn = require('acorn');
2
2
  const walk = require('acorn-walk');
3
+ const vm = require('node:vm');
3
4
  const { calculateEntropy } = require('./utils/entropy');
4
5
 
5
6
  class ASTCollector {
@@ -24,7 +25,9 @@ class ASTCollector {
24
25
  SHELL_EXECUTION: [],
25
26
  ENCODER_USE: [],
26
27
  REMOTE_FETCH_SIGNAL: [],
27
- PIPE_TO_SHELL_SIGNAL: []
28
+ PIPE_TO_SHELL_SIGNAL: [],
29
+ EXPORTS: [],
30
+ IMPORTS: []
28
31
  };
29
32
  const flows = [];
30
33
  const sourceCode = code;
@@ -55,6 +58,57 @@ class ASTCollector {
55
58
  }
56
59
  }
57
60
  },
61
+ ImportDeclaration: (node) => {
62
+ const source = node.source.value;
63
+ node.specifiers.forEach(spec => {
64
+ facts.IMPORTS.push({
65
+ file: filePath,
66
+ line: node.loc.start.line,
67
+ source,
68
+ local: spec.local.name,
69
+ imported: spec.type === 'ImportDefaultSpecifier' ? 'default' : (spec.imported ? spec.imported.name : null)
70
+ });
71
+ });
72
+ },
73
+ ExportNamedDeclaration: (node) => {
74
+ if (node.declaration) {
75
+ if (node.declaration.type === 'VariableDeclaration') {
76
+ node.declaration.declarations.forEach(decl => {
77
+ facts.EXPORTS.push({
78
+ file: filePath,
79
+ line: node.loc.start.line,
80
+ name: decl.id.name,
81
+ type: 'named'
82
+ });
83
+ });
84
+ } else if (node.declaration.id) {
85
+ facts.EXPORTS.push({
86
+ file: filePath,
87
+ line: node.loc.start.line,
88
+ name: node.declaration.id.name,
89
+ type: 'named'
90
+ });
91
+ }
92
+ }
93
+ node.specifiers.forEach(spec => {
94
+ facts.EXPORTS.push({
95
+ file: filePath,
96
+ line: node.loc.start.line,
97
+ name: spec.exported.name,
98
+ local: spec.local.name,
99
+ type: 'named'
100
+ });
101
+ });
102
+ },
103
+ ExportDefaultDeclaration: (node) => {
104
+ facts.EXPORTS.push({
105
+ file: filePath,
106
+ line: node.loc.start.line,
107
+ name: 'default',
108
+ local: (node.declaration.id ? node.declaration.id.name : (node.declaration.name || null)),
109
+ type: 'default'
110
+ });
111
+ },
58
112
  CallExpression: (node, state, ancestors) => {
59
113
  const calleeCode = sourceCode.substring(node.callee.start, node.callee.end);
60
114
 
@@ -66,12 +120,38 @@ class ASTCollector {
66
120
  });
67
121
  }
68
122
 
69
- if (calleeCode === 'require' && node.arguments.length > 0 && node.arguments[0].type !== 'Literal') {
70
- facts.DYNAMIC_REQUIRE.push({
71
- file: filePath,
72
- line: node.loc.start.line,
73
- variable: sourceCode.substring(node.arguments[0].start, node.arguments[0].end)
74
- });
123
+ if (calleeCode === 'require' && node.arguments.length > 0) {
124
+ if (node.arguments[0].type !== 'Literal') {
125
+ facts.DYNAMIC_REQUIRE.push({
126
+ file: filePath,
127
+ line: node.loc.start.line,
128
+ variable: sourceCode.substring(node.arguments[0].start, node.arguments[0].end)
129
+ });
130
+ } else {
131
+ const source = node.arguments[0].value;
132
+ const parent = ancestors[ancestors.length - 2];
133
+ if (parent && parent.type === 'VariableDeclarator' && parent.id.type === 'Identifier') {
134
+ facts.IMPORTS.push({
135
+ file: filePath, line: node.loc.start.line, source, local: parent.id.name, imported: 'default'
136
+ });
137
+ }
138
+ }
139
+ }
140
+
141
+ // De-obfuscation Trigger
142
+ const evaluated = this.tryEvaluate(node, sourceCode);
143
+ if (evaluated) {
144
+ if (this.getNetworkType(evaluated) || this.isShellSink(evaluated) || evaluated === 'eval' || evaluated === 'Function') {
145
+ facts.OBFUSCATION.push({
146
+ file: filePath,
147
+ line: node.loc.start.line,
148
+ reason: `De-obfuscated to: ${evaluated}`,
149
+ revealed: evaluated
150
+ });
151
+ if (evaluated === 'eval' || evaluated === 'Function') {
152
+ facts.DYNAMIC_EXECUTION.push({ file: filePath, line: node.loc.start.line, type: evaluated });
153
+ }
154
+ }
75
155
  }
76
156
 
77
157
  const netType = this.getNetworkType(calleeCode);
@@ -90,7 +170,6 @@ class ASTCollector {
90
170
  callee: calleeCode
91
171
  });
92
172
 
93
- // Signal Analysis: Dropper Patterns
94
173
  node.arguments.forEach(arg => {
95
174
  if (arg.type === 'Literal' && typeof arg.value === 'string') {
96
175
  const val = arg.value.toLowerCase();
@@ -180,6 +259,17 @@ class ASTCollector {
180
259
  }
181
260
  },
182
261
  AssignmentExpression: (node) => {
262
+ const leftCode = sourceCode.substring(node.left.start, node.left.end);
263
+ if (leftCode === 'module.exports' || leftCode.startsWith('exports.')) {
264
+ facts.EXPORTS.push({
265
+ file: filePath,
266
+ line: node.loc.start.line,
267
+ name: leftCode === 'module.exports' ? 'default' : leftCode.replace('exports.', ''),
268
+ local: (node.right.type === 'Identifier' ? node.right.name : null),
269
+ type: leftCode === 'module.exports' ? 'default' : 'named'
270
+ });
271
+ }
272
+
183
273
  if (node.left.type === 'MemberExpression' && node.right.type === 'Identifier') {
184
274
  const from = sourceCode.substring(node.right.start, node.right.end);
185
275
  const to = sourceCode.substring(node.left.start, node.left.end);
@@ -216,6 +306,7 @@ class ASTCollector {
216
306
  }
217
307
 
218
308
  getNetworkType(calleeCode) {
309
+ if (typeof calleeCode !== 'string') return null;
219
310
  const dnsSinks = ['dns.lookup', 'dns.resolve', 'dns.resolve4', 'dns.resolve6'];
220
311
  const rawSocketSinks = ['net.connect', 'net.createConnection'];
221
312
  const networkSinks = ['http.request', 'https.request', 'http.get', 'https.get', 'fetch', 'axios', 'request'];
@@ -233,6 +324,7 @@ class ASTCollector {
233
324
  }
234
325
 
235
326
  isShellSink(calleeCode) {
327
+ if (typeof calleeCode !== 'string') return false;
236
328
  const shellSinks = ['child_process.exec', 'child_process.spawn', 'child_process.execSync', 'exec', 'spawn', 'execSync'];
237
329
  return shellSinks.some(sink => {
238
330
  if (calleeCode === sink) return true;
@@ -243,6 +335,7 @@ class ASTCollector {
243
335
  }
244
336
 
245
337
  isEncoder(calleeCode) {
338
+ if (typeof calleeCode !== 'string') return false;
246
339
  const encoders = ['Buffer.from', 'btoa', 'atob', 'zlib.deflate', 'zlib.gzip', 'crypto.createCipheriv'];
247
340
  return encoders.some(enc => calleeCode === enc || calleeCode.endsWith('.' + enc));
248
341
  }
@@ -263,6 +356,7 @@ class ASTCollector {
263
356
  }
264
357
 
265
358
  isSensitiveFileRead(calleeCode, node, sourceCode) {
359
+ if (typeof calleeCode !== 'string') return false;
266
360
  if (!calleeCode.includes('fs.readFile') && !calleeCode.includes('fs.readFileSync') &&
267
361
  !calleeCode.includes('fs.promises.readFile')) return false;
268
362
 
@@ -275,6 +369,7 @@ class ASTCollector {
275
369
  }
276
370
 
277
371
  isStartupFileWrite(calleeCode, node, sourceCode) {
372
+ if (typeof calleeCode !== 'string') return false;
278
373
  if (!calleeCode.includes('fs.writeFile') && !calleeCode.includes('fs.writeFileSync') &&
279
374
  !calleeCode.includes('fs.appendFile')) return false;
280
375
 
@@ -286,8 +381,19 @@ class ASTCollector {
286
381
  return false;
287
382
  }
288
383
 
289
- getSourceCode(node) {
290
- return this.sourceCode.substring(node.start, node.end);
384
+ tryEvaluate(node, sourceCode) {
385
+ try {
386
+ const code = sourceCode.substring(node.start, node.end);
387
+ if (code.includes('process') || code.includes('require') || code.includes('fs') || code.includes('child_process')) return null;
388
+ if (!code.includes('[') && !code.includes('+') && !code.includes('join') && !code.includes('reverse')) return null;
389
+
390
+ const script = new vm.Script(code);
391
+ const context = vm.createContext({});
392
+ const result = script.runInContext(context, { timeout: 50 });
393
+ return typeof result === 'string' ? result : null;
394
+ } catch (e) {
395
+ return null;
396
+ }
291
397
  }
292
398
  }
293
399
 
package/src/scanner.js CHANGED
@@ -24,6 +24,7 @@ class PackageScanner {
24
24
  try { fs.mkdirSync(cacheDir, { recursive: true }); } catch (e) { }
25
25
  }
26
26
 
27
+ // Initialize fact storage
27
28
  let allFacts = {
28
29
  facts: {
29
30
  ENV_READ: [],
@@ -40,14 +41,16 @@ class PackageScanner {
40
41
  ENCODER_USE: [],
41
42
  REMOTE_FETCH_SIGNAL: [],
42
43
  PIPE_TO_SHELL_SIGNAL: [],
43
- LIFECYCLE_CONTEXT: []
44
+ LIFECYCLE_CONTEXT: [],
45
+ EXPORTS: [],
46
+ IMPORTS: []
44
47
  },
45
48
  flows: []
46
49
  };
47
50
 
48
51
  const pkgVersion = require('../package.json').version;
49
52
 
50
- // Parallel processing with limited concurrency (8 files at a time)
53
+ // Pass 1: Collection
51
54
  const concurrency = 8;
52
55
  for (let i = 0; i < files.length; i += concurrency) {
53
56
  const chunk = files.slice(i, i + concurrency);
@@ -62,47 +65,84 @@ class PackageScanner {
62
65
  let facts = {}, flows = [];
63
66
 
64
67
  if (fs.existsSync(cachePath)) {
65
- // Cache hit: Load metadata
66
68
  try {
67
69
  const cached = JSON.parse(fs.readFileSync(cachePath, 'utf8'));
68
70
  facts = cached.facts || {};
69
71
  flows = cached.flows || [];
70
72
  } catch (e) {
71
- // Corrupt cache: re-scan
72
73
  const result = this.collector.collect(code, file);
73
74
  facts = result.facts;
74
75
  flows = result.flows;
75
76
  }
76
77
  } else {
77
- // Cache miss: Scan and save
78
78
  const result = this.collector.collect(code, file);
79
79
  facts = result.facts;
80
80
  flows = result.flows;
81
-
82
- try {
83
- fs.writeFileSync(cachePath, JSON.stringify({ facts, flows }));
84
- } catch (e) { }
81
+ try { fs.writeFileSync(cachePath, JSON.stringify({ facts, flows })); } catch (e) { }
85
82
  }
86
83
 
87
- // Merge facts (Synchronized)
88
84
  if (lifecycleFiles.has(file)) {
89
85
  facts.LIFECYCLE_CONTEXT = facts.LIFECYCLE_CONTEXT || [];
90
86
  facts.LIFECYCLE_CONTEXT.push({ file, reason: 'Lifecycle script context detected' });
91
87
  }
92
88
 
93
89
  for (const category in facts) {
94
- if (allFacts.facts[category]) {
95
- allFacts.facts[category].push(...facts[category]);
96
- }
90
+ if (allFacts.facts[category]) allFacts.facts[category].push(...facts[category]);
97
91
  }
98
92
  allFacts.flows.push(...flows);
99
93
  }));
100
94
  }
101
95
 
96
+ // Pass 2: Cross-File Taint Resolution
97
+ this.resolveCrossFileTaint(allFacts);
98
+
102
99
  const findings = this.engine.evaluate(allFacts, lifecycleFiles);
103
100
  return this.formatFindings(findings);
104
101
  }
105
102
 
103
+ resolveCrossFileTaint(allFacts) {
104
+ const { facts, flows } = allFacts;
105
+ const exportMap = new Map(); // file -> exportName -> localName/isTainted
106
+
107
+ // 1. Build Export Map
108
+ facts.EXPORTS.forEach(exp => {
109
+ if (!exportMap.has(exp.file)) exportMap.set(exp.file, new Map());
110
+
111
+ // Check if localName is tainted in this file
112
+ const isLocalTainted = flows.some(f => f.file === exp.file && f.toVar === exp.local && f.fromVar.includes('process.env'));
113
+ const isNamedTainted = flows.some(f => f.file === exp.file && f.toVar === exp.name && f.fromVar.includes('process.env'));
114
+
115
+ exportMap.get(exp.file).set(exp.name, {
116
+ local: exp.local,
117
+ isTainted: isLocalTainted || isNamedTainted
118
+ });
119
+ });
120
+
121
+ // 2. Propagate to Imports
122
+ facts.IMPORTS.forEach(imp => {
123
+ let resolvedPath;
124
+ if (imp.source.startsWith('.')) {
125
+ resolvedPath = path.resolve(path.dirname(imp.file), imp.source);
126
+ if (!resolvedPath.endsWith('.js')) resolvedPath += '.js';
127
+ }
128
+
129
+ if (resolvedPath && exportMap.has(resolvedPath)) {
130
+ const targetExports = exportMap.get(resolvedPath);
131
+ const matchedExport = targetExports.get(imp.imported);
132
+
133
+ if (matchedExport && matchedExport.isTainted) {
134
+ // Mark as a virtual ENV_READ in the importing file
135
+ facts.ENV_READ.push({
136
+ file: imp.file,
137
+ line: imp.line,
138
+ variable: `[Cross-File] ${imp.local} (from ${imp.source})`,
139
+ isCrossFile: true
140
+ });
141
+ }
142
+ }
143
+ });
144
+ }
145
+
106
146
  async getFiles() {
107
147
  // Load .ziftignore
108
148
  const ziftIgnorePath = path.join(this.packageDir, '.ziftignore');
package/src/shield.js ADDED
@@ -0,0 +1,57 @@
1
+ const diagnostics = require('node:diagnostics_channel');
2
+
3
+ /**
4
+ * Zift Shield Runtime Guard
5
+ * Intercepts network and shell activity at runtime for security auditing.
6
+ */
7
+
8
+ function setupShield() {
9
+ console.warn('🛡️ ZIFT SHIELD ACTIVE: Monitoring suspicious runtime activity...');
10
+
11
+ // 1. Monitor Network Activity via diagnostics_channel
12
+ const netChannel = diagnostics.channel('net.client.socket.request.start');
13
+ netChannel.subscribe(({ address, port }) => {
14
+ console.warn(`[ZIFT-SHIELD] 🌐 Outbound Connection: ${address}:${port}`);
15
+ });
16
+
17
+ // 2. Wrap Child Process (for shell command execution)
18
+ const cp = require('node:child_process');
19
+ ['exec', 'spawn', 'execSync', 'spawnSync'].forEach(method => {
20
+ const original = cp[method];
21
+ cp[method] = function (...args) {
22
+ const command = args[0];
23
+ const cmdStr = typeof command === 'string' ? command : (args[1] ? args[1].join(' ') : 'unknown');
24
+ console.warn(`[ZIFT-SHIELD] 🐚 Shell Execution: ${cmdStr}`);
25
+
26
+ // Heuristic Check: Is it a potential dropper?
27
+ if (cmdStr.includes('curl') || cmdStr.includes('wget') || cmdStr.includes('| sh')) {
28
+ console.error(`[ZIFT-SHIELD] ⚠️ CRITICAL: Potential Remote Dropper detected in shell execution!`);
29
+ }
30
+
31
+ return original.apply(this, args);
32
+ };
33
+ });
34
+
35
+ // 3. Monitor HTTP/HTTPS
36
+ const http = require('node:http');
37
+ const https = require('node:https');
38
+ [http, https].forEach(mod => {
39
+ ['request', 'get'].forEach(method => {
40
+ const original = mod[method];
41
+ mod[method] = function (...args) {
42
+ let url = args[0];
43
+ if (typeof url === 'object' && url.href) url = url.href;
44
+ else if (typeof url === 'string') url = url;
45
+ else url = `${args[0].host || args[0].hostname}${args[0].path || ''}`;
46
+
47
+ console.warn(`[ZIFT-SHIELD] 📡 HTTP Request: ${url}`);
48
+ return original.apply(this, args);
49
+ };
50
+ });
51
+ });
52
+ }
53
+
54
+ // Auto-activate if required via node -r
55
+ setupShield();
56
+
57
+ module.exports = { setupShield };
package/v22_output.txt DELETED
@@ -1,12 +0,0 @@
1
- 🛡️ Verifying Zift v2.2.0 Deterministic Architecture...
2
- 📊 Audit Results:
3
- - [Priority: 1, Score: 100] ZFT-005: Shell Command Execution
4
- - [Priority: 1, Score: 80] ZFT-001: Environment Variable Exfiltration
5
-
6
- 🔍 Structural Verification:
7
- - DNS Exfil detected: false
8
- - Env Exfil detected: true
9
- - Remote Dropper detected: false
10
- - Mass Env Access detected: false
11
- - Dynamic Require detected: false
12
- ❌ v2.2.0 Verification incomplete. Some rules did not trigger as expected.
@@ -1,16 +0,0 @@
1
- 🛡️ Verifying Zift v2.2.0 Deterministic Architecture...
2
- 📊 Audit Results:
3
- - [Priority: 1, Score: 100] ZFT-005: Shell Command Execution
4
- - [Priority: 2, Score: 85] ZFT-007: DNS-Based Exfiltration
5
- - [Priority: 1, Score: 80] ZFT-001: Environment Variable Exfiltration
6
- - [Priority: 3, Score: 75] ZFT-009: Remote Script Dropper
7
- - [Priority: 1, Score: 30] ZFT-006: Dynamic Require Dependency
8
- - [Priority: 1, Score: 20] ZFT-008: Suspicious Information Collection
9
-
10
- 🔍 Structural Verification:
11
- - DNS Exfil detected: true
12
- - Env Exfil detected: true
13
- - Remote Dropper detected: true
14
- - Mass Env Access detected: true
15
- - Dynamic Require detected: true
16
- ✅ v2.2.0 Architecture Verified Successfully!