admindb 2.1.1 → 2.3.0
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 +368 -335
- package/dist/app.js +227 -1
- package/dist/auth/config.d.ts +1 -1
- package/dist/auth/config.js +109 -1
- package/dist/auth/crypto.js +98 -1
- package/dist/auth/index.js +21 -1
- package/dist/auth/middleware.js +78 -1
- package/dist/auth/routes.js +64 -1
- package/dist/auth/types.js +7 -1
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.js +309 -1
- package/dist/cli/config.js +118 -1
- package/dist/cli/index.js +20 -1
- package/dist/cli/runner.js +208 -1
- package/dist/cli.js +4 -1
- package/dist/data/chain.d.ts +1 -0
- package/dist/data/chain.js +130 -0
- package/dist/data/datasets.d.ts +1 -1
- package/dist/data/datasets.js +171 -1
- package/dist/data/detector.d.ts +1 -1
- package/dist/data/detector.js +535 -1
- package/dist/data/engine.d.ts +1 -1
- package/dist/data/engine.js +586 -1
- package/dist/data/index.d.ts +1 -1
- package/dist/data/index.js +30 -1
- package/dist/data/prng.d.ts +1 -0
- package/dist/data/prng.js +73 -0
- package/dist/data/registry.d.ts +1 -0
- package/dist/data/registry.js +805 -0
- package/dist/data/schema-graph.d.ts +1 -0
- package/dist/data/schema-graph.js +210 -0
- package/dist/data/strategies.d.ts +1 -1
- package/dist/data/strategies.js +100 -1
- package/dist/data/templates.d.ts +1 -0
- package/dist/data/templates.js +134 -0
- package/dist/data/types.d.ts +1 -1
- package/dist/data/types.js +5 -1
- package/dist/data/validator.d.ts +1 -0
- package/dist/data/validator.js +160 -0
- package/dist/db/database.d.ts +1 -1
- package/dist/db/database.js +472 -1
- package/dist/db/export.d.ts +1 -1
- package/dist/db/export.js +67 -1
- package/dist/db/filters.d.ts +1 -1
- package/dist/db/filters.js +119 -1
- package/dist/db/index.js +24 -1
- package/dist/db/introspection.js +164 -1
- package/dist/db/manager.js +327 -1
- package/dist/db/migrations.js +100 -1
- package/dist/db/postgres.d.ts +1 -1
- package/dist/db/postgres.js +687 -1
- package/dist/db/types.d.ts +1 -1
- package/dist/db/types.js +6 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +52 -1
- package/dist/public/css/app.css +1 -1
- package/dist/public/js/api.js +1 -1
- package/dist/public/js/browse.js +1 -1
- package/dist/public/js/common.js +1 -0
- package/dist/public/js/databases.js +1 -1
- package/dist/public/js/designer.js +1 -1
- package/dist/public/js/forms.js +1 -1
- package/dist/public/js/home.js +1 -0
- package/dist/public/js/inspector.js +1 -1
- package/dist/public/js/query.js +1 -1
- package/dist/public/js/schema.js +1 -1
- package/dist/public/js/seed.js +1 -1
- package/dist/routes/api/erd.d.ts +1 -0
- package/dist/routes/api/erd.js +45 -0
- package/dist/routes/api/helpers.d.ts +1 -1
- package/dist/routes/api/helpers.js +213 -1
- package/dist/routes/api/import-export.js +82 -1
- package/dist/routes/api/index.js +48 -1
- package/dist/routes/api/query.js +74 -1
- package/dist/routes/api/rows.js +358 -1
- package/dist/routes/api/seed.js +167 -1
- package/dist/routes/api/tables.js +216 -1
- package/dist/routes/databases.js +210 -1
- package/dist/routes/index.js +19 -1
- package/dist/routes/pages.js +446 -1
- package/dist/serverless.js +149 -1
- package/dist/sql/classifier.js +24 -1
- package/dist/sql/error-analyzer.d.ts +1 -0
- package/dist/sql/error-analyzer.js +550 -0
- package/dist/sql/generator.d.ts +1 -1
- package/dist/sql/generator.js +245 -1
- package/dist/sql/index.js +18 -1
- package/dist/types/api.d.ts +1 -1
- package/dist/types/api.js +2 -1
- package/dist/utils/colors.js +54 -1
- package/dist/utils/common.d.ts +1 -1
- package/dist/utils/common.js +185 -1
- package/dist/utils/csv.d.ts +1 -1
- package/dist/utils/csv.js +61 -1
- package/dist/utils/datatype.js +167 -1
- package/dist/utils/icons.js +81 -1
- package/dist/utils/index.js +20 -1
- package/dist/utils/logger.js +36 -1
- package/dist/views/layouts/main.hbs +1 -74
- package/dist/views/pages/databases.hbs +1 -233
- package/dist/views/pages/designer.hbs +1 -89
- package/dist/views/pages/erd.hbs +1 -0
- package/dist/views/pages/error.hbs +1 -10
- package/dist/views/pages/form.hbs +1 -59
- package/dist/views/pages/home.hbs +1 -124
- package/dist/views/pages/info.hbs +1 -0
- package/dist/views/pages/login.hbs +1 -98
- package/dist/views/pages/query.hbs +1 -87
- package/dist/views/pages/schema.hbs +1 -298
- package/dist/views/pages/seed-select.hbs +251 -0
- package/dist/views/pages/seed.hbs +273 -167
- package/dist/views/pages/table.hbs +1 -327
- package/dist/views/partials/navbar.hbs +1 -83
- package/dist/views/partials/sidebar.hbs +1 -117
- package/docs/API.md +149 -144
- package/docs/EXAMPLES.md +579 -576
- package/docs/SECURITY.md +265 -265
- package/package.json +79 -78
- package/dist/public/js/icons.js +0 -1
package/docs/SECURITY.md
CHANGED
|
@@ -1,265 +1,265 @@
|
|
|
1
|
-
# AdminDB Security, Authentication & Protection Guide
|
|
2
|
-
|
|
3
|
-
> Comprehensive guide to AdminDB's security architecture, shared responsibility model, native authentication system, filesystem browsing sandboxing, remote PostgreSQL protection, and production deployment safeguards.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 📑 Table of Contents
|
|
8
|
-
|
|
9
|
-
- [🛡️ Security Responsibility Model (Crucial)](#️-security-responsibility-model-crucial)
|
|
10
|
-
- [Native Authentication System](#native-authentication-system)
|
|
11
|
-
- [Default Credentials & Alerts](#default-credentials--alerts)
|
|
12
|
-
- [Cryptographic Password Hashing (`npm run generatehash`)](#cryptographic-password-hashing-npm-run-generatehash)
|
|
13
|
-
- [Configuring Credentials](#configuring-credentials)
|
|
14
|
-
- [Session Tokens & Cookie Security](#session-tokens--cookie-security)
|
|
15
|
-
- [Protecting AdminDB with Your Own Application Auth](#protecting-admindb-with-your-own-application-auth)
|
|
16
|
-
- [Custom Express Middleware (Recommended for Production)](#custom-express-middleware-recommended-for-production)
|
|
17
|
-
- [Reverse Proxy & Gateway Protection (Nginx, Caddy, Cloudflare Zero Trust)](#reverse-proxy--gateway-protection-nginx-caddy-cloudflare-zero-trust)
|
|
18
|
-
- [Manager Mode & Filesystem Browsing Security](#manager-mode--filesystem-browsing-security)
|
|
19
|
-
- [Path Sandboxing (`browseRoot`) & Traversal Prevention](#path-sandboxing-browseroot--traversal-prevention)
|
|
20
|
-
- [Blocked Files & Secret Exclusion](#blocked-files--secret-exclusion)
|
|
21
|
-
- [Disabling File Browsing Completely](#disabling-file-browsing-completely)
|
|
22
|
-
- [Remote PostgreSQL Security](#remote-postgresql-security)
|
|
23
|
-
- [Credential Masking & Memory Sanitation](#credential-masking--memory-sanitation)
|
|
24
|
-
- [Secure JSON Configuration Files (`name.postgres.json`)](#secure-json-configuration-files-namepostgresjson)
|
|
25
|
-
- [Per-Database Read-Only Enforcements](#per-database-read-only-enforcements)
|
|
26
|
-
- [Production Security Checklist](#production-security-checklist)
|
|
27
|
-
- [SQL Safety & Injection Protections](#sql-safety--injection-protections)
|
|
28
|
-
- [Universal Destructive Action Safeguards](#universal-destructive-action-safeguards)
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## 🛡️ Security Responsibility Model (Crucial)
|
|
33
|
-
|
|
34
|
-
> [!WARNING]
|
|
35
|
-
> **IMPORTANT: Native Authentication is Basic Security.**
|
|
36
|
-
> AdminDB's built-in single-user login screen and HTTP basic authentication are intended as **convenience access controls** for local development, trusted private intranets, or single-operator setups.
|
|
37
|
-
>
|
|
38
|
-
> **It is the user's sole responsibility to fully protect AdminDB** when exposing it to untrusted networks, shared environments, or the public internet.
|
|
39
|
-
|
|
40
|
-
For production or team usage, you should **always**:
|
|
41
|
-
1. **Wrap AdminDB with your application's own authentication**: If embedding via Express/Node.js (`createRouter`), apply your organization's robust authentication middleware (e.g. NextAuth, Passport.js, OAuth2/OIDC, JWT verification, or session guards) before the AdminDB router, and disable native auth (`auth: false`).
|
|
42
|
-
2. **Place behind a secure reverse proxy or VPN**: Terminate TLS/HTTPS and enforce IP allowlisting, Cloudflare Zero Trust / Cloudflare Access, AWS Cognito, or Tailscale/WireGuard.
|
|
43
|
-
3. **Use granular database credentials**: Create dedicated database users with least-privilege permissions instead of root `postgres` superuser accounts.
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## Native Authentication System
|
|
48
|
-
|
|
49
|
-
### Default Credentials & Alerts
|
|
50
|
-
|
|
51
|
-
Out of the box, AdminDB includes default credentials to ensure a newly launched server is never exposed completely open:
|
|
52
|
-
|
|
53
|
-
* **Default Username:** `admin`
|
|
54
|
-
* **Default Password:** `admin` *(stored internally via a salted `scrypt` hash)*
|
|
55
|
-
|
|
56
|
-
> [!CAUTION]
|
|
57
|
-
> When running with default credentials, AdminDB displays a prominent warning in your terminal on startup and an alert badge in the web UI. Always generate a custom password for anything beyond local testing.
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
### Cryptographic Password Hashing (`npm run generatehash`)
|
|
62
|
-
|
|
63
|
-
AdminDB uses Node.js's built-in cryptographic `scrypt` algorithm with a unique 16-byte random salt per hash. To generate a secure hash for your custom password:
|
|
64
|
-
|
|
65
|
-
```bash
|
|
66
|
-
npm run generatehash
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
The interactive script prompts:
|
|
70
|
-
```text
|
|
71
|
-
Enter password to hash: [your-strong-password]
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
And outputs a formatted hash:
|
|
75
|
-
```text
|
|
76
|
-
⚡ AdminDB Password Hash Generated
|
|
77
|
-
|
|
78
|
-
➜ Hash: scrypt:8011bcda719a32dd307cbcbad899e963:854657965139a68b14ffb30f6a64a18d8b10197046e720dbf6e2e26fee2c5dcc2b6a8b8aed514c1a2be7d73279481bf780c4cf381b68eea40d4e2a7b58dd24f8
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
You can also pass the password as a command-line argument:
|
|
82
|
-
```bash
|
|
83
|
-
node scripts/generate-hash.mjs "my_strong_password_123"
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
---
|
|
87
|
-
|
|
88
|
-
### Configuring Credentials
|
|
89
|
-
|
|
90
|
-
You can supply the generated hash (or plain-text password) through any of the following methods:
|
|
91
|
-
|
|
92
|
-
#### 1. Environment Variables (`.env`)
|
|
93
|
-
```bash
|
|
94
|
-
export ADMINDB_USERNAME="ops_admin"
|
|
95
|
-
export ADMINDB_PASSWORD="scrypt:8011bcda719a32dd307cbcbad899e963:854657965139a68b14ffb30f6a64a18d8b10197046e720dbf6e2e26fee2c5dcc2b6a8b8aed514c1a2be7d73279481bf780c4cf381b68eea40d4e2a7b58dd24f8"
|
|
96
|
-
export ADMINDB_SECRET="a7f8e92c4b1d6e3f8a0b5c7d9e1f2a3b4c5d6e7f8"
|
|
97
|
-
|
|
98
|
-
npx admindb
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
#### 2. CLI Flags
|
|
102
|
-
```bash
|
|
103
|
-
admindb -u ops_admin -P "scrypt:8011bcda719a32dd307cbcbad899e963:854657965139a68b14ffb30f6a64a18d8b10197046e720dbf6e2e26fee2c5dcc2b6a8b8aed514c1a2be7d73279481bf780c4cf381b68eea40d4e2a7b58dd24f8"
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
#### 3. JSON Configuration File (`name.postgres.json`)
|
|
107
|
-
```json
|
|
108
|
-
{
|
|
109
|
-
"production": "postgresql://postgres:secret@localhost:5432/mydb",
|
|
110
|
-
"auth": {
|
|
111
|
-
"username": "ops_admin",
|
|
112
|
-
"password": "scrypt:8011bcda719a32dd307cbcbad899e963:854657965139a68b14ffb30f6a64a18d8b10197046e720dbf6e2e26fee2c5dcc2b6a8b8aed514c1a2be7d73279481bf780c4cf381b68eea40d4e2a7b58dd24f8"
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
---
|
|
118
|
-
|
|
119
|
-
### Session Tokens & Cookie Security
|
|
120
|
-
|
|
121
|
-
When a user logs in through the web UI:
|
|
122
|
-
1. **Token Generation:** A cryptographic timestamped token is created and signed using `HMAC-SHA256` with your configured `ADMINDB_SECRET`.
|
|
123
|
-
2. **Cookie Security Flags:** The session cookie (`admindb_session`) is set with:
|
|
124
|
-
- `HttpOnly: true` (prevents client JavaScript access & XSS token theft)
|
|
125
|
-
- `SameSite: Lax` (protects against Cross-Site Request Forgery)
|
|
126
|
-
- `Path: /` (or your configured `basePath`)
|
|
127
|
-
3. **Constant-Time Verification:** Password matching and token signature verification use constant-time comparisons (`crypto.timingSafeEqual`) to protect against timing attacks.
|
|
128
|
-
|
|
129
|
-
---
|
|
130
|
-
|
|
131
|
-
## Protecting AdminDB with Your Own Application Auth
|
|
132
|
-
|
|
133
|
-
### Custom Express Middleware (Recommended for Production)
|
|
134
|
-
|
|
135
|
-
When embedding AdminDB in an existing Express / Next.js backend, turn off built-in auth (`auth: false`) and apply your existing session or JWT middleware:
|
|
136
|
-
|
|
137
|
-
```ts
|
|
138
|
-
import express from 'express';
|
|
139
|
-
import { createRouter } from 'admindb';
|
|
140
|
-
|
|
141
|
-
const app = express();
|
|
142
|
-
|
|
143
|
-
// Your enterprise authentication middleware
|
|
144
|
-
function requireAdminRole(req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
145
|
-
if (req.user && req.user.role === 'SUPERADMIN') {
|
|
146
|
-
return next();
|
|
147
|
-
}
|
|
148
|
-
res.status(403).send('Forbidden: AdminDB requires SUPERADMIN privileges');
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
app.use('/admin', requireAdminRole, createRouter({
|
|
152
|
-
connection: process.env.DATABASE_URL,
|
|
153
|
-
basePath: '/admin',
|
|
154
|
-
auth: false, // Turn off built-in login form; rely on requireAdminRole
|
|
155
|
-
}));
|
|
156
|
-
|
|
157
|
-
app.listen(45531);
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
### Reverse Proxy & Gateway Protection (Nginx, Caddy, Cloudflare Zero Trust)
|
|
163
|
-
|
|
164
|
-
If running AdminDB standalone (`npx admindb`), bind to localhost (`HOST=127.0.0.1`) and put a reverse proxy in front:
|
|
165
|
-
|
|
166
|
-
```nginx
|
|
167
|
-
# Nginx reverse proxy with IP allowlist and HTTPS termination
|
|
168
|
-
server {
|
|
169
|
-
listen 443 ssl http2;
|
|
170
|
-
server_name db.yourcompany.internal;
|
|
171
|
-
|
|
172
|
-
ssl_certificate /etc/ssl/certs/app.crt;
|
|
173
|
-
ssl_certificate_key /etc/ssl/certs/app.key;
|
|
174
|
-
|
|
175
|
-
# Restrict to VPN / Office IP range
|
|
176
|
-
allow 10.0.0.0/8;
|
|
177
|
-
allow 192.168.1.0/24;
|
|
178
|
-
deny all;
|
|
179
|
-
|
|
180
|
-
location / {
|
|
181
|
-
proxy_pass http://127.0.0.1:45531;
|
|
182
|
-
proxy_set_header Host $host;
|
|
183
|
-
proxy_set_header X-Real-IP $remote_addr;
|
|
184
|
-
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
185
|
-
proxy_set_header X-Forwarded-Proto $scheme;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
---
|
|
191
|
-
|
|
192
|
-
## Manager Mode & Filesystem Browsing Security
|
|
193
|
-
|
|
194
|
-
In Manager Mode, AdminDB provides an interactive filesystem browser to locate and open SQLite databases on the host. Several defensive measures protect host integrity:
|
|
195
|
-
|
|
196
|
-
### Path Sandboxing (`browseRoot`) & Traversal Prevention
|
|
197
|
-
- **Sandboxed Root (`browseRoot` / `-d <folder>`):** When started with a specific directory or `--browse-root`, browsing is strictly jailed to that folder. Any attempt to navigate upward returns `403 Forbidden`.
|
|
198
|
-
- **Symlink Escape Protection:** All path validations resolve real filesystem symlinks (`realpathSync`), preventing symlink-based jailbreaks.
|
|
199
|
-
- **Null-Byte Injection Blocking:** All inputs containing `\0` null-bytes are rejected immediately.
|
|
200
|
-
|
|
201
|
-
### Blocked Files & Secret Exclusion
|
|
202
|
-
The file browser automatically ignores and conceals sensitive system folders and secrets:
|
|
203
|
-
- Directories: `node_modules`, `.git`, `.svn`, `.hg`, `.aws`, `.ssh`, `System Volume Information`, `$RECYCLE.BIN`.
|
|
204
|
-
- Secret Files: Hidden dotfiles (`.*`), `.env`, `.env.local`, `.env.production`.
|
|
205
|
-
- File Filter: Only recognized database files (`.db`, `.sqlite`, `.sqlite3`) are displayed for opening.
|
|
206
|
-
|
|
207
|
-
### Disabling File Browsing Completely
|
|
208
|
-
When AdminDB is started with explicit database files (`--files`, `name.postgres.json`) or in serverless environments, **filesystem browsing is automatically disabled** (`allowBrowse: false`), eliminating any directory traversal attack surface.
|
|
209
|
-
|
|
210
|
-
---
|
|
211
|
-
|
|
212
|
-
## Remote PostgreSQL Security
|
|
213
|
-
|
|
214
|
-
### Credential Masking & Memory Sanitation
|
|
215
|
-
- When PostgreSQL connection URIs (`postgresql://user:password@host:5432/db`) are registered, credentials are sanitised across the UI, responses, and log messages (`postgresql://user:****@host:5432/db`).
|
|
216
|
-
- Passwords are encrypted in-memory and are never leaked to client browsers.
|
|
217
|
-
|
|
218
|
-
### Secure JSON Configuration Files (`name.postgres.json`)
|
|
219
|
-
To avoid leaking passwords in shell history or process tables (`ps aux`), store database connections in a restricted JSON file:
|
|
220
|
-
|
|
221
|
-
```json
|
|
222
|
-
{
|
|
223
|
-
"production": "postgresql://postgres:secret@prod.internal:5432/prod_db",
|
|
224
|
-
"analytics": "postgresql://postgres:secret@analytics.internal:5432/dw_db"
|
|
225
|
-
}
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
And start AdminDB using the file:
|
|
229
|
-
```bash
|
|
230
|
-
npx admindb name.postgres.json
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
### Per-Database Read-Only Enforcements
|
|
234
|
-
- AdminDB allows marking any PostgreSQL or SQLite database as **Read-only** directly from the UI or configuration (`[ ] Open as Read-only`).
|
|
235
|
-
- In read-only mode, all write statements (`INSERT`, `UPDATE`, `DELETE`, `DROP`, `ALTER`, `CREATE`) and data-mutating APIs are blocked at the engine layer.
|
|
236
|
-
|
|
237
|
-
---
|
|
238
|
-
|
|
239
|
-
## Production Security Checklist
|
|
240
|
-
|
|
241
|
-
- [ ] **Custom Credentials:** Replaced default `admin/admin` with a salted `scrypt` hash (`npm run generatehash`).
|
|
242
|
-
- [ ] **Fixed Session Secret:** Configured `ADMINDB_SECRET` to prevent session invalidation on restart.
|
|
243
|
-
- [ ] **Private Interface:** Bound to `HOST=127.0.0.1` or private subnet.
|
|
244
|
-
- [ ] **HTTPS / TLS:** Terminated SSL via reverse proxy or load balancer.
|
|
245
|
-
- [ ] **Custom Auth Wrapper:** Placed behind application auth middleware when embedded in Express.
|
|
246
|
-
- [ ] **Least Privilege DB Users:** Connected PostgreSQL using dedicated user roles with appropriate table grants.
|
|
247
|
-
- [ ] **Read-Only Where Applicable:** Enabled `--readonly` for auditing and data-viewer personas.
|
|
248
|
-
- [ ] **Jailed Browsing:** Specified `-d /path/to/dbs` or disabled browsing with explicit files.
|
|
249
|
-
|
|
250
|
-
---
|
|
251
|
-
|
|
252
|
-
## SQL Safety & Injection Protections
|
|
253
|
-
|
|
254
|
-
1. **Identifier Quoting:** Identifiers (table names, columns, indexes) are safely double-quoted (`"table_name"`).
|
|
255
|
-
2. **Parameterized Queries:** Queries use native driver parameter placeholders (`?` for SQLite, `$1, $2, ...` for PostgreSQL).
|
|
256
|
-
3. **Safe Preview Modes:** Preview endpoints return raw generated SQL strings for visual inspection without executing against the database.
|
|
257
|
-
4. **Internal Table Protection:** Internal AdminDB state tables (`_saved_queries`) are protected from being dropped, renamed, or mutated.
|
|
258
|
-
|
|
259
|
-
---
|
|
260
|
-
|
|
261
|
-
## Universal Destructive Action Safeguards
|
|
262
|
-
|
|
263
|
-
1. **Interactive Confirmation Barriers (`UI.confirm`):** Prompts with primary key details and impact assessments before single/bulk deletions.
|
|
264
|
-
2. **Type-to-Confirm Input Verification:** Dropping tables and deleting database files requires typing the exact name of the item.
|
|
265
|
-
3. **Transactional Isolation:** Bulk operations and CSV imports run in atomic transactions (`BEGIN ... COMMIT/ROLLBACK`), ensuring zero partial corruption on errors.
|
|
1
|
+
# AdminDB Security, Authentication & Protection Guide
|
|
2
|
+
|
|
3
|
+
> Comprehensive guide to AdminDB's security architecture, shared responsibility model, native authentication system, filesystem browsing sandboxing, remote PostgreSQL protection, and production deployment safeguards.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 📑 Table of Contents
|
|
8
|
+
|
|
9
|
+
- [🛡️ Security Responsibility Model (Crucial)](#️-security-responsibility-model-crucial)
|
|
10
|
+
- [Native Authentication System](#native-authentication-system)
|
|
11
|
+
- [Default Credentials & Alerts](#default-credentials--alerts)
|
|
12
|
+
- [Cryptographic Password Hashing (`npm run generatehash`)](#cryptographic-password-hashing-npm-run-generatehash)
|
|
13
|
+
- [Configuring Credentials](#configuring-credentials)
|
|
14
|
+
- [Session Tokens & Cookie Security](#session-tokens--cookie-security)
|
|
15
|
+
- [Protecting AdminDB with Your Own Application Auth](#protecting-admindb-with-your-own-application-auth)
|
|
16
|
+
- [Custom Express Middleware (Recommended for Production)](#custom-express-middleware-recommended-for-production)
|
|
17
|
+
- [Reverse Proxy & Gateway Protection (Nginx, Caddy, Cloudflare Zero Trust)](#reverse-proxy--gateway-protection-nginx-caddy-cloudflare-zero-trust)
|
|
18
|
+
- [Manager Mode & Filesystem Browsing Security](#manager-mode--filesystem-browsing-security)
|
|
19
|
+
- [Path Sandboxing (`browseRoot`) & Traversal Prevention](#path-sandboxing-browseroot--traversal-prevention)
|
|
20
|
+
- [Blocked Files & Secret Exclusion](#blocked-files--secret-exclusion)
|
|
21
|
+
- [Disabling File Browsing Completely](#disabling-file-browsing-completely)
|
|
22
|
+
- [Remote PostgreSQL Security](#remote-postgresql-security)
|
|
23
|
+
- [Credential Masking & Memory Sanitation](#credential-masking--memory-sanitation)
|
|
24
|
+
- [Secure JSON Configuration Files (`name.postgres.json`)](#secure-json-configuration-files-namepostgresjson)
|
|
25
|
+
- [Per-Database Read-Only Enforcements](#per-database-read-only-enforcements)
|
|
26
|
+
- [Production Security Checklist](#production-security-checklist)
|
|
27
|
+
- [SQL Safety & Injection Protections](#sql-safety--injection-protections)
|
|
28
|
+
- [Universal Destructive Action Safeguards](#universal-destructive-action-safeguards)
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 🛡️ Security Responsibility Model (Crucial)
|
|
33
|
+
|
|
34
|
+
> [!WARNING]
|
|
35
|
+
> **IMPORTANT: Native Authentication is Basic Security.**
|
|
36
|
+
> AdminDB's built-in single-user login screen and HTTP basic authentication are intended as **convenience access controls** for local development, trusted private intranets, or single-operator setups.
|
|
37
|
+
>
|
|
38
|
+
> **It is the user's sole responsibility to fully protect AdminDB** when exposing it to untrusted networks, shared environments, or the public internet.
|
|
39
|
+
|
|
40
|
+
For production or team usage, you should **always**:
|
|
41
|
+
1. **Wrap AdminDB with your application's own authentication**: If embedding via Express/Node.js (`createRouter`), apply your organization's robust authentication middleware (e.g. NextAuth, Passport.js, OAuth2/OIDC, JWT verification, or session guards) before the AdminDB router, and disable native auth (`auth: false`).
|
|
42
|
+
2. **Place behind a secure reverse proxy or VPN**: Terminate TLS/HTTPS and enforce IP allowlisting, Cloudflare Zero Trust / Cloudflare Access, AWS Cognito, or Tailscale/WireGuard.
|
|
43
|
+
3. **Use granular database credentials**: Create dedicated database users with least-privilege permissions instead of root `postgres` superuser accounts.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Native Authentication System
|
|
48
|
+
|
|
49
|
+
### Default Credentials & Alerts
|
|
50
|
+
|
|
51
|
+
Out of the box, AdminDB includes default credentials to ensure a newly launched server is never exposed completely open:
|
|
52
|
+
|
|
53
|
+
* **Default Username:** `admin`
|
|
54
|
+
* **Default Password:** `admin` *(stored internally via a salted `scrypt` hash)*
|
|
55
|
+
|
|
56
|
+
> [!CAUTION]
|
|
57
|
+
> When running with default credentials, AdminDB displays a prominent warning in your terminal on startup and an alert badge in the web UI. Always generate a custom password for anything beyond local testing.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### Cryptographic Password Hashing (`npm run generatehash`)
|
|
62
|
+
|
|
63
|
+
AdminDB uses Node.js's built-in cryptographic `scrypt` algorithm with a unique 16-byte random salt per hash. To generate a secure hash for your custom password:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm run generatehash
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The interactive script prompts:
|
|
70
|
+
```text
|
|
71
|
+
Enter password to hash: [your-strong-password]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
And outputs a formatted hash:
|
|
75
|
+
```text
|
|
76
|
+
⚡ AdminDB Password Hash Generated
|
|
77
|
+
|
|
78
|
+
➜ Hash: scrypt:8011bcda719a32dd307cbcbad899e963:854657965139a68b14ffb30f6a64a18d8b10197046e720dbf6e2e26fee2c5dcc2b6a8b8aed514c1a2be7d73279481bf780c4cf381b68eea40d4e2a7b58dd24f8
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
You can also pass the password as a command-line argument:
|
|
82
|
+
```bash
|
|
83
|
+
node scripts/generate-hash.mjs "my_strong_password_123"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
### Configuring Credentials
|
|
89
|
+
|
|
90
|
+
You can supply the generated hash (or plain-text password) through any of the following methods:
|
|
91
|
+
|
|
92
|
+
#### 1. Environment Variables (`.env`)
|
|
93
|
+
```bash
|
|
94
|
+
export ADMINDB_USERNAME="ops_admin"
|
|
95
|
+
export ADMINDB_PASSWORD="scrypt:8011bcda719a32dd307cbcbad899e963:854657965139a68b14ffb30f6a64a18d8b10197046e720dbf6e2e26fee2c5dcc2b6a8b8aed514c1a2be7d73279481bf780c4cf381b68eea40d4e2a7b58dd24f8"
|
|
96
|
+
export ADMINDB_SECRET="a7f8e92c4b1d6e3f8a0b5c7d9e1f2a3b4c5d6e7f8"
|
|
97
|
+
|
|
98
|
+
npx admindb
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### 2. CLI Flags
|
|
102
|
+
```bash
|
|
103
|
+
admindb -u ops_admin -P "scrypt:8011bcda719a32dd307cbcbad899e963:854657965139a68b14ffb30f6a64a18d8b10197046e720dbf6e2e26fee2c5dcc2b6a8b8aed514c1a2be7d73279481bf780c4cf381b68eea40d4e2a7b58dd24f8"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### 3. JSON Configuration File (`name.postgres.json`)
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"production": "postgresql://postgres:secret@localhost:5432/mydb",
|
|
110
|
+
"auth": {
|
|
111
|
+
"username": "ops_admin",
|
|
112
|
+
"password": "scrypt:8011bcda719a32dd307cbcbad899e963:854657965139a68b14ffb30f6a64a18d8b10197046e720dbf6e2e26fee2c5dcc2b6a8b8aed514c1a2be7d73279481bf780c4cf381b68eea40d4e2a7b58dd24f8"
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
### Session Tokens & Cookie Security
|
|
120
|
+
|
|
121
|
+
When a user logs in through the web UI:
|
|
122
|
+
1. **Token Generation:** A cryptographic timestamped token is created and signed using `HMAC-SHA256` with your configured `ADMINDB_SECRET`.
|
|
123
|
+
2. **Cookie Security Flags:** The session cookie (`admindb_session`) is set with:
|
|
124
|
+
- `HttpOnly: true` (prevents client JavaScript access & XSS token theft)
|
|
125
|
+
- `SameSite: Lax` (protects against Cross-Site Request Forgery)
|
|
126
|
+
- `Path: /` (or your configured `basePath`)
|
|
127
|
+
3. **Constant-Time Verification:** Password matching and token signature verification use constant-time comparisons (`crypto.timingSafeEqual`) to protect against timing attacks.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Protecting AdminDB with Your Own Application Auth
|
|
132
|
+
|
|
133
|
+
### Custom Express Middleware (Recommended for Production)
|
|
134
|
+
|
|
135
|
+
When embedding AdminDB in an existing Express / Next.js backend, turn off built-in auth (`auth: false`) and apply your existing session or JWT middleware:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import express from 'express';
|
|
139
|
+
import { createRouter } from 'admindb';
|
|
140
|
+
|
|
141
|
+
const app = express();
|
|
142
|
+
|
|
143
|
+
// Your enterprise authentication middleware
|
|
144
|
+
function requireAdminRole(req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
145
|
+
if (req.user && req.user.role === 'SUPERADMIN') {
|
|
146
|
+
return next();
|
|
147
|
+
}
|
|
148
|
+
res.status(403).send('Forbidden: AdminDB requires SUPERADMIN privileges');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
app.use('/admin', requireAdminRole, createRouter({
|
|
152
|
+
connection: process.env.DATABASE_URL,
|
|
153
|
+
basePath: '/admin',
|
|
154
|
+
auth: false, // Turn off built-in login form; rely on requireAdminRole
|
|
155
|
+
}));
|
|
156
|
+
|
|
157
|
+
app.listen(45531);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
### Reverse Proxy & Gateway Protection (Nginx, Caddy, Cloudflare Zero Trust)
|
|
163
|
+
|
|
164
|
+
If running AdminDB standalone (`npx admindb`), bind to localhost (`HOST=127.0.0.1`) and put a reverse proxy in front:
|
|
165
|
+
|
|
166
|
+
```nginx
|
|
167
|
+
# Nginx reverse proxy with IP allowlist and HTTPS termination
|
|
168
|
+
server {
|
|
169
|
+
listen 443 ssl http2;
|
|
170
|
+
server_name db.yourcompany.internal;
|
|
171
|
+
|
|
172
|
+
ssl_certificate /etc/ssl/certs/app.crt;
|
|
173
|
+
ssl_certificate_key /etc/ssl/certs/app.key;
|
|
174
|
+
|
|
175
|
+
# Restrict to VPN / Office IP range
|
|
176
|
+
allow 10.0.0.0/8;
|
|
177
|
+
allow 192.168.1.0/24;
|
|
178
|
+
deny all;
|
|
179
|
+
|
|
180
|
+
location / {
|
|
181
|
+
proxy_pass http://127.0.0.1:45531;
|
|
182
|
+
proxy_set_header Host $host;
|
|
183
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
184
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
185
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Manager Mode & Filesystem Browsing Security
|
|
193
|
+
|
|
194
|
+
In Manager Mode, AdminDB provides an interactive filesystem browser to locate and open SQLite databases on the host. Several defensive measures protect host integrity:
|
|
195
|
+
|
|
196
|
+
### Path Sandboxing (`browseRoot`) & Traversal Prevention
|
|
197
|
+
- **Sandboxed Root (`browseRoot` / `-d <folder>`):** When started with a specific directory or `--browse-root`, browsing is strictly jailed to that folder. Any attempt to navigate upward returns `403 Forbidden`.
|
|
198
|
+
- **Symlink Escape Protection:** All path validations resolve real filesystem symlinks (`realpathSync`), preventing symlink-based jailbreaks.
|
|
199
|
+
- **Null-Byte Injection Blocking:** All inputs containing `\0` null-bytes are rejected immediately.
|
|
200
|
+
|
|
201
|
+
### Blocked Files & Secret Exclusion
|
|
202
|
+
The file browser automatically ignores and conceals sensitive system folders and secrets:
|
|
203
|
+
- Directories: `node_modules`, `.git`, `.svn`, `.hg`, `.aws`, `.ssh`, `System Volume Information`, `$RECYCLE.BIN`.
|
|
204
|
+
- Secret Files: Hidden dotfiles (`.*`), `.env`, `.env.local`, `.env.production`.
|
|
205
|
+
- File Filter: Only recognized database files (`.db`, `.sqlite`, `.sqlite3`) are displayed for opening.
|
|
206
|
+
|
|
207
|
+
### Disabling File Browsing Completely
|
|
208
|
+
When AdminDB is started with explicit database files (`--files`, `name.postgres.json`) or in serverless environments, **filesystem browsing is automatically disabled** (`allowBrowse: false`), eliminating any directory traversal attack surface.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Remote PostgreSQL Security
|
|
213
|
+
|
|
214
|
+
### Credential Masking & Memory Sanitation
|
|
215
|
+
- When PostgreSQL connection URIs (`postgresql://user:password@host:5432/db`) are registered, credentials are sanitised across the UI, responses, and log messages (`postgresql://user:****@host:5432/db`).
|
|
216
|
+
- Passwords are encrypted in-memory and are never leaked to client browsers.
|
|
217
|
+
|
|
218
|
+
### Secure JSON Configuration Files (`name.postgres.json`)
|
|
219
|
+
To avoid leaking passwords in shell history or process tables (`ps aux`), store database connections in a restricted JSON file:
|
|
220
|
+
|
|
221
|
+
```json
|
|
222
|
+
{
|
|
223
|
+
"production": "postgresql://postgres:secret@prod.internal:5432/prod_db",
|
|
224
|
+
"analytics": "postgresql://postgres:secret@analytics.internal:5432/dw_db"
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
And start AdminDB using the file:
|
|
229
|
+
```bash
|
|
230
|
+
npx admindb name.postgres.json
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Per-Database Read-Only Enforcements
|
|
234
|
+
- AdminDB allows marking any PostgreSQL or SQLite database as **Read-only** directly from the UI or configuration (`[ ] Open as Read-only`).
|
|
235
|
+
- In read-only mode, all write statements (`INSERT`, `UPDATE`, `DELETE`, `DROP`, `ALTER`, `CREATE`) and data-mutating APIs are blocked at the engine layer.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Production Security Checklist
|
|
240
|
+
|
|
241
|
+
- [ ] **Custom Credentials:** Replaced default `admin/admin` with a salted `scrypt` hash (`npm run generatehash`).
|
|
242
|
+
- [ ] **Fixed Session Secret:** Configured `ADMINDB_SECRET` to prevent session invalidation on restart.
|
|
243
|
+
- [ ] **Private Interface:** Bound to `HOST=127.0.0.1` or private subnet.
|
|
244
|
+
- [ ] **HTTPS / TLS:** Terminated SSL via reverse proxy or load balancer.
|
|
245
|
+
- [ ] **Custom Auth Wrapper:** Placed behind application auth middleware when embedded in Express.
|
|
246
|
+
- [ ] **Least Privilege DB Users:** Connected PostgreSQL using dedicated user roles with appropriate table grants.
|
|
247
|
+
- [ ] **Read-Only Where Applicable:** Enabled `--readonly` for auditing and data-viewer personas.
|
|
248
|
+
- [ ] **Jailed Browsing:** Specified `-d /path/to/dbs` or disabled browsing with explicit files.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## SQL Safety & Injection Protections
|
|
253
|
+
|
|
254
|
+
1. **Identifier Quoting:** Identifiers (table names, columns, indexes) are safely double-quoted (`"table_name"`).
|
|
255
|
+
2. **Parameterized Queries:** Queries use native driver parameter placeholders (`?` for SQLite, `$1, $2, ...` for PostgreSQL).
|
|
256
|
+
3. **Safe Preview Modes:** Preview endpoints return raw generated SQL strings for visual inspection without executing against the database.
|
|
257
|
+
4. **Internal Table Protection:** Internal AdminDB state tables (`_saved_queries`) are protected from being dropped, renamed, or mutated.
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Universal Destructive Action Safeguards
|
|
262
|
+
|
|
263
|
+
1. **Interactive Confirmation Barriers (`UI.confirm`):** Prompts with primary key details and impact assessments before single/bulk deletions.
|
|
264
|
+
2. **Type-to-Confirm Input Verification:** Dropping tables and deleting database files requires typing the exact name of the item.
|
|
265
|
+
3. **Transactional Isolation:** Bulk operations and CSV imports run in atomic transactions (`BEGIN ... COMMIT/ROLLBACK`), ensuring zero partial corruption on errors.
|