@isol8/core 0.13.0-alpha.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 (57) hide show
  1. package/README.md +39 -0
  2. package/dist/client/remote.d.ts +64 -0
  3. package/dist/client/remote.d.ts.map +1 -0
  4. package/dist/config.d.ts +36 -0
  5. package/dist/config.d.ts.map +1 -0
  6. package/dist/docker/Dockerfile +42 -0
  7. package/dist/docker/proxy-handler.sh +180 -0
  8. package/dist/docker/proxy.sh +57 -0
  9. package/dist/docker/seccomp-profile.json +67 -0
  10. package/dist/engine/audit.d.ts +31 -0
  11. package/dist/engine/audit.d.ts.map +1 -0
  12. package/dist/engine/code-fetcher.d.ts +21 -0
  13. package/dist/engine/code-fetcher.d.ts.map +1 -0
  14. package/dist/engine/concurrency.d.ts +46 -0
  15. package/dist/engine/concurrency.d.ts.map +1 -0
  16. package/dist/engine/default-seccomp-profile.d.ts +8 -0
  17. package/dist/engine/default-seccomp-profile.d.ts.map +1 -0
  18. package/dist/engine/docker.d.ts +167 -0
  19. package/dist/engine/docker.d.ts.map +1 -0
  20. package/dist/engine/image-builder.d.ts +71 -0
  21. package/dist/engine/image-builder.d.ts.map +1 -0
  22. package/dist/engine/pool.d.ts +94 -0
  23. package/dist/engine/pool.d.ts.map +1 -0
  24. package/dist/engine/stats.d.ts +35 -0
  25. package/dist/engine/stats.d.ts.map +1 -0
  26. package/dist/engine/utils.d.ts +71 -0
  27. package/dist/engine/utils.d.ts.map +1 -0
  28. package/dist/index.d.ts +19 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +2777 -0
  31. package/dist/index.js.map +30 -0
  32. package/dist/runtime/adapter.d.ts +63 -0
  33. package/dist/runtime/adapter.d.ts.map +1 -0
  34. package/dist/runtime/adapters/bash.d.ts +3 -0
  35. package/dist/runtime/adapters/bash.d.ts.map +1 -0
  36. package/dist/runtime/adapters/bun.d.ts +4 -0
  37. package/dist/runtime/adapters/bun.d.ts.map +1 -0
  38. package/dist/runtime/adapters/deno.d.ts +10 -0
  39. package/dist/runtime/adapters/deno.d.ts.map +1 -0
  40. package/dist/runtime/adapters/node.d.ts +4 -0
  41. package/dist/runtime/adapters/node.d.ts.map +1 -0
  42. package/dist/runtime/adapters/python.d.ts +4 -0
  43. package/dist/runtime/adapters/python.d.ts.map +1 -0
  44. package/dist/runtime/index.d.ts +15 -0
  45. package/dist/runtime/index.d.ts.map +1 -0
  46. package/dist/types.d.ts +532 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/utils/logger.d.ts +32 -0
  49. package/dist/utils/logger.d.ts.map +1 -0
  50. package/dist/version.d.ts +15 -0
  51. package/dist/version.d.ts.map +1 -0
  52. package/docker/Dockerfile +42 -0
  53. package/docker/proxy-handler.sh +180 -0
  54. package/docker/proxy.sh +57 -0
  55. package/docker/seccomp-profile.json +67 -0
  56. package/package.json +48 -0
  57. package/schema/isol8.config.schema.json +315 -0
