* fix(security): sanitize dependency names & connection strings against command/SQL injection
Follow-up to the PowerShell module-name injection fix (#9587, CWE-78): the
same audit surfaced the identical "secondary identifier interpolated into an
interpreter/SQL command without escaping" pattern in a few other executors.
- R executor (the real twin, HIGH): package name/version parsed from a
user-supplied renv.lock were interpolated raw into an `Rscript -e
"...renv::install(\"{pkg}@{version}\"...)"` eval string. A double-quote in
the name/version broke out → arbitrary R (unsandboxed under DISABLE_NSJAIL /
non-Linux). Now validated in parse_renv_lock (charset) and escaped at the
sink as defense-in-depth (also escapes the lib path, which holds backslashes
on Windows).
- DuckDB ATTACH (MED): the connection string built from resource fields
(host/db/user/password) is embedded in a single-quoted DuckDB literal; escape
quotes so a field value can't break out of the ATTACH statement.
- PgDatabase::to_uri: URL-encode host and dbname (user/password already were),
so '@'/'/'/'?'/'&' can't reshape the parsed URI (feeds live PG connect and
DuckDB ATTACH).
- DuckDB CREATE SECRET (FFI): wrap the interpolated S3 key/secret/endpoint in
the existing sql_single_quote() helper, consistent with the resource-limits
setup right above it.
- PowerShell: also escape the configured private repo URL/PAT in the install
template (same sink as the module names; the escape landed after #9587 was
squash-merged so it was not in the merged change).
Adds unit tests for the R validation/escaping.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(security): escape ducklake/snowflake/bigquery identifiers; preserve IPv6 host
- to_uri: don't percent-encode bracketed IPv6 literal hosts ([::1]) — encoding
their brackets/colons would stop them parsing as a host (review fix).
- duckdb ducklake ATTACH: the catalog conn string, storage and data_path are
embedded in single-quoted DuckDB literals; escape quotes so a resource field
can't break out (the ducklake path bypassed the ATTACH escape added earlier).
- snowflake: validate account_identifier (it forms the request hostname).
- bigquery: validate project_id (it forms a request URL path segment).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>