@rebasepro/rls-check 0.16.0 → 0.16.1-canary.g0d7af95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/checks/anonymous-write-allowed.d.ts +1 -1
- package/dist/checks/current-setting-throws.d.ts +1 -1
- package/dist/checks/grant-to-public.d.ts +1 -1
- package/dist/checks/index.d.ts +1 -1
- package/dist/checks/junction-table-unprotected.d.ts +1 -1
- package/dist/checks/matview-bypasses-rls.d.ts +1 -1
- package/dist/checks/policy-always-true.d.ts +1 -1
- package/dist/checks/policy-anonymous-tautology.d.ts +1 -1
- package/dist/checks/policy-role-unreachable.d.ts +1 -1
- package/dist/checks/rls-disabled.d.ts +1 -1
- package/dist/checks/rls-enabled-no-policies.d.ts +1 -1
- package/dist/checks/rls-enabled-not-forced.d.ts +1 -1
- package/dist/checks/security-definer-mutable-search-path.d.ts +1 -1
- package/dist/checks/unqualified-column-in-subquery.d.ts +1 -1
- package/dist/checks/util.d.ts +1 -1
- package/dist/checks/view-bypasses-rls.d.ts +1 -1
- package/dist/cli.d.ts +22 -1
- package/dist/index.d.ts +13 -11
- package/dist/index.es.js +467 -30
- package/dist/index.es.js.map +1 -1
- package/dist/introspect.d.ts +26 -1
- package/dist/redact.d.ts +13 -0
- package/dist/report-html.d.ts +68 -0
- package/dist/report.d.ts +1 -1
- package/dist/types.d.ts +10 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -188,6 +188,9 @@ npx @rebasepro/rls-check [connection-string] [options]
|
|
|
188
188
|
|
|
189
189
|
--json Machine-readable ScanResult on stdout, and nothing else.
|
|
190
190
|
--schema <name> Restrict the scan to a schema. Repeatable or comma-separated.
|
|
191
|
+
--role <name> Treat this role as one an untrusted caller arrives as, in
|
|
192
|
+
addition to anon, authenticated, web_anon and rebase_user.
|
|
193
|
+
Repeatable or comma-separated.
|
|
191
194
|
--fail-on <severity> Exit 1 at or above this severity: info, low, medium, high,
|
|
192
195
|
critical, or none to never fail. Default: high.
|
|
193
196
|
--only <id> Run only these checks. Repeatable or comma-separated.
|
|
@@ -293,6 +296,7 @@ Being clear about this is the point of the tool. It is a **static audit of the c
|
|
|
293
296
|
- **It does not execute queries as other roles.** It never connects as `anon`, never sets a JWT claim, and never tries to read a row it should not be able to read. Everything it reports is inferred from what the catalogs say, not observed.
|
|
294
297
|
- **It cannot prove a policy is correct.** Deciding whether `owner_id = auth.uid()` is the right rule for your application requires knowing your application. `rls-check` can only tell you that certain *shapes* are wrong — a policy that is always true, a view that runs as its owner, a table with RLS switched off.
|
|
295
298
|
- **A clean report is not a security certification.** It means these fourteen checks found nothing. It does not mean your authorization model is sound, your API layer enforces what it should, or your data is safe.
|
|
299
|
+
- **It recognises app roles by name, and yours may not be one of them.** Every check reports a table as exposed only when a role an untrusted caller can arrive as holds privileges on it. Out of the box that means `PUBLIC`, Supabase's `anon` and `authenticated`, PostgREST's `web_anon`, and Rebase's `rebase_user`. If your application connects as `app_user`, `api` or anything else, name it — `--role app_user` — or the checks have nothing to gate on. A scan that finds a write-holding role it cannot account for says so in a `Note` rather than printing a clean report.
|
|
296
300
|
- **It does not model your API layer.** Whether a table is actually reachable depends on PostgREST, your server, or your gateway. Findings say "if this table is exposed over an API" when reachability depends on something outside the database — believe that qualifier.
|
|
297
301
|
- **It does not see what your connection sees.** Almost every connection string handed to a tool like this belongs to a superuser or a table owner, which RLS cannot constrain. That is what lets it read the true catalog; it also means the findings describe what *other* roles get. The report says so, prominently, every time it applies.
|
|
298
302
|
- **Heuristic checks produce false positives by design.** Junction-table inference and unqualified-column detection match a shape, not a proof. They are reported in a separate section for exactly that reason.
|
package/dist/checks/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* is not, which is why the list is ordered by severity rather than alphabetically
|
|
7
7
|
* — it is read by humans deciding what to look at first.
|
|
8
8
|
*/
|
|
9
|
-
import type { Check, DbSnapshot, Finding } from "../types";
|
|
9
|
+
import type { Check, DbSnapshot, Finding } from "../types.js";
|
|
10
10
|
export declare const CHECKS: Check[];
|
|
11
11
|
export interface RunOptions {
|
|
12
12
|
/** Run only these check ids. */
|
package/dist/checks/util.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* noise, and noise is what gets a tool like this uninstalled — so the helpers
|
|
7
7
|
* below err towards "no" whenever the catalog is ambiguous.
|
|
8
8
|
*/
|
|
9
|
-
import type { DbGrant, DbPolicy, DbRelation, DbSnapshot, Finding, Severity } from "../types";
|
|
9
|
+
import type { DbGrant, DbPolicy, DbRelation, DbSnapshot, Finding, Severity } from "../types.js";
|
|
10
10
|
export declare const SEVERITY_ORDER: Severity[];
|
|
11
11
|
export declare const docsFor: (id: string) => string;
|
|
12
12
|
export type Privilege = DbGrant["privileges"][number];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Check, DbSnapshot, DbView } from "../types";
|
|
1
|
+
import type { Check, DbSnapshot, DbView } from "../types.js";
|
|
2
2
|
/** Base relations of `view` that have RLS turned on. */
|
|
3
3
|
export declare function protectedBaseTables(snapshot: DbSnapshot, view: DbView): string[];
|
|
4
4
|
/**
|
package/dist/cli.d.ts
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* could have come from `pg`, Node or the user goes through `redactSecrets`
|
|
19
19
|
* on its way out.
|
|
20
20
|
*/
|
|
21
|
-
import type { ScanResult, Severity } from "./types";
|
|
21
|
+
import type { ScanResult, Severity } from "./types.js";
|
|
22
22
|
/** Clean, or nothing at or above `--fail-on`. */
|
|
23
23
|
export declare const EXIT_OK = 0;
|
|
24
24
|
/** Findings at or above `--fail-on`. */
|
|
@@ -29,6 +29,12 @@ export interface ScanOptions {
|
|
|
29
29
|
connectionString: string;
|
|
30
30
|
/** Restrict to these schemas. Empty or omitted means "every user schema". */
|
|
31
31
|
schemas?: string[];
|
|
32
|
+
/**
|
|
33
|
+
* Additional roles an untrusted caller can arrive as, on top of the names
|
|
34
|
+
* this tool recognises. Needed by any stack whose app role is not called
|
|
35
|
+
* `anon`, `authenticated`, `web_anon` or `rebase_user`.
|
|
36
|
+
*/
|
|
37
|
+
roles?: string[];
|
|
32
38
|
/** Run only these check ids. */
|
|
33
39
|
only?: string[];
|
|
34
40
|
/** Skip these check ids. */
|
|
@@ -75,7 +81,17 @@ export declare function exitCodeFor(result: ScanResult, failOn: Severity | "none
|
|
|
75
81
|
export interface CliOptions {
|
|
76
82
|
connectionString: string | null;
|
|
77
83
|
json: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* `--html <path>`: also write a self-contained HTML report there.
|
|
86
|
+
*
|
|
87
|
+
* "Also", not "instead": the terminal output is what a CI log keeps, and
|
|
88
|
+
* the file is what gets forwarded to whoever owns the database. Making the
|
|
89
|
+
* flag replace stdout would trade one audience for the other.
|
|
90
|
+
*/
|
|
91
|
+
html: string | null;
|
|
78
92
|
schemas: string[];
|
|
93
|
+
/** Extra roles to treat as reachable by an untrusted caller. */
|
|
94
|
+
roles: string[];
|
|
79
95
|
failOn: Severity | "none";
|
|
80
96
|
skip: string[];
|
|
81
97
|
only: string[];
|
|
@@ -138,6 +154,11 @@ export declare function resolveVersion(): string;
|
|
|
138
154
|
export interface CliIo {
|
|
139
155
|
stdout(text: string): void;
|
|
140
156
|
stderr(text: string): void;
|
|
157
|
+
/**
|
|
158
|
+
* Write a file, for `--html`. Injected rather than imported so the CLI
|
|
159
|
+
* tests can exercise the whole path without touching a disk.
|
|
160
|
+
*/
|
|
161
|
+
writeFile?(path: string, contents: string): void;
|
|
141
162
|
env: NodeJS.ProcessEnv;
|
|
142
163
|
cwd: string;
|
|
143
164
|
/** Whether stdout is a terminal; drives colour when nothing else decides. */
|
package/dist/index.d.ts
CHANGED
|
@@ -16,14 +16,16 @@
|
|
|
16
16
|
* at production databases by people who have never heard of us, and the install
|
|
17
17
|
* has to be something they can read in full before they run it.
|
|
18
18
|
*/
|
|
19
|
-
export { runCli, scan, selectCheckIds, EXIT_OK, EXIT_FINDINGS, EXIT_ERROR } from "./cli";
|
|
20
|
-
export type { ScanOptions, CliIo, CliOptions } from "./cli";
|
|
21
|
-
export { introspect } from "./introspect";
|
|
22
|
-
export type { ConnectOptions } from "./introspect";
|
|
23
|
-
export { CHECKS, runChecks } from "./checks";
|
|
24
|
-
export { renderReport, renderJson, renderCheckCatalog, severityRank, maxSeverity, exceedsThreshold, formatTarget } from "./report";
|
|
25
|
-
export type { RenderOptions } from "./report";
|
|
26
|
-
export {
|
|
27
|
-
export type {
|
|
28
|
-
export {
|
|
29
|
-
export type {
|
|
19
|
+
export { runCli, scan, selectCheckIds, EXIT_OK, EXIT_FINDINGS, EXIT_ERROR } from "./cli.js";
|
|
20
|
+
export type { ScanOptions, CliIo, CliOptions } from "./cli.js";
|
|
21
|
+
export { introspect } from "./introspect.js";
|
|
22
|
+
export type { ConnectOptions } from "./introspect.js";
|
|
23
|
+
export { CHECKS, runChecks } from "./checks/index.js";
|
|
24
|
+
export { renderReport, renderJson, renderCheckCatalog, severityRank, maxSeverity, exceedsThreshold, formatTarget } from "./report.js";
|
|
25
|
+
export type { RenderOptions } from "./report.js";
|
|
26
|
+
export { renderHtml, escapeHtml } from "./report-html.js";
|
|
27
|
+
export type { HtmlRenderOptions } from "./report-html.js";
|
|
28
|
+
export { redactConnectionString, redactSecrets, parseConnectionString, formatEndpoint } from "./redact.js";
|
|
29
|
+
export type { ConnectionTarget } from "./redact.js";
|
|
30
|
+
export { SEVERITIES } from "./types.js";
|
|
31
|
+
export type { Check, DbColumn, DbForeignKey, DbGrant, DbPolicy, DbRelation, DbRole, DbRoutine, DbSnapshot, DbView, Finding, FindingTarget, PolicyCommand, PgRelationKind, ScanResult, Severity } from "./types.js";
|