Known security-relevant behaviors of the plugin, with rationale. Review before deploying to a hardened environment.
python-lib/shared_duckdb/storage_config.py decrypts the GCS HMAC secret
stored in project variables using a password hardcoded in the source
(gcp_credentials, see the decrypt_string(...) call).
This is deliberate and was explicitly kept (2026-07 hardening review): the value stored in project variables is obfuscation, not encryption. Anyone with read access to the plugin source and the project variables can recover the secret. The threat this protects against is casual disclosure (a secret readable in cleartext in the project-variables UI / API dumps), nothing more.
Operational guidance:
- Treat the
gcs_hmacproject variable as if it were a cleartext credential: restrict project access accordingly. - Prefer service-account-based GCS connections over HMAC keys where possible; the HMAC path exists for DuckDB's S3-compat GCS access.
- Rotating the HMAC key rotates the actual credential; the obfuscation password does not need rotation (it protects nothing by itself).
The dashboard backend exposes GET /api/duckdb/query?q=... which executes
SQL against the dashboard DuckDB database. Statements are type-checked before
execution and only read statements (SELECT/EXPLAIN — SHOW/DESCRIBE/SUMMARIZE
parse as SELECT) are accepted; writes (INSERT/UPDATE/CREATE/DROP/COPY/ATTACH/
SET/transactions/…) are rejected with a 400. This matters because the backend
shares one writable DuckDB handle per process (see
pulse_duckdb/engine/create_conn.py) — the statement gate, not the connection
mode, is what makes this endpoint read-only.
Gating:
- In DSS: only enabled when the standard project variable
debugistrueon the dashboard project. Keep it off outside active debugging. The DuckDB file contains the full gold layer (all collected metadata), so anyone with webapp access can read all of it while enabled. - Local dev: since the 2026-07 hardening release, local dev no longer
enables it implicitly — set
PULSE_DEV_ALLOW_RAW_SQL=1explicitly.
Connection credentials (AWS keys, Azure keys, GCS HMAC) are rendered into
CREATE SECRET statements. Values are single-quote escaped, and values
containing {/} are rejected with a clear error (they previously broke
str.format cryptically). Credentials never leave the recipe/backend process;
they are not written to gold outputs.
The ignore_certs plugin setting disables certificate verification for
hub→worker API calls. Only use it for lab instances with self-signed
certificates; prefer installing the CA into the code-env trust store.
Multiple gunicorn workers coordinate DuckDB initialization only via the
fcntl lock file under PULSE_DUCKDB_DIR (.duckdb_init.lock). The lock
directory is created at startup (since the 2026-07 release — previously the
directory was never created and the lock silently could not be acquired, so
workers raced). There is no other cross-process coordination; anything else
that must be once-per-instance belongs behind that lock.