Restrict HTTP file artifact inputs

This commit is contained in:
2026-07-04 23:34:44 +00:00
parent 0d45ac6e3c
commit 5c882f26a9
14 changed files with 415 additions and 18 deletions

View File

@@ -83,9 +83,12 @@ Notes:
- `--prompt-dir <dir>`: prompt definition directory.
- `--profile-dir <dir>`: custom profile definition directory.
- `--schema-dir <dir>`: schema base directory for `json_schema` validation.
- `--artifact-root <dir>`: base directory for HTTP `file` input references.
Notes:
- `serve` does not accept runtime model override flags such as `--model` or `--llm-base-url`.
- HTTP `file` input references are rejected unless an artifact root is configured through `server.artifact_root` or `--artifact-root`.
- `--artifact-root` affects only `serve`; `run` and `render` file input paths are unchanged.
## Input And Variable Syntax

View File

@@ -34,6 +34,7 @@ schema_dir: /opt/scriptorium/schemas
server:
addr: 127.0.0.1:8080
artifact_root: /var/lib/scriptorium/artifacts
defaults:
render_format: text
@@ -47,12 +48,14 @@ Top-level fields:
- `profile_dir` (optional): default custom profile definition directory.
- `schema_dir` (optional): base directory for schema files used by `json_schema` validation.
- `server.addr` (optional): default listen address for `serve`.
- `server.artifact_root` (optional): base directory for HTTP `file` input references.
- `defaults.render_format` (optional): default `render` output format (`text` or `json`).
Built-in defaults:
- `schema_dir`: `.`
- `server.addr`: `:8080`
- `server.artifact_root`: unset; HTTP `file` input references are rejected until configured.
- `defaults.render_format`: `text`
Validation behavior:
@@ -60,6 +63,15 @@ Validation behavior:
- Config decoding is strict; unknown YAML fields are rejected.
- Raw API key fields are not supported in `config.yml`.
HTTP artifact root behavior:
- `server.artifact_root` applies only to `serve`.
- HTTP `inline` input references work without an artifact root.
- HTTP `file` input references are resolved against `server.artifact_root` and must stay inside it.
- Relative traversal and absolute paths outside the root are rejected.
- Symlinks inside the root are followed by the operating system; do not make the artifact root writable by untrusted users.
- CLI `run` and `render` file inputs keep their normal direct filesystem path behavior.
## Prompt Definition Files
Prompt definitions are YAML files anywhere under `prompt_dir`, including nested subdirectories.
@@ -269,6 +281,9 @@ Rules:
- Invalid generated JSON causes validation status `failed` (not a runtime error).
Supported artifact reference types for request inputs are `file` and `inline`.
For HTTP `serve`, `file` references require `server.artifact_root` and must stay
inside that root. CLI `run` and `render` file inputs are not restricted by
`server.artifact_root`.
## Secrets Handling

View File

@@ -70,6 +70,12 @@ Input reference types currently supported by runtime artifact loading:
- `file`
- `inline`
HTTP `file` references require `server.artifact_root` or `serve --artifact-root`.
Relative file URIs resolve inside that root. Absolute file URIs are accepted
only when they remain inside the root. Requests that escape the root, including
`..` traversal and absolute paths outside the root, return
`400 artifact_not_allowed`. `inline` references do not require an artifact root.
Model override notes:
- Numeric model override fields distinguish omitted values from explicit zero values. For example, omitting `temperature` preserves the selected profile/default value, while `"temperature": 0` explicitly sets the effective temperature to zero.
@@ -194,6 +200,7 @@ Current error mapping (non-exhaustive):
- `400 profile_required`: no explicit `profile_id` and prompt has no `default_profile`
- `400 prompt_load_failed`: prompt definition invalid/unloadable
- `400 profile_load_failed`: profile invalid/unloadable
- `400 artifact_not_allowed`: file input artifact is outside the configured artifact root or file refs are not enabled
- `400 artifact_read_failed`: input artifact loading failed
- `400 prompt_render_failed`: template render failed
- `400 api_key_env_missing`: named API-key environment variable is missing

View File

@@ -85,6 +85,7 @@ Primary app settings consumed by adapters:
- `profile_dir` (optional custom profile source)
- `schema_dir`
- `server.addr`
- `server.artifact_root` (HTTP `serve` file input root)
- `defaults.render_format`
Execution profile/request settings used through runner:
@@ -116,6 +117,10 @@ Artifact refs:
- Supported reference types: `inline`, `file`.
- Unsupported types return `ErrUnsupportedRefType`.
- CLI `run` and `render` use direct filesystem file reads for `file` references.
- HTTP `serve` uses a restricted artifact reader: `inline` references work without a root, while `file` references require `server.artifact_root` or `--artifact-root` and must stay inside that root.
- HTTP file paths are resolved with clean absolute paths and containment checks, not string-prefix checks.
- Symlinks inside the root are followed by the operating system; the configured root must not be writable by untrusted users.
LLM adapter:

View File

@@ -35,6 +35,7 @@ Built-in defaults relevant to operations:
- `schema_dir: .`
- `server.addr: :8080`
- `server.artifact_root`: unset; HTTP `file` input references are rejected until configured
- `defaults.render_format: text`
## Normal CLI Workflow
@@ -75,11 +76,14 @@ Current inbound API behavior:
- Route: `POST /v1/runs`
- JSON request parsing rejects unknown fields.
- Validation content failures still return `200 OK` with `validation.status: "failed"`.
- `inline` input references work without filesystem configuration.
- `file` input references require `server.artifact_root` or `serve --artifact-root`; relative paths resolve inside that root and paths outside it are rejected.
Security caveat:
- `serve` has no built-in authentication or authorization.
- Deploy only behind trusted controls (private network boundary, authenticated reverse proxy, API gateway, or equivalent).
- Keep the HTTP artifact root as narrow as practical and do not make it writable by untrusted users.
## Output, Logs, And Exit Codes