2837 Commits

Author SHA1 Message Date
Ophir LOJKINE 162f996d8b v0.44.1
CI / compile_and_lint (push) Has been cancelled
CI / test (, sqlite, sqlite::memory:) (push) Has been cancelled
CI / test (mssql, mssql, mssql://root:Password123!@127.0.0.1/sqlpage) (push) Has been cancelled
CI / test (mysql, mysql, mysql://root:Password123!@127.0.0.1/sqlpage) (push) Has been cancelled
CI / test (oracle, oracle, Driver=Oracle 21 ODBC driver;Dbq=//127.0.0.1:1521/FREEPDB1;Uid=root;Pwd=Password123!) (push) Has been cancelled
CI / test (postgres, odbc, Driver=PostgreSQL Unicode;Server=127.0.0.1;Port=5432;Database=sqlpage;UID=root;PWD=Password123!, true) (push) Has been cancelled
CI / test (postgres, postgres, postgres://root:Password123!@127.0.0.1/sqlpage) (push) Has been cancelled
CI / windows_test (push) Has been cancelled
CI / playwright (push) Has been cancelled
CI / docker_build (linux/amd64, duckdb) (push) Has been cancelled
CI / docker_build (linux/arm/v7, minimal) (push) Has been cancelled
CI / docker_build (linux/arm64, duckdb) (push) Has been cancelled
CI / docker_build (linux/arm64, minimal) (push) Has been cancelled
CI / docker_build (linux/amd64, minimal) (push) Has been cancelled
CI / hurl_examples (push) Has been cancelled
CI / hurl (${{ matrix.example }}) (push) Has been cancelled
CI / docker_push (duckdb) (push) Has been cancelled
CI / docker_push (minimal) (push) Has been cancelled
Create Release / Build sqlpage binaries (macOS & Windows) (.exe, , windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
Create Release / Build sqlpage binaries (macOS & Windows) (odbc-static, macos-latest, x86_64-apple-darwin) (push) Has been cancelled
Create Release / Build sqlpage binaries (Linux) (push) Has been cancelled
Create Release / Build AWS Lambda Serverless zip image (push) Has been cancelled
Create Release / Create Github Release (push) Has been cancelled
Create Release / Publish to crates.io (push) Has been cancelled
v0.44.1
2026-06-12 00:00:26 +02:00
Ophir LOJKINE d8cb2526de fix(oidc): reject backslash and control chars in relative redirect targets (#1311)
The relative-redirect check accepted /\evil.test (and /<TAB>/evil.test):
the WHATWG URL parser used by the url crate treats \ as / and strips ASCII
tab/newline/CR, so url::Url::join turned these into the external authority
evil.test when building post_logout_redirect_uri. is_safe_relative_redirect now
rejects any backslash or ASCII control character, applied via one shared helper
in verify_logout_params, validate_redirect_url, and sqlpage.oidc_logout_url.
2026-06-11 23:30:49 +02:00
Ophir LOJKINE b893455439 Bind OIDC logout URLs to the requesting session (#1313)
* fix(oidc): bind logout URLs to the current session (forced-logout CSRF)

Logout URLs were signed only over the redirect target and a timestamp, so any
valid, unexpired logout URL would clear whoever's cookies followed it. The
logout signature now also covers the caller's sqlpage_auth cookie, so a logout
URL only logs out the session it was issued for. Generation and verification
select the same cookie (the last of any duplicates, matching how RequestInfo
merges them) so the check stays consistent.

* style: run cargo fmt on the logout cookie test
2026-06-11 15:11:35 +02:00
Ophir LOJKINE 4b487c1acb fix: hide SQL details in production error responses for every output format (#1308)
In production, error responses must not leak the SQL statement, the source
file path, the raw database error, environment values, or configuration, for
ANY output format. In development the full detail is shown, and the full error
is always logged server-side.

This centralizes the dev-vs-production decision in a single place. An internal
error stays a full `anyhow::Error` everywhere; the only place that turns it into
a user-facing representation is `ClientError::new` in `src/webserver/error.rs`,
which is also the only caller of `DevOrProd::is_prod`. Every renderer (HTML,
JSON, NDJSON, SSE, CSV) and the header/pre-body path obtains a `ClientError`
from that one function and only formats it; none of them inspect the
environment. Leaking is therefore impossible by construction: a renderer cannot
emit what it never receives.

The error type, the production message, `get_backtrace_as_strings`, and the
error-component data construction live in `error.rs`; `render.rs` only renders
components and formats a `ClientError`.
2026-06-11 11:56:23 +02:00
Ophir LOJKINE afbe9b1794 fix(oidc): apply protected/public path rules to the percent-decoded path (#1310)
An unauthenticated request could encode a byte of a protected prefix (e.g.
/%70rotected/, which the router decodes to /protected/ and serves) to bypass
oidc_protected_paths. is_public_path now percent-decodes both the request path
and the configured prefixes before the plain string-prefix comparison, so
encoded and plain URLs are classified identically, including when site_prefix
contains percent-encoded characters such as a space. Plain string matching
preserves the documented /public vs /public/ distinction.
2026-06-10 23:00:00 +02:00
Ophir LOJKINE 5548539f8f update-deps 2026-06-10 22:23:59 +02:00
Ophir LOJKINE 441f21cc96 Fix Hurl checksum verification in CI 2026-06-10 18:00:06 +02:00
Ophir LOJKINE a6501464b7 Cache Hurl binary in CI 2026-06-10 17:57:44 +02:00
Ophir LOJKINE fe13e4a1d6 Exclude attacker-planted-cookie attacks from the threat model (#1314)
Attacks that require injecting attacker-chosen cookies into the victim's
browser (e.g. OIDC login CSRF / session fixation via a forged login-flow
-state cookie) are out of scope: SQLPage assumes its origin cookie jar is
writable only by the user agent.
2026-06-10 16:54:41 +02:00
Ophir LOJKINE c37ce26351 Fix Content-Disposition parameter injection via download filenames (#1309)
The csv and download components built the Content-Disposition header by
string-interpolating the user-supplied filename. A filename containing
characters such as ';', '"' or '=' could inject an additional header
parameter (e.g. a second, agent-preferred filename*=...), letting an app
that interpolates untrusted data into the filename smuggle a different
download name past the intended one.

Build the header with actix-web's structured ContentDisposition type so
the filename is always a single, properly quoted/escaped value and cannot
create new parameters.
2026-06-10 16:39:01 +02:00
Ophir LOJKINE d92a7399e2 fix: enforce unprivileged path guard on fresh cache hits (#1307)
Reserved/private SQL files (sqlpage/ prefix, dotfiles, .. traversal,
absolute paths) became directly routable over HTTP while their parsed
form was fresh in sql_file_cache. A trusted page loading such a file via
sqlpage.run_sql(...) loads it with privilege and caches it; a later
direct unprivileged request hit the fresh cache entry before the path
guard ran, returning 200 and executing the private SQL instead of 403.

The unprivileged path validation is extracted into
filesystem::validate_unprivileged_path and now enforced before
consulting the cache in both HTTP routing (AppFileStore::contains) and
the unprivileged FileCache::get_with_privilege path.
2026-06-10 16:37:20 +02:00
Ophir LOJKINE 895096b8e5 docs: warn that static file serving follows symlinks under web_root (#1305)
* docs: warn that static serving follows symlinks under web_root

Operators control web_root contents, so a symlink there is a trusted
deployment artifact. Clarify that SQLPage follows such symlinks during
static file serving, meaning a symlink under web_root pointing to
reserved/private files (sqlpage/ config, dotfiles) or to files outside
web_root would make those targets publicly reachable.

Note added to SECURITY.md (Out of Scope), cross-referenced from the
web_root row in configuration.md and an Unreleased CHANGELOG entry.

* Update web_root description for clarity
2026-06-10 16:26:57 +02:00
Ophir LOJKINE abd60cd8d2 docs: clarify persist_uploaded_file folder is trusted app input (#1306)
Document that the folder/destination_folder argument of
sqlpage.persist_uploaded_file must be chosen by the app author and never
derived from untrusted request data. It is joined directly to the web
root, so a value containing '..' or an absolute path would write the
uploaded file outside the web root. Docs-only clarification of existing
intended behavior; no logic change.
2026-06-10 16:25:59 +02:00
Ophir LOJKINE ada23bc089 update-deps 2026-06-08 14:53:37 +02:00
Ophir LOJKINE 1ffc6d82b8 document select options_source behavior (#1300) 2026-06-08 14:51:33 +02:00
Ophir LOJKINE 96de58788a Document security policy and threat model (#1297) 2026-06-05 21:37:30 +02:00
Ophir LOJKINE 8b9d6a0319 Improve CI Docker cache reuse (#1296)
* Improve CI Docker cache reuse

* Ignore git metadata in Docker builds

* Use BuildKit cache mounts for Cargo Docker builds

* Make Docker dependency layer match real build inputs

* Revert "Make Docker dependency layer match real build inputs"

This reverts commit 3a9372150ed30437c0b7872907a3e03ce1c38f5d.

* Revert "Use BuildKit cache mounts for Cargo Docker builds"

This reverts commit dac2c5264bee72fc287877fcfe15e49c319d99dd.

* Test CI incremental Rust caches

* Remove slow Windows port diagnostic

* Narrow Windows incremental cache

* Reuse Linux test artifacts in CI

* Avoid duplicate Linux test execution in CI

* Isolate Docker cache scopes by recipe

* Warm Docker dependencies for lib target

* Warm Docker dependencies with Cargo config

* Stabilize Docker metadata for cache keys

* Use Git context for Docker builds
2026-06-04 00:20:09 +02:00
Ophir LOJKINE 2b52960f62 update dependencies 2026-06-02 16:02:59 +02:00
Ophir LOJKINE 635650b26a Run example Hurl tests from CI image build 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 9b8a091e60 Strengthen master-detail Hurl flow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 5e6ff73699 Strengthen telemetry Hurl trace checks 2026-06-02 15:56:27 +02:00
Ophir LOJKINE ab714a4ff1 Strengthen CRUD auth Hurl flow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE af0ca82e6d Strengthen user auth Hurl flow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 5f8e769716 Fix todo example SQLite permissions 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 9d76d05540 Add PostGIS and official site Hurl flows 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 35ce87fd54 Add SSO and admin example Hurl flows 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 53ff0bd52c Fix telemetry Hurl compose startup 2026-06-02 15:56:27 +02:00
Ophir LOJKINE d254c8c3ae Fix SSO compose and add database Hurl flows 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 0e6a2d023c Fix Hurl runner rebuilds and Pokemon smoke test 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 4fc8247757 Add remote content cards Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 93d8da560b Add Apache example Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 868f647375 Add nginx example Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE c2c6b75436 Add React custom scripts Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 8bb80d165b Add charts custom components Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE fcba5e6680 Add sending emails Hurl smoke test 2026-06-02 15:56:27 +02:00
Ophir LOJKINE f89b678dfb Use htmlUnescape in splitwise Hurl assertions 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 370583d9d9 Add splitwise Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 5d78aadc04 Add plots tables forms Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 5a68eddafd Add corporate conundrum Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE dc3187aae2 Add many-to-many form Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE eaa5c1724c Add rich text editor Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 75ce7d6ce9 Add simple website Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 2981ff9a40 Add light-dark toggle Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 00b3e1b425 Add tiny Twitter Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 14b4bd6f9b Add multiple-choice Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 530524cd37 Add master-detail Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 7792fdfc24 Add custom form Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 6650f52f6f Add cookie example Hurl workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 9cba64c303 Add telemetry Hurl span workflow 2026-06-02 15:56:27 +02:00
Ophir LOJKINE 2d572615d3 Add variable-fields form Hurl workflow 2026-06-02 15:56:27 +02:00