IO Security
Keel takes a security-first approach to external access. By default, all file system IO and HTTP network requests are disabled. This protects against untrusted code accessing your file system or making network calls.
Security Model
Keel provides three security layers for IO access:
| Mode | Description | Use Case |
|---|---|---|
| Disabled (default) | No file system access | Running untrusted code, sandboxed environments |
| Read-Only | Can read files, cannot write | Data processing, analysis scripts |
| Sandboxed | Full IO within a directory | Plugin systems, isolated workloads |
Comparison Table
| Operation | Disabled | Read-Only | Sandboxed |
|---|---|---|---|
File.read | Denied | Allowed | Allowed (in sandbox) |
File.write | Denied | Denied | Allowed (in sandbox) |
File.append | Denied | Denied | Allowed (in sandbox) |
File.delete | Denied | Denied | Allowed (in sandbox) |
File.exists | Denied | Allowed | Allowed (in sandbox) |
Dir.list | Denied | Allowed | Allowed (in sandbox) |
Dir.create | Denied | Denied | Allowed (in sandbox) |
Dir.delete | Denied | Denied | Allowed (in sandbox) |
print / println | Allowed | Allowed | Allowed |
readLine | Allowed | Allowed | Allowed |
Environment Variables
Configure IO access using environment variables:
KEEL_IO_DISABLED
Controls whether file system IO is enabled.
| Value | Effect |
|---|---|
| (unset) | IO disabled (default) |
1 or true | IO disabled |
0 or false | IO enabled |
KEEL_IO_READ_ONLY
When IO is enabled, restricts access to read operations only.
| Value | Effect |
|---|---|
| (unset) | Full IO access (when enabled) |
1 or true | Read-only access |
0 or false | Full IO access |
KEEL_IO_SANDBOX
Restricts all IO operations to a specific directory. Paths outside the sandbox are denied.
| Value | Effect |
|---|---|
| (unset) | No path restrictions |
/path/to/dir | All IO restricted to this directory |
The sandbox enforces:
- All paths must be within the sandbox directory
- Path traversal attempts (
../) that escape the sandbox are denied - Symlinks pointing outside the sandbox are denied
Use Cases
Development
Enable full IO for local development:
KEEL_IO_DISABLED=0 keel run my-script.kl
CI/CD Pipelines
Read-only access for build scripts that need to read configuration but shouldn't modify files:
KEEL_IO_DISABLED=0 KEEL_IO_READ_ONLY=1 keel run build-check.kl
Plugin Systems
Sandbox plugins to their own directory:
KEEL_IO_DISABLED=0 KEEL_IO_SANDBOX=/app/plugins/my-plugin keel run plugin.kl
Data Processing
Read-only access for analysis scripts:
KEEL_IO_DISABLED=0 KEEL_IO_READ_ONLY=1 keel run analyze-logs.kl
Affected Operations
File Operations
| Function | Description | Requires |
|---|---|---|
File.read path | Read file contents | Read access |
File.readLines path | Read file as list of lines | Read access |
File.write path content | Write content to file | Write access |
File.append path content | Append content to file | Write access |
File.delete path | Delete a file | Write access |
File.exists path | Check if file exists | Read access |
File.size path | Get file size in bytes | Read access |
Directory Operations
| Function | Description | Requires |
|---|---|---|
Dir.list path | List directory contents | Read access |
Dir.create path | Create directory | Write access |
Dir.delete path | Delete empty directory | Write access |
Dir.exists path | Check if directory exists | Read access |
Always Allowed
These operations work regardless of IO settings:
| Function | Description |
|---|---|
print value | Print to stdout (no newline) |
println value | Print to stdout with newline |
readLine | Read line from stdin |
readLine prompt | Print prompt, read line from stdin |
Compile-Time Security Checks
When a security-gated module is disabled, calling its restricted functions produces a compile-time error instead of a runtime error. The compiler checks the environment variable at compilation time and rejects calls to disabled functions before any code runs.
This applies to:
- IO — 18 gated file system functions (e.g.,
IO.readFile,IO.writeFile) - Http —
Http.send - DataFrame — file I/O functions (
readCsv,readJson,readParquet,writeCsv,writeJson,readDta,writeDta) - DateTime — all functions (controlled via
KEEL_DATETIME_DISABLED)
Always-allowed functions (e.g., IO.println, Http.get, DataFrame.select) are unaffected.
Error messages include actionable hints:
Error: IO file operations are disabled (set KEEL_IO_DISABLED=0 to enable)
Hint: Set KEEL_IO_DISABLED=0 to enable IO operations.
Note: Security controls can be configured via environment variables.
Runtime checks remain as defense-in-depth.
Error Messages
When IO operations are denied, Keel provides clear error messages:
IO Error: File system access is disabled.
Set KEEL_IO_DISABLED=0 to enable file operations.
Attempted operation: File.read "/etc/passwd"
IO Error: Write operations are disabled (read-only mode).
Unset KEEL_IO_READ_ONLY to enable write operations.
Attempted operation: File.write "/tmp/output.txt"
IO Error: Path is outside sandbox.
Sandbox: /app/data
Attempted: /etc/passwd
Attempted operation: File.read "/etc/passwd"
HTTP Network Security
HTTP requests via the Http module are disabled by default. This prevents untrusted code from making network calls.
KEEL_HTTP_DISABLED
Controls whether HTTP requests are enabled.
| Value | Effect |
|---|---|
| (unset) | HTTP disabled (default) |
1 or true | HTTP disabled |
0 or false | HTTP enabled |
KEEL_HTTP_ALLOWED_HOSTS
When HTTP is enabled, restricts requests to specific domains. Requests to other hosts are denied.
| Value | Effect |
|---|---|
| (unset) | All hosts allowed (when enabled) |
host1,host2 | Only listed hosts allowed |
HTTP Security Examples
# Enable HTTP requests
KEEL_HTTP_DISABLED=0 keel run api-client.kl
# Allow only specific API hosts
KEEL_HTTP_DISABLED=0 KEEL_HTTP_ALLOWED_HOSTS=api.example.com,cdn.example.com keel run client.kl
HTTP Operations
| Operation | Disabled | Enabled | Enabled + Host Allowlist |
|---|---|---|---|
Http.send (any method) | Denied | Allowed | Allowed (listed hosts only) |
All request construction functions (Http.get, Http.post, Http.withHeader, etc.) are always allowed because they are pure — only Http.send performs the actual network call.
HTTP Error Messages
When HTTP is disabled:
HTTP Error: HTTP requests are disabled.
Set KEEL_HTTP_DISABLED=0 to enable HTTP requests.
When a host is not in the allowlist:
HTTP Error: Host not allowed: api.blocked.com
Allowed hosts: api.example.com, cdn.example.com
Set KEEL_HTTP_ALLOWED_HOSTS to configure allowed hosts.
DataFrame Security
The DataFrame module provides file I/O functions (readCsv, readJson, readParquet, readDta, writeCsv, writeJson, writeParquet, writeDta) that have their own security controls, separate from the IO module.
KEEL_DATAFRAME_DISABLED
Controls whether DataFrame file operations are enabled.
| Value | Effect |
|---|---|
| (unset) | DataFrame operations enabled (default) |
1 or true | DataFrame file I/O disabled |
0 or false | DataFrame operations enabled |
KEEL_DATAFRAME_SANDBOX
Restricts DataFrame file operations to a specific directory.
| Value | Effect |
|---|---|
| (unset) | No path restrictions |
/path/to/dir | All DataFrame file I/O restricted to this directory |
KEEL_DATAFRAME_MAX_ROWS
Limits the number of rows loaded from files, preventing memory exhaustion from large datasets.
| Value | Effect |
|---|---|
| (unset) | No row limit |
10000 | Load at most 10,000 rows |
DataFrame Security Examples
# Sandbox DataFrame to a data directory
KEEL_DATAFRAME_SANDBOX=/data keel run analysis.kl
# Limit rows to prevent memory issues with large files
KEEL_DATAFRAME_MAX_ROWS=100000 keel run analysis.kl
# Disable DataFrame file I/O for untrusted code
KEEL_DATAFRAME_DISABLED=1 keel run untrusted.kl
# Combine with IO controls
KEEL_IO_DISABLED=0 KEEL_IO_READ_ONLY=1 KEEL_DATAFRAME_SANDBOX=/data keel run analysis.kl
DataFrame Operations
| Operation | Disabled | Enabled | Sandboxed |
|---|---|---|---|
DataFrame.readCsv | Denied | Allowed | Allowed (in sandbox) |
DataFrame.readJson | Denied | Allowed | Allowed (in sandbox) |
DataFrame.readParquet | Denied | Allowed | Allowed (in sandbox) |
DataFrame.readDta | Denied | Allowed | Allowed (in sandbox) |
DataFrame.writeCsv | Denied | Allowed | Allowed (in sandbox) |
DataFrame.writeJson | Denied | Allowed | Allowed (in sandbox) |
DataFrame.writeParquet | Denied | Allowed | Allowed (in sandbox) |
DataFrame.writeDta | Denied | Allowed | Allowed (in sandbox) |
DataFrame.select, filter*, etc. | Allowed | Allowed | Allowed |
All in-memory DataFrame operations (column ops, row ops, filters, aggregation, joins) are always allowed because they operate on data already in memory.
DateTime Security
The DateTime module provides date and time operations including DateTime.now() which accesses the system clock. All DateTime operations can be disabled when system time access is sensitive.
KEEL_DATETIME_DISABLED
Controls whether DateTime operations are enabled.
| Value | Effect |
|---|---|
| (unset) | DateTime operations enabled (default) |
1 or true | DateTime operations disabled |
0 or false | DateTime operations enabled |
DateTime Security Examples
# Disable DateTime for sandboxed/reproducible environments
KEEL_DATETIME_DISABLED=1 keel run deterministic-test.kl
# Enable DateTime for time-aware scripts
KEEL_DATETIME_DISABLED=0 keel run time-based-script.kl
DateTime Operations
| Operation | Disabled | Enabled |
|---|---|---|
| All DateTime functions | Denied | Allowed |
When disabled, all 48 DateTime functions (creation, parsing, formatting, manipulation, comparison, etc.) are denied at compile time.
Best Practices
-
Default to disabled — Only enable IO when your script genuinely needs file access
-
Use read-only when possible — If your script only reads files, enable read-only mode to prevent accidental writes
-
Sandbox untrusted code — When running plugins or user-provided scripts, always use a sandbox
-
Prefer explicit paths — When sandboxing, use absolute paths for clarity
-
Combine modes — Use sandbox with read-only for maximum safety:
KEEL_IO_DISABLED=0 KEEL_IO_READ_ONLY=1 KEEL_IO_SANDBOX=/data keel run script.kl -
Document IO requirements — If your script needs IO or HTTP, document the required environment variables
-
Restrict HTTP hosts — When enabling HTTP, use
KEEL_HTTP_ALLOWED_HOSTSto limit which domains your code can reach -
Combine IO and HTTP controls — You can enable HTTP while keeping file IO disabled, or vice versa:
KEEL_HTTP_DISABLED=0 keel run api-only.kl # HTTP enabled, IO still disabled -
Sandbox DataFrame operations — When processing untrusted data files, restrict DataFrame file access to a specific directory:
KEEL_DATAFRAME_SANDBOX=/data keel run analysis.kl -
Limit DataFrame rows — Prevent memory exhaustion from large files with
KEEL_DATAFRAME_MAX_ROWS
See Also
- CLI Reference — Command-line options and environment variables
- Http Module — HTTP client functions
- Json Module — JSON parsing and encoding
- DataFrame Module — Tabular data manipulation
- DateTime Module — Date and time operations
- IO Module — File system operations