donsetch 1.1.0 → 1.2.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.
Files changed (2) hide show
  1. package/install.js +20 -6
  2. package/package.json +1 -1
package/install.js CHANGED
@@ -18,7 +18,7 @@ const https = require('https');
18
18
  const crypto = require('crypto');
19
19
  const fs = require('fs');
20
20
  const path = require('path');
21
- const { execSync } = require('child_process');
21
+ const { execFileSync } = require('child_process');
22
22
 
23
23
  const REPO = 'dondai44423/donsetch';
24
24
  const VERSION = require('./package.json').version;
@@ -61,15 +61,27 @@ const baseUrl = `https://github.com/${REPO}/releases/download/${TAG}`;
61
61
  const assetUrl = `${baseUrl}/${plat.asset}`;
62
62
  const checksumUrl = `${baseUrl}/${plat.asset}.sha256`;
63
63
 
64
- // ── download with redirect following ────────────────────────────
64
+ // ── download with redirect following (max 5 hops) ───────────────
65
65
  function download(url, dest) {
66
66
  return new Promise((resolve, reject) => {
67
- function get(u) {
67
+ const MAX_REDIRECTS = 5;
68
+ function get(u, hops) {
69
+ if (hops > MAX_REDIRECTS) {
70
+ reject(new Error(`too many redirects for ${url}`));
71
+ return;
72
+ }
68
73
  const opts = { headers: { 'Accept': 'application/octet-stream', 'User-Agent': 'donsetch-npm-installer' } };
69
74
  https.get(u, opts, (res) => {
70
75
  if ([301, 302, 303, 307, 308].includes(res.statusCode)) {
71
76
  res.resume();
72
- get(res.headers.location);
77
+ const loc = res.headers.location;
78
+ if (!loc) { reject(new Error(`redirect without Location from ${u}`)); return; }
79
+ // Stay on https: never follow a downgrade to cleartext.
80
+ if (loc.startsWith('http://')) {
81
+ reject(new Error(`refusing http:// downgrade redirect to ${loc}`));
82
+ return;
83
+ }
84
+ get(loc, hops + 1);
73
85
  return;
74
86
  }
75
87
  if (res.statusCode !== 200) {
@@ -86,7 +98,7 @@ function download(url, dest) {
86
98
  });
87
99
  }).on('error', reject);
88
100
  }
89
- get(url);
101
+ get(url, 0);
90
102
  });
91
103
  }
92
104
 
@@ -119,7 +131,9 @@ async function main() {
119
131
 
120
132
  // 4. Extract (tar is built into Linux, macOS, and Windows 10+)
121
133
  console.log('donsetch: extracting...');
122
- execSync(`tar xzf "${tarball}" -C "${binDir}"`, { stdio: 'inherit' });
134
+ // execFileSync: no shell, no string interpolation the install
135
+ // path (which can contain quotes/spaces) is passed as argv.
136
+ execFileSync('tar', ['xzf', tarball, '-C', binDir], { stdio: 'inherit' });
123
137
 
124
138
  // 5. Cleanup
125
139
  try { fs.unlinkSync(tarball); } catch (_) {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "donsetch",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Web fetch, search and crawl for AI agents. Zero API keys. Chrome-true TLS.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "author": "Bishesh Bhandari",