package/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # @isol8/core
2
+
3
+ Core engine for isol8 secure code execution.
4
+
5
+ > **Note**: The `isol8` package is deprecated. Use `@isol8/core` instead.
6
+
7
+ For full documentation, usage examples, and contribution guidelines, see the main [isol8 README](../README.md).
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @isol8/core
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { DockerIsol8 } from "@isol8/core";
19
+
20
+ const engine = new DockerIsol8();
21
+ await engine.start();
22
+
23
+ const result = await engine.execute({
24
+ code: "print('Hello from isol8!')",
25
+ runtime: "python",
26
+ });
27
+
28
+ console.log(result.stdout); // "Hello from isol8!\n"
29
+
30
+ await engine.stop();
31
+ ```
32
+
33
+ ## API
34
+
35
+ See [API Documentation](https://isol8.dev/docs/api) for full API reference.
36
+
37
+ ## License
38
+
39
+ MIT - See [../LICENSE](../LICENSE)
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @module client/remote
3
+ *
4
+ * HTTP client for communicating with a remote isol8 server. Implements the
5
+ * {@link Isol8Engine} interface, so it can be used interchangeably with
6
+ * {@link DockerIsol8} for local-vs-remote execution.
7
+ */
8
+ import type { ExecutionRequest, ExecutionResult, Isol8Engine, Isol8Options, StartOptions, StreamEvent } from "../types";
9
+ /** Connection options for the remote isol8 client. */
10
+ export interface RemoteIsol8Options {
11
+ /** Base URL of the isol8 server (e.g. `"http://localhost:3000"`). */
12
+ host: string;
13
+ /** API key for Bearer token authentication. */
14
+ apiKey: string;
15
+ /** Optional session ID for persistent mode. If set, the server maintains container state across calls. */
16
+ sessionId?: string;
17
+ }
18
+ /**
19
+ * Remote isol8 client that communicates with an isol8 server over HTTP.
20
+ * Implements the {@link Isol8Engine} interface for seamless local/remote switching.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const isol8 = new RemoteIsol8(
25
+ * { host: "http://localhost:3000", apiKey: "secret" },
26
+ * { network: "none" }
27
+ * );
28
+ * await isol8.start();
29
+ * const result = await isol8.execute({ code: "print(1)", runtime: "python" });
30
+ * await isol8.stop();
31
+ * ```
32
+ */
33
+ export declare class RemoteIsol8 implements Isol8Engine {
34
+ private readonly host;
35
+ private readonly apiKey;
36
+ private readonly sessionId?;
37
+ private readonly isol8Options?;
38
+ /**
39
+ * @param options - Connection options (host, API key, session ID).
40
+ * @param isol8Options - Isol8 configuration to send to the server.
41
+ */
42
+ constructor(options: RemoteIsol8Options, isol8Options?: Isol8Options);
43
+ /** Verify the remote server is reachable by hitting the `/health` endpoint. */
44
+ start(_options?: StartOptions): Promise<void>;
45
+ /** Destroy the remote session (if persistent). No-op for ephemeral mode. */
46
+ stop(): Promise<void>;
47
+ /** Execute code on the remote server and return the result. */
48
+ execute(req: ExecutionRequest): Promise<ExecutionResult>;
49
+ /**
50
+ * Execute code on the remote server and stream output chunks via SSE.
51
+ * Yields {@link StreamEvent} objects as they arrive from the server.
52
+ */
53
+ executeStream(req: ExecutionRequest): AsyncIterable<StreamEvent>;
54
+ /**
55
+ * Upload a file to the remote container (persistent mode only).
56
+ * Content is Base64-encoded for transport.
57
+ */
58
+ putFile(path: string, content: Buffer | string): Promise<void>;
59
+ /** Download a file from the remote container (persistent mode only). */
60
+ getFile(path: string): Promise<Buffer>;
61
+ /** Internal fetch wrapper that attaches auth and content-type headers. */
62
+ private fetch;
63
+ }
64
+ //# sourceMappingURL=remote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../../src/client/remote.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACZ,MAAM,UAAU,CAAC;AAElB,sDAAsD;AACtD,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,0GAA0G;IAC1G,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,WAAY,YAAW,WAAW;IAC7C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAe;IAE7C;;;OAGG;gBACS,OAAO,EAAE,kBAAkB,EAAE,YAAY,CAAC,EAAE,YAAY;IAOpE,+EAA+E;IACzE,KAAK,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAQnD,4EAA4E;IACtE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B,+DAA+D;IACzD,OAAO,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IAkB9D;;;OAGG;IACI,aAAa,CAAC,GAAG,EAAE,gBAAgB,GAAG,aAAa,CAAC,WAAW,CAAC;IA0DvE;;;OAGG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBpE,wEAAwE;IAClE,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgB5C,0EAA0E;YAC5D,KAAK;CAUpB"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @module config
3
+ *
4
+ * Configuration discovery and loading for isol8. Searches for `isol8.config.json`
5
+ * in the working directory and then in `~/.isol8/config.json`, merging any found
6
+ * config with built-in defaults.
7
+ */
8
+ import type { Isol8Config } from "./types";
9
+ /**
10
+ * Built-in default configuration. Used as the base for all config merges.
11
+ * All values here are the "safe defaults" — network disabled, conservative limits.
12
+ */
13
+ declare const DEFAULT_CONFIG: Isol8Config;
14
+ /**
15
+ * Discovers and loads the isol8 configuration file.
16
+ *
17
+ * Search order (first match wins):
18
+ * 1. `isol8.config.json` in CWD (or the provided `cwd` argument)
19
+ * 2. `~/.isol8/config.json`
20
+ *
21
+ * If no config file is found, returns a copy of {@link DEFAULT_CONFIG}.
22
+ * Partial configs are deep-merged with defaults — you only need to specify
23
+ * the fields you want to override.
24
+ *
25
+ * @param cwd - Optional working directory to search from (defaults to `process.cwd()`).
26
+ * @returns The resolved configuration.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const config = loadConfig();
31
+ * console.log(config.defaults.timeoutMs); // 30000
32
+ * ```
33
+ */
34
+ export declare function loadConfig(cwd?: string): Isol8Config;
35
+ export { DEFAULT_CONFIG };
36
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C;;;GAGG;AACH,QAAA,MAAM,cAAc,EAAE,WA0DrB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW,CAepD;AAiDD,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,42 @@
1
+ # ── Base ──────────────────────────────────────────────────────────────
2
+ FROM alpine:3.21 AS base
3
+ RUN apk add --no-cache tini curl ca-certificates iptables bash \
4
+ && addgroup -S sandbox && adduser -S sandbox -G sandbox -h /sandbox
5
+ COPY proxy.sh /usr/local/bin/proxy.sh
6
+ COPY proxy-handler.sh /usr/local/bin/proxy-handler.sh
7
+ RUN chmod +x /usr/local/bin/proxy.sh /usr/local/bin/proxy-handler.sh
8
+ WORKDIR /sandbox
9
+ ENTRYPOINT ["/sbin/tini", "--"]
10
+
11
+ # ── Python ────────────────────────────────────────────────────────────
12
+ FROM base AS python
13
+ RUN apk add --no-cache python3 py3-pip
14
+ CMD ["python3"]
15
+
16
+ # ── Node ──────────────────────────────────────────────────────────────
17
+ FROM base AS node
18
+ RUN apk add --no-cache nodejs npm
19
+ CMD ["node"]
20
+
21
+ # ── Bun ───────────────────────────────────────────────────────────────
22
+ FROM base AS bun
23
+ RUN apk add --no-cache unzip libstdc++ libgcc \
24
+ && curl -fsSL https://bun.sh/install | bash \
25
+ && mv /root/.bun/bin/bun /usr/local/bin/bun \
26
+ && ln -s /usr/local/bin/bun /usr/local/bin/bunx
27
+ CMD ["bun"]
28
+
29
+ # ── Deno ──────────────────────────────────────────────────────────────
30
+ FROM denoland/deno:alpine AS deno
31
+ RUN apk add --no-cache tini curl ca-certificates iptables bash \
32
+ && addgroup -S sandbox && adduser -S sandbox -G sandbox -h /sandbox
33
+ COPY proxy.sh /usr/local/bin/proxy.sh
34
+ COPY proxy-handler.sh /usr/local/bin/proxy-handler.sh
35
+ RUN chmod +x /usr/local/bin/proxy.sh /usr/local/bin/proxy-handler.sh
36
+ WORKDIR /sandbox
37
+ ENTRYPOINT ["/sbin/tini", "--"]
38
+ CMD ["deno"]
39
+
40
+ # ── Bash ──────────────────────────────────────────────────────────────
41
+ FROM base AS bash
42
+ CMD ["bash"]
@@ -0,0 +1,180 @@
1
+ #!/bin/bash
2
+ # isol8 proxy handler — handles a single proxied connection.
3
+ #
4
+ # Invoked by: nc -lk -e proxy-handler.sh
5
+ # stdin/stdout are wired to the client socket by nc.
6
+ #
7
+ # Env vars (inherited from proxy.sh launcher):
8
+ # ISOL8_WHITELIST_FILE - Path to file with whitelist regex patterns
9
+ # ISOL8_BLACKLIST_FILE - Path to file with blacklist regex patterns
10
+ #
11
+ # Supports:
12
+ # - HTTPS CONNECT tunneling (bidirectional relay via exec nc)
13
+ # - HTTP forwarding (GET/POST/etc via bash /dev/tcp)
14
+
15
+ WL="${ISOL8_WHITELIST_FILE:-}"
16
+ BL="${ISOL8_BLACKLIST_FILE:-}"
17
+
18
+ log_network() {
19
+ local method="$1"
20
+ local host="$2"
21
+ local path="$3"
22
+ local action="$4"
23
+ local duration_ms="$5"
24
+
25
+ if [ -d "/tmp/isol8-proxy" ]; then
26
+ # Handle path: output proper JSON null if path is "null", otherwise quote it
27
+ if [ "$path" = "null" ] || [ -z "$path" ]; then
28
+ printf '{"timestamp":"%s","method":"%s","host":"%s","path":null,"action":"%s","durationMs":%d}\n' \
29
+ "$(date -Iseconds)" "$method" "$host" "$action" "$duration_ms" >> /tmp/isol8-proxy/network.jsonl
30
+ else
31
+ printf '{"timestamp":"%s","method":"%s","host":"%s","path":"%s","action":"%s","durationMs":%d}\n' \
32
+ "$(date -Iseconds)" "$method" "$host" "$path" "$action" "$duration_ms" >> /tmp/isol8-proxy/network.jsonl
33
+ fi
34
+ fi
35
+ }
36
+
37
+ is_allowed() {
38
+ local host="$1"
39
+
40
+ # Check blacklist first
41
+ if [ -n "$BL" ] && [ -s "$BL" ]; then
42
+ if echo "$host" | grep -qEf "$BL" 2>/dev/null; then
43
+ return 1
44
+ fi
45
+ fi
46
+
47
+ # If whitelist is empty or missing, allow all
48
+ if [ -z "$WL" ] || [ ! -s "$WL" ]; then
49
+ return 0
50
+ fi
51
+
52
+ # Must match at least one whitelist pattern
53
+ if echo "$host" | grep -qEf "$WL" 2>/dev/null; then
54
+ return 0
55
+ fi
56
+
57
+ return 1
58
+ }
59
+
60
+ # Read the request line
61
+ # e.g. "CONNECT host:443 HTTP/1.1" or "GET http://host/path HTTP/1.1"
62
+ read -r request_line || exit 0
63
+ request_line="${request_line%%$'\r'}"
64
+
65
+ method="${request_line%% *}"
66
+ rest="${request_line#* }"
67
+ target="${rest%% *}"
68
+
69
+ # Read and store all headers until blank line
70
+ headers=""
71
+ content_length=0
72
+ while IFS= read -r hline; do
73
+ hline="${hline%%$'\r'}"
74
+ [ -z "$hline" ] && break
75
+ headers="${headers}${hline}"$'\n'
76
+ # Extract Content-Length
77
+ case "$hline" in
78
+ [Cc]ontent-[Ll]ength:*)
79
+ content_length="${hline#*: }"
80
+ content_length="${content_length// /}"
81
+ ;;
82
+ esac
83
+ done
84
+
85
+ # ── CONNECT (HTTPS tunneling) ──────────────────────────────────────────
86
+ if [ "$method" = "CONNECT" ]; then
87
+ host="${target%%:*}"
88
+ port="${target##*:}"
89
+ [ "$port" = "$host" ] && port=443
90
+
91
+ if ! is_allowed "$host"; then
92
+ msg="isol8: CONNECT to ${host} blocked by network filter"
93
+ # Log security event
94
+ if [ -d "/tmp/isol8-proxy" ]; then
95
+ printf '{"type":"network_blocked","timestamp":"%s","details":{"method":"CONNECT","host":"%s","reason":"filter_mismatch"}}\n' "$(date -Iseconds)" "$host" >> /tmp/isol8-proxy/security-events.jsonl
96
+ fi
97
+ # Log network event
98
+ log_network "CONNECT" "$host" "null" "BLOCK" 0
99
+ printf "HTTP/1.1 403 Forbidden\r\nContent-Type: text/plain\r\nContent-Length: %d\r\n\r\n%s" \
100
+ "${#msg}" "$msg"
101
+ exit 0
102
+ fi
103
+
104
+ # Log allowed CONNECT (duration will be 0 since we can't measure after exec)
105
+ log_network "CONNECT" "$host" "null" "ALLOW" 0
106
+
107
+ # Send 200 then replace this process with nc for bidirectional relay.
108
+ # nc inherits the client socket on stdin/stdout from the nc -lk -e parent.
109
+ printf "HTTP/1.1 200 Connection Established\r\n\r\n"
110
+ exec nc "$host" "$port"
111
+ fi
112
+
113
+ # ── HTTP forwarding ────────────────────────────────────────────────────
114
+ # Proxy HTTP requests use absolute URLs: GET http://host:port/path HTTP/1.1
115
+ url_rest="${target#*://}"
116
+ hostport="${url_rest%%/*}"
117
+ path="/${url_rest#*/}"
118
+ # Handle URLs with no path component
119
+ [ "$path" = "/${url_rest}" ] && path="/"
120
+
121
+ host="${hostport%%:*}"
122
+ port="${hostport##*:}"
123
+ [ "$port" = "$host" ] && port=80
124
+
125
+ if ! is_allowed "$host"; then
126
+ msg="isol8: request to ${host} blocked by network filter"
127
+ # Log security event
128
+ if [ -d "/tmp/isol8-proxy" ]; then
129
+ printf '{"type":"network_blocked","timestamp":"%s","details":{"method":"%s","host":"%s","reason":"filter_mismatch"}}\n' "$(date -Iseconds)" "$method" "$host" >> /tmp/isol8-proxy/security-events.jsonl
130
+ fi
131
+ # Log network event
132
+ log_network "$method" "$host" "$path" "BLOCK" 0
133
+ printf "HTTP/1.1 403 Forbidden\r\nContent-Type: text/plain\r\nContent-Length: %d\r\n\r\n%s" \
134
+ "${#msg}" "$msg"
135
+ exit 0
136
+ fi
137
+
138
+ # Record start time for duration measurement
139
+ if [ -d "/tmp/isol8-proxy" ]; then
140
+ start_time=$(date +%s%3N)
141
+ fi
142
+
143
+ # Open TCP connection via bash /dev/tcp
144
+ if ! exec 3<>/dev/tcp/"$host"/"$port" 2>/dev/null; then
145
+ msg="isol8: proxy error: connection to ${host}:${port} failed"
146
+ printf "HTTP/1.1 502 Bad Gateway\r\nContent-Type: text/plain\r\nContent-Length: %d\r\n\r\n%s" \
147
+ "${#msg}" "$msg"
148
+ exit 0
149
+ fi
150
+
151
+ # Send request line with relative path (not absolute URL)
152
+ printf "%s %s HTTP/1.1\r\n" "$method" "$path" >&3
153
+
154
+ # Forward headers, skipping Proxy-* headers
155
+ while IFS= read -r h; do
156
+ [ -z "$h" ] && continue
157
+ case "$h" in
158
+ Proxy-*|proxy-*) continue ;;
159
+ esac
160
+ printf "%s\r\n" "$h" >&3
161
+ done <<< "$headers"
162
+ printf "\r\n" >&3
163
+
164
+ # Forward request body if present
165
+ if [ "$content_length" -gt 0 ] 2>/dev/null; then
166
+ head -c "$content_length" >&3
167
+ fi
168
+
169
+ # Relay response back to client
170
+ cat <&3
171
+
172
+ # Calculate duration and log the network event
173
+ if [ -n "$start_time" ] && [ -d "/tmp/isol8-proxy" ]; then
174
+ end_time=$(date +%s%3N)
175
+ duration=$((end_time - start_time))
176
+ log_network "$method" "$host" "$path" "ALLOW" "$duration"
177
+ fi
178
+
179
+ exec 3>&-
180
+ exit 0
@@ -0,0 +1,57 @@
1
+ #!/bin/bash
2
+ # isol8 proxy launcher — parses env vars and starts the proxy listener.
3
+ #
4
+ # Env vars:
5
+ # ISOL8_WHITELIST - JSON array of regex strings (allow these)
6
+ # ISOL8_BLACKLIST - JSON array of regex strings (block these)
7
+ # ISOL8_PROXY_PORT - Port to listen on (default: 8118)
8
+ #
9
+ # This script:
10
+ # 1. Parses ISOL8_WHITELIST/BLACKLIST JSON arrays into grep-compatible pattern files
11
+ # 2. Starts nc -lk -e /usr/local/bin/proxy-handler.sh on the specified port
12
+ #
13
+ # The pattern files are stored in /tmp/isol8-proxy/ and exported as env vars
14
+ # so the handler (forked by nc -e) can access them via inherited environment.
15
+
16
+ PORT="${ISOL8_PROXY_PORT:-8118}"
17
+ PROXY_DIR="/tmp/isol8-proxy"
18
+ mkdir -p "$PROXY_DIR"
19
+
20
+ # Create log files
21
+ touch "$PROXY_DIR/security-events.jsonl"
22
+ touch "$PROXY_DIR/network.jsonl"
23
+
24
+ WL_FILE="$PROXY_DIR/whitelist"
25
+ BL_FILE="$PROXY_DIR/blacklist"
26
+
27
+ # Parse JSON array of regex strings into a file with one ERE pattern per line.
28
+ # Input: JSON like '["^example\\.com$","^api\\."]'
29
+ # Output: file with one grep -E compatible pattern per line
30
+ parse_patterns() {
31
+ local json="$1" outfile="$2"
32
+ : > "$outfile"
33
+ if [ -z "$json" ] || [ "$json" = "[]" ]; then
34
+ return
35
+ fi
36
+ # Strip brackets, split on "," → one quoted pattern per line
37
+ # Then strip quotes and unescape doubled backslashes from JSON encoding
38
+ echo "$json" \
39
+ | sed 's/^\[//; s/\]$//' \
40
+ | sed 's/","/"\n"/g' \
41
+ | sed 's/^"//; s/"$//' \
42
+ | sed 's/\\\\/\\/g' \
43
+ > "$outfile"
44
+ }
45
+
46
+ parse_patterns "${ISOL8_WHITELIST:-}" "$WL_FILE"
47
+ parse_patterns "${ISOL8_BLACKLIST:-}" "$BL_FILE"
48
+
49
+ # Export paths so the handler (forked by nc -e) can find them
50
+ export ISOL8_WHITELIST_FILE="$WL_FILE"
51
+ export ISOL8_BLACKLIST_FILE="$BL_FILE"
52
+
53
+ echo "isol8 proxy listening on 127.0.0.1:${PORT}"
54
+
55
+ # Start listening — nc -lk provides a persistent server that forks
56
+ # a handler for each connection with stdin/stdout wired to the socket
57
+ exec nc -lk -s 127.0.0.1 -p "$PORT" -e /usr/local/bin/proxy-handler.sh
@@ -0,0 +1,67 @@
1
+ {
2
+ "defaultAction": "SCMP_ACT_ALLOW",
3
+ "architectures": [
4
+ "SCMP_ARCH_X86_64",
5
+ "SCMP_ARCH_X86",
6
+ "SCMP_ARCH_X32",
7
+ "SCMP_ARCH_AARCH64"
8
+ ],
9
+ "syscalls": [
10
+ {
11
+ "names": [
12
+ "acct",
13
+ "add_key",
14
+ "bpf",
15
+ "clock_adjtime",
16
+ "clock_settime",
17
+ "create_module",
18
+ "delete_module",
19
+ "finit_module",
20
+ "get_mempolicy",
21
+ "init_module",
22
+ "ioperm",
23
+ "iopl",
24
+ "kcmp",
25
+ "kexec_file_load",
26
+ "kexec_load",
27
+ "keyctl",
28
+ "lookup_dcookie",
29
+ "mbind",
30
+ "mount",
31
+ "move_pages",
32
+ "name_to_handle_at",
33
+ "open_by_handle_at",
34
+ "perf_event_open",
35
+ "pivot_root",
36
+ "process_vm_readv",
37
+ "process_vm_writev",
38
+ "ptrace",
39
+ "query_module",
40
+ "quotactl",
41
+ "reboot",
42
+ "request_key",
43
+ "set_mempolicy",
44
+ "setns",
45
+ "settimeofday",
46
+ "stime",
47
+ "swapon",
48
+ "swapoff",
49
+ "sysfs",
50
+ "syslog",
51
+ "umount",
52
+ "umount2",
53
+ "unshare",
54
+ "uselib",
55
+ "userfaultfd",
56
+ "ustat",
57
+ "vm86",
58
+ "vm86old"
59
+ ],
60
+ "action": "SCMP_ACT_ERRNO",
61
+ "args": [],
62
+ "comment": "",
63
+ "includes": {},
64
+ "excludes": {}
65
+ }
66
+ ]
67
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Pluggable audit logger for execution provenance.
3
+ *
4
+ * Records ExecutionAudit objects to various destinations based on configuration.
5
+ * Supports filesystem and stdout logging, with extensibility for cloud services.
6
+ */
7
+ import type { AuditConfig, ExecutionAudit } from "../types";
8
+ export declare class AuditLogger {
9
+ private readonly config;
10
+ private readonly auditFile;
11
+ constructor(config: AuditConfig);
12
+ /**
13
+ * Clean up audit log files older than retentionDays.
14
+ * Checks both the main executions.log and any rotated/archived logs.
15
+ */
16
+ private cleanupOldLogs;
17
+ /**
18
+ * Record an audit entry based on the current configuration.
19
+ */
20
+ record(audit: ExecutionAudit): void;
21
+ /**
22
+ * Run the configured post-log script.
23
+ * The script receives the audit file path as its first argument.
24
+ */
25
+ private runPostLogScript;
26
+ /**
27
+ * Apply privacy filtering to audit data based on configuration.
28
+ */
29
+ private filterAuditData;
30
+ }
31
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/engine/audit.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG5D,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,MAAM,EAAE,WAAW;IAqB/B;;;OAGG;IACH,OAAO,CAAC,cAAc;IAwCtB;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAoCnC;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAuBxB;;OAEG;IACH,OAAO,CAAC,eAAe;CAuCxB"}
@@ -0,0 +1,21 @@
1
+ import type { RemoteCodePolicy } from "../types";
2
+ export interface FetchCodeRequest {
3
+ codeUrl: string;
4
+ codeHash?: string;
5
+ allowInsecureCodeUrl?: boolean;
6
+ }
7
+ export interface FetchCodeResult {
8
+ code: string;
9
+ url: string;
10
+ hash: string;
11
+ }
12
+ interface CodeFetcherDeps {
13
+ fetchFn?: (input: string, init?: RequestInit) => Promise<Response>;
14
+ lookupFn?: (hostname: string) => Promise<Array<{
15
+ address: string;
16
+ family: number;
17
+ }>>;
18
+ }
19
+ export declare function fetchRemoteCode(request: FetchCodeRequest, policy: RemoteCodePolicy, deps?: CodeFetcherDeps): Promise<FetchCodeResult>;
20
+ export {};
21
+ //# sourceMappingURL=code-fetcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-fetcher.d.ts","sourceRoot":"","sources":["../../src/engine/code-fetcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,eAAe;IACvB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnE,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;CACtF;AA2GD,wBAAsB,eAAe,CACnC,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,gBAAgB,EACxB,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,eAAe,CAAC,CAkH1B"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @module engine/concurrency
3
+ *
4
+ * Async semaphore for limiting the number of concurrent container executions.
5
+ * Used by {@link DockerIsol8} to prevent resource exhaustion.
6
+ */
7
+ /**
8
+ * A counting semaphore for limiting concurrent async operations.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const sem = new Semaphore(3); // allow 3 concurrent operations
13
+ *
14
+ * await sem.acquire();
15
+ * try {
16
+ * await doWork();
17
+ * } finally {
18
+ * sem.release();
19
+ * }
20
+ * ```
21
+ */
22
+ export declare class Semaphore {
23
+ private readonly max;
24
+ private current;
25
+ private readonly queue;
26
+ /**
27
+ * @param max - Maximum number of concurrent acquisitions. Must be ≥ 1.
28
+ * @throws {Error} If `max` is less than 1.
29
+ */
30
+ constructor(max: number);
31
+ /** The number of permits currently available. */
32
+ get available(): number;
33
+ /** The number of callers waiting to acquire a permit. */
34
+ get pending(): number;
35
+ /**
36
+ * Acquire a permit. Resolves immediately if one is available,
37
+ * otherwise queues the caller until a permit is released.
38
+ */
39
+ acquire(): Promise<void>;
40
+ /**
41
+ * Release a permit. If callers are queued, the next one is resolved.
42
+ * Must be called exactly once for each successful `acquire()`.
43
+ */
44
+ release(): void;
45
+ }
46
+ //# sourceMappingURL=concurrency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concurrency.d.ts","sourceRoot":"","sources":["../../src/engine/concurrency.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;;GAcG;AACH,qBAAa,SAAS;IAQR,OAAO,CAAC,QAAQ,CAAC,GAAG;IAPhC,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsB;IAE5C;;;OAGG;gBAC0B,GAAG,EAAE,MAAM;IAMxC,iDAAiD;IACjD,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,yDAAyD;IACzD,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAW9B;;;OAGG;IACH,OAAO,IAAI,IAAI;CAQhB"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Embedded default seccomp profile.
3
+ *
4
+ * This keeps strict seccomp available in standalone compiled binaries where
5
+ * docker/seccomp-profile.json may not be present on disk.
6
+ */
7
+ export declare const EMBEDDED_DEFAULT_SECCOMP_PROFILE: string;
8
+ //# sourceMappingURL=default-seccomp-profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-seccomp-profile.d.ts","sourceRoot":"","sources":["../../src/engine/default-seccomp-profile.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,QA6D3C,CAAC"}