@keygraph/shannon 1.3.0 → 1.5.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/dist/index.mjs +67 -0
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -150,6 +150,72 @@ function addHostFlag() {
150
150
  return [];
151
151
  }
152
152
  /**
153
+ * Names whose standard IPs aren't covered by `shouldSkipHostsIp`. Loopback names
154
+ * stay because their IPs (127.x, ::1) get rewritten — not skipped. Others like
155
+ * `broadcasthost` and `ip6-mcastprefix` are intentionally omitted: their IPs
156
+ * (255.255.255.255, ff00::/8) are already dropped at the IP filter.
157
+ */
158
+ const HOSTS_SKIP_NAMES = new Set([
159
+ "localhost",
160
+ "ip6-localhost",
161
+ "ip6-loopback",
162
+ "ip6-localnet",
163
+ "host.docker.internal",
164
+ "gateway.docker.internal",
165
+ "kubernetes.docker.internal"
166
+ ]);
167
+ function isLoopbackIp(ip) {
168
+ return ip.startsWith("127.") || ip === "::1";
169
+ }
170
+ function shouldSkipHostsIp(ip) {
171
+ if (ip === "0.0.0.0" || ip === "255.255.255.255") return true;
172
+ if (ip.startsWith("169.254.")) return true;
173
+ const lower = ip.toLowerCase();
174
+ if (lower.startsWith("fe80:") || lower.startsWith("ff")) return true;
175
+ return false;
176
+ }
177
+ function shouldSkipHostsName(name, hostname) {
178
+ const lower = name.toLowerCase();
179
+ if (HOSTS_SKIP_NAMES.has(lower)) return true;
180
+ if (lower === hostname.toLowerCase()) return true;
181
+ if (lower.endsWith(".localhost")) return true;
182
+ return false;
183
+ }
184
+ /**
185
+ * Read the host's /etc/hosts and emit --add-host flags so the worker resolves
186
+ * user-added entries the same way. Loopback IPs (127.x, ::1) are rewritten to
187
+ * `host-gateway` so they target the host's loopback instead of the container's.
188
+ */
189
+ function forwardEtcHostsFlags() {
190
+ if (process.env.SHANNON_FORWARD_HOSTS === "false") return [];
191
+ if (os.platform() === "win32") return [];
192
+ let content;
193
+ try {
194
+ content = fs.readFileSync("/etc/hosts", "utf-8");
195
+ } catch {
196
+ return [];
197
+ }
198
+ const hostname = os.hostname();
199
+ const flags = [];
200
+ for (const rawLine of content.split("\n")) {
201
+ const hashIdx = rawLine.indexOf("#");
202
+ const line = (hashIdx >= 0 ? rawLine.slice(0, hashIdx) : rawLine).trim();
203
+ if (!line) continue;
204
+ const tokens = line.split(" ").flatMap((t) => t.split(" ")).filter(Boolean);
205
+ const ip = tokens[0];
206
+ const names = tokens.slice(1);
207
+ if (!ip || names.length === 0) continue;
208
+ if (shouldSkipHostsIp(ip)) continue;
209
+ const targetIp = isLoopbackIp(ip) ? "host-gateway" : ip;
210
+ const formattedIp = targetIp.includes(":") ? `[${targetIp}]` : targetIp;
211
+ for (const name of names) {
212
+ if (shouldSkipHostsName(name, hostname)) continue;
213
+ flags.push("--add-host", `${name}:${formattedIp}`);
214
+ }
215
+ }
216
+ return flags;
217
+ }
218
+ /**
153
219
  * Spawn the worker container in detached mode and return the process.
154
220
  * When `opts.debug` is true, omits `--rm` so the container persists for log inspection.
155
221
  */
@@ -158,6 +224,7 @@ function spawnWorker(opts) {
158
224
  if (!opts.debug) args.push("--rm");
159
225
  args.push("--name", opts.containerName, "--network", "shannon-net");
160
226
  args.push(...addHostFlag());
227
+ args.push(...forwardEtcHostsFlags());
161
228
  if (os.platform() === "linux" && process.getuid && process.getgid) args.push("-e", `SHANNON_HOST_UID=${process.getuid()}`, "-e", `SHANNON_HOST_GID=${process.getgid()}`);
162
229
  args.push("-v", `${opts.workspacesDir}:/app/workspaces`);
163
230
  args.push("-v", `${opts.repo.hostPath}:${opts.repo.containerPath}:ro`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keygraph/shannon",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "description": "Shannon - Autonomous white-box AI pentester for web applications and APIs by Keygraph",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",