Skip to content

Commit 537d248

Browse files
committed
Keep security policy out of native driver PR
1 parent 29b422e commit 537d248

1 file changed

Lines changed: 174 additions & 3 deletions

File tree

SECURITY.md

Lines changed: 174 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,177 @@
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, a 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 Inputs
19+
20+
SQLPage trusts the application and deployment:
21+
22+
- application files under `web_root`;
23+
- application files stored in the optional `sqlpage_files` table;
24+
- configuration, command-line arguments, environment variables, and `.env`
25+
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`, alter templates, change OIDC path rules, enable
34+
dangerous Markdown options, enable `allow_exec`, or write SQL into
35+
`sqlpage_files`, that is outside SQLPage's vulnerability boundary unless
36+
SQLPage itself granted that access to an untrusted actor.
37+
38+
### Untrusted Inputs
39+
40+
SQLPage does not trust remote inputs:
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+
49+
Database row values are not classified globally as trusted or untrusted.
50+
SQLPage cannot know whether a row came from an administrator-maintained table,
51+
user-generated content, a trigger, or a third-party import. The security
52+
boundary depends on where trusted SQL places the value.
53+
54+
### Data Positions and Instruction Positions
55+
56+
Trusted SQL chooses whether a value is ordinary data or an instruction to
57+
SQLPage.
58+
59+
Data positions are values SQLPage should render, serialize, encode, or pass as
60+
bound database parameters without giving them extra authority. Examples include
61+
ordinary table cells, text fields, JSON response data, CSV cells, and safe
62+
Markdown.
63+
64+
Instruction positions are values SQLPage intentionally treats as application
65+
instructions or capability arguments. Examples include:
66+
67+
- component names;
68+
- `dynamic` component properties;
69+
- response status codes, headers, redirects, cookies, and downloads;
70+
- file paths passed to `run_sql`, `read_file_as_text`, or
71+
`read_file_as_data_url`;
72+
- URLs and request options passed to `fetch` or `fetch_with_meta`;
73+
- raw HTML and unsafe Markdown;
74+
- command names and arguments passed to `exec` when `allow_exec` is enabled.
75+
76+
Placing a database value in an instruction position is an application decision.
77+
For example, `select sqlpage.read_file_as_text(f) from trusted_table` is allowed
78+
by design. If someone who can modify `trusted_table` can read arbitrary files,
79+
that is a problem in the application or database permissions, not SQLPage.
80+
81+
SQLPage's responsibility is to enforce the documented meaning and guardrails of
82+
each position: data positions must not become instructions, instruction
83+
positions must not bypass their documented checks, and malformed values must not
84+
crash SQLPage or escape into unrelated capabilities.
85+
86+
## In Scope
87+
88+
Please report cases where SQLPage itself crosses that boundary. Examples:
89+
90+
- An HTTP request can execute attacker-chosen SQL without trusted SQL explicitly
91+
exposing that behavior.
92+
- SQLPage parameter handling turns `$name`, `:name`, or `?name` into executable
93+
SQL instead of a bound database value.
94+
- A value in a data position causes SQL execution, command execution, host file
95+
access, response-header injection, unsafe HTML execution, or another
96+
instruction-position effect.
97+
- A database value in any position reliably crashes or panics SQLPage instead
98+
of producing a response or application-level error.
99+
- HTTP routing, path decoding, static file serving, caching, `run_sql`, or file
100+
functions expose host files that trusted SQL or configuration did not select.
101+
- Reserved private files, including the `sqlpage/` prefix, dotfiles,
102+
templates, and configuration, are reachable over HTTP.
103+
- `allow_exec` is false, but an attacker can execute a local command through
104+
SQLPage.
105+
- Built-in OIDC handling accepts forged, expired, wrong-issuer,
106+
wrong-audience, wrong-nonce, or wrong-signature tokens, or applies configured
107+
public/protected path rules incorrectly.
108+
- Default-safe rendering or safe Markdown executes browser script.
109+
- SQLPage-generated production error responses expose source code, stack
110+
traces, SQL text, parameters, environment values, or configuration values.
111+
- Upload handling allows path traversal, overwrite of unintended files, or file
112+
disclosure without trusted SQL selecting that behavior.
113+
- Official SQLPage documentation or examples recommend placing untrusted remote
114+
input into an instruction position without validation.
115+
116+
## Out of Scope
117+
118+
The following are usually application or deployment vulnerabilities, not
119+
SQLPage vulnerabilities:
120+
121+
- Trusted SQL omits authentication or authorization checks.
122+
- Trusted SQL, a stored procedure, trigger, view, or extension builds and
123+
executes SQL from untrusted data.
124+
- Trusted SQL selects a value into an instruction position such as `component`,
125+
`dynamic.properties`, a redirect target, header value, file path, `run_sql`
126+
target, `fetch` URL, raw HTML, unsafe Markdown, or `exec` argument.
127+
- Trusted SQL intentionally reads a host file, including an absolute path, and
128+
returns it to a client.
129+
- An operator intentionally changes configuration to expose files, trust a
130+
different database, make an OIDC path public, weaken CSP, enable dangerous
131+
Markdown options, load SQLite extensions, or enable `allow_exec`.
132+
- An attacker can modify SQL files, templates, configuration, environment
133+
variables, migrations, database code, or `sqlpage_files`.
134+
- The configured database role has broader permissions than the application
135+
needs.
136+
- A SQLPage application is publicly reachable because no authentication was
137+
configured.
138+
- Trusted SQL asks SQLPage or the database to perform expensive work.
139+
140+
These may still be serious and should be fixed in the affected application,
141+
deployment, or documentation.
142+
143+
## Boundary Examples
144+
145+
Report: `/x.sql?sort=...` causes SQLPage to execute attacker-chosen SQL because
146+
SQLPage rewrote a parameter incorrectly.
147+
148+
Do not report as SQLPage: `x.sql` passes `sort` to a stored procedure that
149+
concatenates it into dynamic SQL.
150+
151+
Report: a normal table cell containing `<script>` executes script in the
152+
browser when rendered by a default-safe component.
153+
154+
Do not report as SQLPage: trusted SQL selects that value as `html`,
155+
`unsafe_contents_md`, `component`, or `dynamic.properties`.
156+
157+
Report: a specific string returned by the database in a text column panics the
158+
SQLPage process.
159+
160+
Do not report as SQLPage: trusted SQL passes that string as the filename
161+
argument to `sqlpage.read_file_as_text`.
162+
163+
Report: `/..%2F..%2Fetc%2Fpasswd` or `/sqlpage/sqlpage.json` is served directly
164+
by SQLPage.
165+
166+
Do not report as SQLPage: trusted SQL calls
167+
`sqlpage.read_file_as_text('/etc/passwd')` and renders the result.
168+
169+
Report: an unauthenticated request can write a new SQL file into
170+
`sqlpage_files` through an unintended SQLPage endpoint.
171+
172+
Do not report as SQLPage: an administrator, migration, or intentionally exposed
173+
application page writes SQL into `sqlpage_files`.
174+
175+
Report: official documentation recommends `sqlpage.run_sql($user_input)`.
176+
177+
Do not report as SQLPage: a private application uses
178+
`sqlpage.run_sql($user_input)` despite the documentation warning against it.

0 commit comments

Comments
 (0)