Skip to content

Commit 05b40ae

Browse files
Merge pull request #6 from Altinity/add-clickhouse-security-skill
Add altinity-expert-clickhouse-security skill
2 parents 0a3aa36 + c9d661a commit 05b40ae

31 files changed

Lines changed: 1964 additions & 3 deletions

altinity-expert-clickhouse/README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This package contains the modular `altinity-expert-clickhouse-*` ClickHouse diag
44

55
## Layout
66

7-
- `skills/` — all `altinity-expert-clickhouse-*` skill definitions (each has its own `SKILL.md`). The `...-overview` skill is the router and suggests which specialist skill(s) to run next.
7+
- `skills/` — all `altinity-expert-clickhouse-*` skill definitions (each has its own `SKILL.md`). The `...-overview` skill is the router and suggests which specialist skill(s) to run next. The `...-security` skill is a standalone, read-only security audit (it uses a `references/` subdirectory loaded on demand) and is not part of the performance-triage chain below.
88
- `tests/` — test suite and scenarios. Do not modify structure without updating prompts/runner.
99
- `../releases/` — built zip packages for distribution.
1010

@@ -40,6 +40,20 @@ Report requirements:
4040
```
4141

4242

43+
## Security Audit (standalone)
44+
45+
The `altinity-expert-clickhouse-security` skill performs a professional, read-only
46+
security audit (users, roles, grants, definer views, row policies, external sources,
47+
audit logs, secrets, Keeper/interserver, encryption/backups, HTTP surface, cluster,
48+
and version-specific behavior). Example prompt:
49+
50+
```
51+
Perform a read-only ClickHouse security audit using the altinity-expert-clickhouse-security skill.
52+
Produce findings with severity, confidence, evidence (redacted), and SQL-only limitations.
53+
```
54+
55+
Run its test with `make test-security` (see below).
56+
4357
## Run Tests
4458

4559
From `altinity-expert-clickhouse/tests`:
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
---
2+
name: altinity-expert-clickhouse-security
3+
description: Read-only ClickHouse security audit expert for live or exported systems. Use when assessing ClickHouse security posture, reviewing users, roles, grants, settings profiles, row policies, table functions, external sources, table engines, executable UDFs, audit logs, named collections, password hash hygiene, SQL SECURITY DEFINER, impersonation, TLS/network exposure, Keeper/interserver security, encryption at rest, backups, the HTTP interface surface, cluster security, or version-specific ClickHouse security behavior. Diagnoses from SQL/system tables, supplied configuration files, query logs, access metadata, and ClickHouse/Altinity documentation.
4+
license: Apache-2.0
5+
---
6+
7+
# Altinity Expert ClickHouse Security
8+
9+
Use this skill to perform a professional, read-only ClickHouse security audit. Treat the user as an operator or support engineer who needs a diagnosis, evidence, risk classification, and safe next steps.
10+
11+
## Core behavior
12+
13+
- Work as a senior ClickHouse security reviewer.
14+
- Prefer read-only SQL and metadata inspection.
15+
- Never run destructive SQL.
16+
- Never perform online password guessing.
17+
- Never print secrets, password hashes, salts, private keys, access keys, tokens, or recovered password candidates in normal reports.
18+
- Correlate findings. Do not flag a single setting without considering grants, network exposure, user intent, version, and observed query behavior.
19+
- State what could not be verified from SQL-only access.
20+
- Use ClickHouse and Altinity documentation as source of truth for version-specific behavior.
21+
- When recommendations are requested, provide minimal, targeted remediation steps after presenting the diagnosis.
22+
23+
## Standard workflow
24+
25+
1. Establish scope:
26+
- live SQL access, exported `system.*` data, supplied `users.xml` / `config.xml`, or query-log extracts.
27+
- single node or cluster.
28+
- ClickHouse version and deployment model.
29+
2. Collect safe evidence:
30+
- `SELECT version()`
31+
- `SHOW ACCESS`
32+
- selected `system.*` tables
33+
- supplied configuration snippets
34+
- recent `system.query_log` and `system.session_log`, if available.
35+
3. Load only the relevant reference files below.
36+
4. Produce findings with:
37+
- title
38+
- severity
39+
- confidence
40+
- evidence summary
41+
- why it matters
42+
- what was not verifiable
43+
- suggested confirmation or remediation, only when appropriate.
44+
45+
## Reference index
46+
47+
- `references/01-scope-and-safety.md`: safe execution rules, evidence handling, redaction.
48+
- `references/02-identity-authentication.md`: users, auth methods, default user, expiration, multiple auth methods.
49+
- `references/03-users-roles-grants-rbac.md`: RBAC, grants, admin-equivalent permissions.
50+
- `references/04-definer-impersonation-principals.md`: `SQL SECURITY DEFINER`, `EXECUTE AS`, no-password principals.
51+
- `references/05-network-exposure-and-tls.md`: host restrictions, ports, TLS, exposure.
52+
- `references/06-table-functions-external-sources.md`: table functions, `SOURCES` grants, exfiltration paths.
53+
- `references/07-table-engines-and-external-integrations.md`: external table engines, persistent integrations.
54+
- `references/08-row-column-policy-security.md`: row policies, column grants, bypass patterns.
55+
- `references/09-settings-profiles-constraints-quotas.md`: settings profiles, constraints, quotas, readonly.
56+
- `references/10-audit-logging-and-log-integrity.md`: query/session logs, `log_query_settings`, observability gaps.
57+
- `references/11-query-log-threat-hunting.md`: suspicious behavior from logs.
58+
- `references/12-secrets-named-collections-credentials.md`: named collections, secret handling, hardcoded credentials.
59+
- `references/13-password-hash-hygiene.md`: hash inventory, duplicate hashes, weak hash matching, safe reporting.
60+
- `references/14-version-specific-security-checks.md`: version-aware checks.
61+
- `references/15-cluster-distributed-security.md`: cluster-wide consistency and distributed security.
62+
- `references/16-keeper-and-interserver-security.md`: ZooKeeper/Keeper exposure and ACLs, interserver authentication.
63+
- `references/17-executable-udf-and-code-execution.md`: executable UDFs and server-side command execution capability.
64+
- `references/18-encryption-at-rest-and-backups.md`: encrypted disks, storage credentials, `BACKUP`/`RESTORE` destinations.
65+
- `references/19-http-interface-surface.md`: HTTP handlers, Play UI, CORS, default-credential access over HTTP.
66+
- `references/20-reporting-severity-and-output-format.md`: severity rubric and final report structure.
67+
68+
## SQL style
69+
70+
Use fenced `sql` blocks for SQL. Keep SQL compatible with ClickHouse 24.8+ unless a version-specific note says otherwise. Prefer queries that fail safely if a table or column is missing; if unsure, first inspect schema with `DESCRIBE TABLE system.<table>`.
71+
72+
## Redaction
73+
74+
Never print secrets, hashes, salts, keys, tokens, or connection strings. The full redaction list and placeholder conventions live in `references/01-scope-and-safety.md`; apply them to all evidence.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Scope and safety
2+
3+
Use this section first for any live-system audit.
4+
5+
## Non-negotiable rules
6+
7+
- Use read-only SQL only.
8+
- Do not run `CREATE`, `ALTER`, `DROP`, `TRUNCATE`, `INSERT`, `OPTIMIZE`, `SYSTEM`, `KILL`, `BACKUP`, `RESTORE`, or `SET` unless the user explicitly asks for a remediation command and understands it is not an audit probe.
9+
- Do not run network probes through table functions.
10+
- Do not use table functions to test whether exfiltration is possible.
11+
- Do not attempt online password guessing or authentication attempts.
12+
- Do not print secrets, password hashes, salts, or credential candidates.
13+
14+
## Initial evidence checklist
15+
16+
Collect when available:
17+
18+
```sql
19+
SELECT version();
20+
```
21+
22+
```sql
23+
SHOW ACCESS;
24+
```
25+
26+
```sql
27+
SELECT name, value, changed
28+
FROM system.settings
29+
WHERE name IN
30+
(
31+
'log_queries',
32+
'log_query_settings',
33+
'readonly',
34+
'allow_ddl'
35+
)
36+
ORDER BY name;
37+
```
38+
39+
If cluster-wide checks are needed, prefer existing cluster topology supplied by the user. Do not guess cluster names. Ask for the cluster name, or inspect only local node data.
40+
41+
## Evidence confidence
42+
43+
Use these confidence labels:
44+
45+
- `high`: direct metadata evidence from SQL/config/logs.
46+
- `medium`: strong pattern, but inherited roles/profiles or cluster coverage may be incomplete.
47+
- `low`: inferred from partial DDL text, samples, or missing logs.
48+
- `unknown`: cannot be verified with available access.
49+
50+
## Redaction (canonical)
51+
52+
This is the single source of truth for redaction; other sections refer here. When showing evidence, redact:
53+
54+
- password hashes and salts
55+
- secrets in URLs and named collections
56+
- cloud access keys and secret keys
57+
- SAS tokens and signed URLs
58+
- private keys
59+
- bearer tokens and JWTs
60+
- connection strings (including JDBC/ODBC) containing credentials
61+
- internal hostnames, if the user asks for sanitized output
62+
63+
Use placeholders such as `<redacted_hash>`, `<redacted_secret>`, `<redacted_key>`, and `<internal_host>`.
64+
65+
## Reporting limitations
66+
67+
Always state SQL-only gaps, such as:
68+
69+
- cannot verify `listen_host`, TLS certificate configuration, or named collection storage without config access.
70+
- cannot confirm full cluster posture from one node.
71+
- cannot validate password strength from salted/bcrypt hashes except through safe offline denylist matching.
72+
- cannot know whether broad grants are intentional without ownership context.
73+
74+
## Auditor privilege affects what is observed
75+
76+
State the identity and privilege level the audit ran as. A highly-privileged auditor sees a complete `SHOW ACCESS` and full system tables, but settings read from the live session reflect that session, not other users' enforced policy (see `09-settings-profiles-constraints-quotas.md`). A low-privilege auditor may see only a partial picture and should say so. Note the auditing identity in the report so session-derived readings are interpreted correctly.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Identity and authentication checks
2+
3+
Use this section to evaluate ClickHouse user authentication posture. Do not treat authentication method alone as risk; correlate with host restrictions, grants, and intended role.
4+
5+
## Check: authentication method inventory
6+
7+
```sql
8+
SELECT
9+
name,
10+
auth_type,
11+
valid_until,
12+
host_ip,
13+
host_names,
14+
host_names_regexp,
15+
host_names_like,
16+
default_roles_all,
17+
default_roles_list,
18+
default_roles_except
19+
FROM system.users
20+
ORDER BY name;
21+
```
22+
23+
Classify:
24+
25+
- `plaintext_password`: high concern because plaintext storage is avoidable.
26+
- `sha256_password` / `sha256_hash`: acceptable but weaker than bcrypt if hashes are compromised.
27+
- `double_sha1_password` / `double_sha1_hash`: usually compatibility-driven; ask why it is needed.
28+
- `bcrypt_password` / `bcrypt_hash`: preferred local password storage.
29+
- `ldap`, `kerberos`, `ssl_certificate`, `ssh_key`, `jwt`, `http`: evaluate the external mechanism and local fallback methods.
30+
- `no_password` / `no_authentication`: neutral by itself. See `04-definer-impersonation-principals.md`.
31+
32+
## Check: default user posture
33+
34+
Focus on `default` because it is commonly overused.
35+
36+
Risk signals:
37+
38+
- broad host access.
39+
- admin-equivalent grants.
40+
- local password auth with weak method.
41+
- used by applications and administrators simultaneously.
42+
- used for inter-node communication without clear isolation.
43+
44+
Do not recommend deleting or disabling `default` blindly. First confirm internode usage, automation, and cluster configuration.
45+
46+
## Check: credential expiration
47+
48+
Use `valid_until` from `system.users`.
49+
50+
Risk signals:
51+
52+
- human users with no expiration policy.
53+
- expired credentials still configured.
54+
- multiple auth methods where a weak fallback lacks expiration.
55+
56+
## Check: multiple authentication methods
57+
58+
A user with multiple auth methods can authenticate through any listed method. One weak fallback can undermine a strong primary method.
59+
60+
Risk examples:
61+
62+
- `bcrypt_password` plus `plaintext_password`.
63+
- external auth plus local password fallback with broad hosts.
64+
- certificate/SSH plus no-password fallback.
65+
66+
Rate an auth method only together with host restriction and grants: `sha256_password` from a narrow IP with read-only grants is low; `plaintext_password` from broad hosts with grant option is high.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Users, roles, grants, and RBAC checks
2+
3+
Use this section when reviewing `SHOW ACCESS`, `system.grants`, users, and roles.
4+
5+
## Check: collect grants
6+
7+
Preferred:
8+
9+
```sql
10+
SHOW ACCESS;
11+
```
12+
13+
If system grants are available, also inspect relevant rows:
14+
15+
```sql
16+
SELECT *
17+
FROM system.grants
18+
ORDER BY user_name, role_name, database, table, access_type;
19+
```
20+
21+
Column names may vary by version; inspect with `DESCRIBE TABLE system.grants` if needed.
22+
23+
## Check: admin-equivalent permissions
24+
25+
Flag users or roles with combinations of:
26+
27+
- `GRANT ALL ON *.*`
28+
- `WITH GRANT OPTION`
29+
- `ACCESS MANAGEMENT`
30+
- `CREATE USER`, `ALTER USER`, `DROP USER`
31+
- broad `CREATE`, `ALTER`, `DROP`, `TRUNCATE`
32+
- broad `SYSTEM`
33+
- broad `SOURCES`: `FILE`, `URL`, `S3`, `REMOTE`, `MYSQL`, `POSTGRES`, `JDBC`, `ODBC`, `AZURE`
34+
- `INTROSPECTION`
35+
- `ALLOW SQL SECURITY NONE`
36+
- `IMPERSONATE ON *`
37+
38+
## Counting and attribution rules
39+
40+
Apply these before reporting grant findings, or counts will be inflated and admins will be flagged for being admins:
41+
42+
- **Do not double-count `ALL`-implied privileges.** `GRANT ALL ON *.*` already implies `SYSTEM`, `INTROSPECTION`, `SOURCES`/`S3`/`URL`/`FILE`/`REMOTE`, `displaySecretsInShowAndSelect`, `NAMED COLLECTION ADMIN`, and the DDL/access-management privileges. When you report "N principals have SYSTEM/SOURCES/INTROSPECTION", count only those who hold it **without** `ALL`; otherwise you are re-listing the same admins under every derived privilege.
43+
- **Deduplicate identities.** One human often has several principals — e.g. a local user `name` and an SSO/OAuth identity `name@example.com`, or a personal user plus a role. Note the likely link and report once, rather than as separate findings.
44+
- **Distinguish expected admins and service accounts.** `ALL` on `clickhouse_operator` (the ClickHouse/Altinity Kubernetes operator), a break-glass admin, or a named service role is usually intentional. The finding is the *unexpected* `ALL`-holder, or an admin set that is larger than the operating model justifies — not the existence of admins. Ask for ownership context when intent is unclear.
45+
- **Gate severity on reachability.** Pair every powerful grant with the principal's `host_ip`/`host_names` and auth method (see `05-network-exposure-and-tls.md` and `02-identity-authentication.md`). The same `ALL` + grant option is Critical on `::/0` with plaintext auth and far lower when locked to localhost/operator with strong auth.
46+
- **Merge same-principal findings.** If one account combines weak auth, `ALL`, and broad grant option, report it as one correlated finding with combined blast radius, not three.
47+
- **Authority comes from grants, not settings.** Read/write capability is decided by RBAC (`SELECT` vs `INSERT`/`ALTER`/`CREATE`/`DROP`), not by `readonly`/`allow_ddl`. Do **not** credit a `readonly` profile as a mitigation that lowers a grant finding — it is a mutable, per-session settings overlay, and "grant broad, then clamp with `readonly`" is a design smell, not a control. The finding is the over-broad grant; right-size it. Treat `readonly=2` only as effective-behavior context (a grant may be currently inert) and as a risk *amplifier* (`SET` + `CREATE TEMPORARY TABLE` + `SOURCES` → table functions; see `09`).
48+
49+
## Check: privilege inheritance
50+
51+
Look for:
52+
53+
- users with all roles enabled by default.
54+
- powerful roles granted to low-privilege users.
55+
- role chains that make a user admin-equivalent.
56+
- grants assigned to roles that look like application or BI roles.
57+
58+
## Check: grant option blast radius
59+
60+
`WITH GRANT OPTION` is high risk when combined with broad privileges. The user can delegate permissions beyond the original operational intent.
61+
62+
Severity escalation:
63+
64+
- broad privileges + grant option: critical/high.
65+
- object-level select + grant option: medium, depends on data sensitivity.
66+
- admin role with grantees_any: high.
67+
68+
## Stating impact
69+
70+
Never write "too many grants". State the reachable outcome: create users, delegate privileges, read sensitive system metadata, create external data paths, drop/mutate production objects, or bypass row-policy designs.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Definer, impersonation, and security principal checks
2+
3+
Use this section for `SQL SECURITY DEFINER`, `EXECUTE AS`, `IMPERSONATE`, and no-password principal analysis.
4+
5+
## Key model
6+
7+
`no_password` and `no_authentication` are not automatically findings. They are often deliberate non-login principals used as security contexts for views, materialized views, JWT shadow definers, or impersonation workflows.
8+
9+
## Check: no-password principals
10+
11+
```sql
12+
SELECT
13+
name,
14+
auth_type,
15+
host_ip,
16+
host_names,
17+
host_names_regexp,
18+
host_names_like,
19+
default_roles_all,
20+
default_roles_list,
21+
default_roles_except
22+
FROM system.users
23+
WHERE has(auth_type, 'no_password')
24+
OR has(auth_type, 'no_authentication')
25+
ORDER BY name;
26+
```
27+
28+
Classify:
29+
30+
- expected: no-password user has narrow/no login path, narrow grants, and is referenced as definer or controlled impersonation target.
31+
- suspicious: no-password user has broad hosts, admin grants, grant option, source grants, or no visible purpose.
32+
33+
## Check: views using definer security
34+
35+
```sql
36+
SELECT
37+
database,
38+
name,
39+
engine,
40+
create_table_query
41+
FROM system.tables
42+
WHERE positionCaseInsensitive(create_table_query, 'SQL SECURITY DEFINER') > 0
43+
OR positionCaseInsensitive(create_table_query, 'DEFINER') > 0
44+
ORDER BY database, name;
45+
```
46+
47+
Risk signals:
48+
49+
- definer has more grants than needed by the view query.
50+
- definer is an admin or default user.
51+
- view exposes sensitive columns or unfiltered rows.
52+
- caller-facing role has broad `SELECT` on many definer views.
53+
- materialized view definer has unexpected `INSERT` privileges.
54+
55+
## Check: SQL SECURITY NONE
56+
57+
`SQL SECURITY NONE` is deprecated and dangerous. Creating such views requires `ALLOW SQL SECURITY NONE`; flag principals with this privilege.
58+
59+
Search in `SHOW ACCESS` for:
60+
61+
```text
62+
ALLOW SQL SECURITY NONE
63+
```
64+
65+
## Check: impersonation
66+
67+
Inspect `SHOW ACCESS` for:
68+
69+
```text
70+
IMPERSONATE
71+
```
72+
73+
Risk signals:
74+
75+
- `IMPERSONATE ON *`.
76+
- impersonation granted to app users or BI users.
77+
- impersonation target has admin-equivalent grants.
78+
- `access_control_improvements.allow_impersonate_user` enabled without clear controls.

0 commit comments

Comments
 (0)