Skip to content

Commit 42d774b

Browse files
committed
Document security policy and threat model
1 parent 8b9d6a0 commit 42d774b

1 file changed

Lines changed: 143 additions & 3 deletions

File tree

SECURITY.md

Lines changed: 143 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,146 @@
22

33
## Reporting a Vulnerability
44

5-
If you find a critical security vulnerability in this repo, you can report it directly by
6-
email to the main maintainer on `contact@ophir.dev`.
7-
This will allow publishing a new safe version before the vulnerability starts being exploited.
5+
Please report suspected SQLPage vulnerabilities privately to
6+
`contact@ophir.dev`.
7+
8+
Include the SQLPage version or commit, database backend, relevant
9+
configuration, minimal SQL file if possible, and the exact attacker-controlled
10+
input. Do not open a public issue for a non-public vulnerability.
11+
12+
## Threat Model
13+
14+
SQLPage is a runtime for applications written in SQL. It maps HTTP requests to
15+
SQL files, executes those files on the configured database, and renders the
16+
result. SQLPage is not a sandbox for SQLPage application authors or operators.
17+
18+
### Trusted Control
19+
20+
The following define the application's behavior and are trusted:
21+
22+
- Application files under `web_root`, including SQL files and static assets.
23+
- Application files stored in the optional `sqlpage_files` table.
24+
- SQLPage configuration, command-line arguments, environment variables, and
25+
`.env` files.
26+
- Templates, migrations, and connection-management SQL in the configuration
27+
directory.
28+
- Database behavior and access: roles, permissions, schema, extensions,
29+
triggers, stored procedures, views, and migrations.
30+
- Anyone or anything that can modify one of the above.
31+
32+
Control of trusted inputs is control of the SQLPage application. If an attacker
33+
can edit `sqlpage.json`, change `web_root`, weaken OIDC path rules, enable
34+
dangerous Markdown options, enable `allow_exec`, alter templates, or write SQL
35+
into `sqlpage_files`, that is outside SQLPage's vulnerability boundary unless
36+
SQLPage itself granted that access to an untrusted actor.
37+
38+
### Untrusted Data
39+
40+
The following are untrusted data by default:
41+
42+
- HTTP paths, query strings, form fields, request bodies, and multipart uploads.
43+
- Uploaded filenames, MIME types, and file contents.
44+
- HTTP headers, cookies, Basic Auth credentials, and unauthenticated OIDC
45+
callback parameters.
46+
- Responses from remote servers contacted with `sqlpage.fetch` or
47+
`sqlpage.fetch_with_meta`.
48+
- Values returned by database queries, except when SQLPage is loading
49+
application files from `sqlpage_files`.
50+
51+
Database contents are data, not trust. A researcher should not have to prove
52+
which table values are user-generated. SQLPage must handle database values as
53+
untrusted unless trusted SQL places them in a documented control position.
54+
55+
Some result columns are control positions: SQLPage treats their values as
56+
instructions, not ordinary display data. These include component names,
57+
`dynamic` component properties, HTTP headers, redirects, cookies, downloads,
58+
file paths passed to file functions or `run_sql`, URLs passed to `fetch`, raw
59+
HTML, unsafe Markdown, and `exec` command names or arguments. If trusted SQL
60+
puts untrusted data in a control position, the resulting behavior is the
61+
application's responsibility.
62+
63+
## In Scope
64+
65+
Please report cases where SQLPage itself lets untrusted data gain a capability
66+
that should require trusted control. Examples:
67+
68+
- An HTTP request can execute attacker-chosen SQL on the configured database
69+
without trusted SQL explicitly exposing that behavior.
70+
- SQLPage parameter handling turns `$name`, `:name`, or `?name` into executable
71+
SQL instead of a bound database value.
72+
- HTTP routing, path decoding, static file serving, caching, `run_sql`, or file
73+
functions expose host files that trusted SQL or configuration did not choose
74+
to expose.
75+
- Reserved private files, including the `sqlpage/` prefix, dotfiles,
76+
templates, and configuration, are reachable over HTTP.
77+
- `allow_exec` is false, but an attacker can execute a local command through
78+
SQLPage.
79+
- Built-in OIDC handling accepts forged, expired, wrong-issuer,
80+
wrong-audience, wrong-nonce, or wrong-signature tokens, or applies configured
81+
public/protected path rules incorrectly.
82+
- Default-safe rendering or safe Markdown executes browser script from
83+
untrusted data.
84+
- SQLPage-generated production error responses expose source code, stack
85+
traces, SQL text, parameters, environment values, or configuration values.
86+
- Upload handling allows path traversal, overwrite of unintended files, or file
87+
disclosure without trusted SQL selecting that behavior.
88+
- Official SQLPage documentation or examples recommend placing untrusted data in
89+
a control position without validation.
90+
91+
## Out of Scope
92+
93+
The following are usually application or deployment vulnerabilities, not
94+
SQLPage vulnerabilities:
95+
96+
- A trusted SQL file omits authentication or authorization checks.
97+
- Trusted SQL, a stored procedure, trigger, view, or extension builds and
98+
executes SQL from untrusted data.
99+
- Trusted SQL selects untrusted data into a control position such as
100+
`component`, `dynamic.properties`, a redirect target, header value, file path,
101+
`run_sql` target, `fetch` URL, raw HTML, unsafe Markdown, or `exec` argument.
102+
- Trusted SQL intentionally reads a host file, including an absolute path, and
103+
returns it to a client.
104+
- An operator intentionally changes configuration to expose files, trust a
105+
different database, make an OIDC path public, weaken CSP, enable dangerous
106+
Markdown options, load SQLite extensions, or enable `allow_exec`.
107+
- An attacker can modify SQL files, templates, configuration, environment
108+
variables, migrations, database code, or `sqlpage_files`.
109+
- The configured database role has broader permissions than the application
110+
needs.
111+
- A SQLPage application is publicly reachable because no authentication was
112+
configured.
113+
- Trusted SQL asks SQLPage or the database to perform expensive work.
114+
115+
These may still be serious and should be fixed in the affected application,
116+
deployment, or documentation.
117+
118+
## Boundary Examples
119+
120+
Report: `/x.sql?sort=...` causes SQLPage to execute attacker-chosen SQL because
121+
SQLPage rewrote a parameter incorrectly.
122+
123+
Do not report as SQLPage: `x.sql` passes `sort` to a stored procedure that
124+
concatenates it into dynamic SQL.
125+
126+
Report: a normal table cell containing `<script>` executes script in the
127+
browser when rendered by a default-safe component.
128+
129+
Do not report as SQLPage: trusted SQL selects that value as `html`,
130+
`unsafe_contents_md`, `component`, or `dynamic.properties`.
131+
132+
Report: `/..%2F..%2Fetc%2Fpasswd` or `/sqlpage/sqlpage.json` is served directly
133+
by SQLPage.
134+
135+
Do not report as SQLPage: trusted SQL calls
136+
`sqlpage.read_file_as_text('/etc/passwd')` and renders the result.
137+
138+
Report: an unauthenticated request can write a new SQL file into
139+
`sqlpage_files` through an unintended SQLPage endpoint.
140+
141+
Do not report as SQLPage: an administrator, migration, or intentionally exposed
142+
application page writes SQL into `sqlpage_files`.
143+
144+
Report: official documentation recommends `sqlpage.run_sql($user_input)`.
145+
146+
Do not report as SQLPage: a private application uses
147+
`sqlpage.run_sql($user_input)` despite the documentation warning against it.

0 commit comments

Comments
 (0)