Esc
Start typing to search...

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:

ModeDescriptionUse Case
Disabled (default)No file system accessRunning untrusted code, sandboxed environments
Read-OnlyCan read files, cannot writeData processing, analysis scripts
SandboxedFull IO within a directoryPlugin systems, isolated workloads

Comparison Table

OperationDisabledRead-OnlySandboxed
File.readDeniedAllowedAllowed (in sandbox)
File.writeDeniedDeniedAllowed (in sandbox)
File.appendDeniedDeniedAllowed (in sandbox)
File.deleteDeniedDeniedAllowed (in sandbox)
File.existsDeniedAllowedAllowed (in sandbox)
Dir.listDeniedAllowedAllowed (in sandbox)
Dir.createDeniedDeniedAllowed (in sandbox)
Dir.deleteDeniedDeniedAllowed (in sandbox)
print / printlnAllowedAllowedAllowed
readLineAllowedAllowedAllowed

Environment Variables

Configure IO access using environment variables:

KEEL_IO_DISABLED

Controls whether file system IO is enabled.

ValueEffect
(unset)IO disabled (default)
1 or trueIO disabled
0 or falseIO enabled

KEEL_IO_READ_ONLY

When IO is enabled, restricts access to read operations only.

ValueEffect
(unset)Full IO access (when enabled)
1 or trueRead-only access
0 or falseFull IO access

KEEL_IO_SANDBOX

Restricts all IO operations to a specific directory. Paths outside the sandbox are denied.

ValueEffect
(unset)No path restrictions
/path/to/dirAll 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

FunctionDescriptionRequires
File.read pathRead file contentsRead access
File.readLines pathRead file as list of linesRead access
File.write path contentWrite content to fileWrite access
File.append path contentAppend content to fileWrite access
File.delete pathDelete a fileWrite access
File.exists pathCheck if file existsRead access
File.size pathGet file size in bytesRead access

Directory Operations

FunctionDescriptionRequires
Dir.list pathList directory contentsRead access
Dir.create pathCreate directoryWrite access
Dir.delete pathDelete empty directoryWrite access
Dir.exists pathCheck if directory existsRead access

Always Allowed

These operations work regardless of IO settings:

FunctionDescription
print valuePrint to stdout (no newline)
println valuePrint to stdout with newline
readLineRead line from stdin
readLine promptPrint 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)
  • HttpHttp.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.

ValueEffect
(unset)HTTP disabled (default)
1 or trueHTTP disabled
0 or falseHTTP enabled

KEEL_HTTP_ALLOWED_HOSTS

When HTTP is enabled, restricts requests to specific domains. Requests to other hosts are denied.

ValueEffect
(unset)All hosts allowed (when enabled)
host1,host2Only 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

OperationDisabledEnabledEnabled + Host Allowlist
Http.send (any method)DeniedAllowedAllowed (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.

ValueEffect
(unset)DataFrame operations enabled (default)
1 or trueDataFrame file I/O disabled
0 or falseDataFrame operations enabled

KEEL_DATAFRAME_SANDBOX

Restricts DataFrame file operations to a specific directory.

ValueEffect
(unset)No path restrictions
/path/to/dirAll 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.

ValueEffect
(unset)No row limit
10000Load 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

OperationDisabledEnabledSandboxed
DataFrame.readCsvDeniedAllowedAllowed (in sandbox)
DataFrame.readJsonDeniedAllowedAllowed (in sandbox)
DataFrame.readParquetDeniedAllowedAllowed (in sandbox)
DataFrame.readDtaDeniedAllowedAllowed (in sandbox)
DataFrame.writeCsvDeniedAllowedAllowed (in sandbox)
DataFrame.writeJsonDeniedAllowedAllowed (in sandbox)
DataFrame.writeParquetDeniedAllowedAllowed (in sandbox)
DataFrame.writeDtaDeniedAllowedAllowed (in sandbox)
DataFrame.select, filter*, etc.AllowedAllowedAllowed

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.

ValueEffect
(unset)DateTime operations enabled (default)
1 or trueDateTime operations disabled
0 or falseDateTime 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

OperationDisabledEnabled
All DateTime functionsDeniedAllowed

When disabled, all 48 DateTime functions (creation, parsing, formatting, manipulation, comparison, etc.) are denied at compile time.

Best Practices

  1. Default to disabled — Only enable IO when your script genuinely needs file access

  2. Use read-only when possible — If your script only reads files, enable read-only mode to prevent accidental writes

  3. Sandbox untrusted code — When running plugins or user-provided scripts, always use a sandbox

  4. Prefer explicit paths — When sandboxing, use absolute paths for clarity

  5. 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
    
  6. Document IO requirements — If your script needs IO or HTTP, document the required environment variables

  7. Restrict HTTP hosts — When enabling HTTP, use KEEL_HTTP_ALLOWED_HOSTS to limit which domains your code can reach

  8. 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
    
  9. Sandbox DataFrame operations — When processing untrusted data files, restrict DataFrame file access to a specific directory:

    KEEL_DATAFRAME_SANDBOX=/data keel run analysis.kl
    
  10. Limit DataFrame rows — Prevent memory exhaustion from large files with KEEL_DATAFRAME_MAX_ROWS

See Also