@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
@@ -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
+ }
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@isol8/core",
3
+ "version": "0.13.0-alpha.0",
4
+ "description": "Core engine for isol8 secure code execution",
5
+ "author": "Illusion47586",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/index.js",
13
+ "types": "./dist/index.d.ts"
14
+ },
15
+ "./schema": "./schema/isol8.config.schema.json"
16
+ },
17
+ "scripts": {
18
+ "build": "bun run scripts/build.ts",
19
+ "test": "bun test tests/unit/",
20
+ "test:prod": "echo 'No production tests in core package'",
21
+ "lint:check": "ultracite check",
22
+ "lint:fix": "ultracite fix",
23
+ "schema": "ts-json-schema-generator --path src/types.ts --type Isol8UserConfig --tsconfig tsconfig.json -o schema/isol8.config.schema.json && ultracite fix schema/isol8.config.schema.json"
24
+ },
25
+ "dependencies": {
26
+ "dockerode": "^4.0.9",
27
+ "hono": "^4.11.9"
28
+ },
29
+ "devDependencies": {
30
+ "@types/bun": "latest",
31
+ "@types/dockerode": "^4.0.1",
32
+ "@types/node": "^25.2.3",
33
+ "ts-json-schema-generator": "^2.5.0",
34
+ "typescript": "^5.9.3",
35
+ "ultracite": "^7.2.0"
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "schema",
40
+ "docker"
41
+ ],
42
+ "jsonValidation": [
43
+ {
44
+ "fileMatch": "isol8.config.json",
45
+ "url": "./schema/isol8.config.schema.json"
46
+ }
47
+ ]
48
+ }