mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
fix query route safe clickhouse error codes (#1268)
<!-- Make sure you've read the CONTRIBUTING.md guidelines: https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Refined analytics query error classification so certain database errors are treated as known/handled, reducing exposure of internal diagnostics in responses. * **Tests** * Added end-to-end tests verifying safe (masked) error responses, preventing leakage of restricted column/identifier details and constraining suggestion text in error messages. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
d51c303fb0
commit
381e057c1f
@ -83,6 +83,8 @@ const SAFE_CLICKHOUSE_ERROR_CODES = [
|
||||
|
||||
const UNSAFE_CLICKHOUSE_ERROR_CODES = [
|
||||
36, // BAD_ARGUMENTS
|
||||
43, // ILLEGAL_TYPE_OF_ARGUMENT
|
||||
47, // UNKNOWN_IDENTIFIER
|
||||
60, // UNKNOWN_TABLE
|
||||
497, // ACCESS_DENIED
|
||||
];
|
||||
|
||||
@ -1524,6 +1524,103 @@ it("does not allow input() function", async ({ expect }) => {
|
||||
`);
|
||||
});
|
||||
|
||||
it("returns a safe error for illegal type of argument (code 43)", async ({ expect }) => {
|
||||
const response = await runQuery({
|
||||
query: "SELECT arrayJoin(123)",
|
||||
});
|
||||
|
||||
expect(stripQueryId(response, expect)).toMatchInlineSnapshot(`
|
||||
NiceResponse {
|
||||
"status": 400,
|
||||
"body": {
|
||||
"code": "ANALYTICS_QUERY_ERROR",
|
||||
"details": {
|
||||
"error": deindent\`
|
||||
Error during execution of this query.
|
||||
|
||||
As you are in development mode, you can see the full error: 43 Argument for function arrayJoin must be Array or Map: In scope SELECT arrayJoin(123).
|
||||
\`,
|
||||
},
|
||||
"error": deindent\`
|
||||
Error during execution of this query.
|
||||
|
||||
As you are in development mode, you can see the full error: 43 Argument for function arrayJoin must be Array or Map: In scope SELECT arrayJoin(123).
|
||||
\`,
|
||||
},
|
||||
"headers": Headers {
|
||||
"x-stack-known-error": "ANALYTICS_QUERY_ERROR",
|
||||
<some fields may have been hidden>,
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it("does not leak column names from restricted tables via illegal type of argument (code 43)", async ({ expect }) => {
|
||||
// ClickHouse resolves identifiers and checks types before checking permissions,
|
||||
// so a code 43 error referencing a restricted table column could leak its name/type
|
||||
const response = await runQuery({
|
||||
query: "SELECT arrayJoin(query) FROM system.query_log",
|
||||
});
|
||||
|
||||
expect(stripQueryId(response, expect)).toMatchInlineSnapshot(`
|
||||
NiceResponse {
|
||||
"status": 400,
|
||||
"body": {
|
||||
"code": "ANALYTICS_QUERY_ERROR",
|
||||
"details": {
|
||||
"error": deindent\`
|
||||
Error during execution of this query.
|
||||
|
||||
As you are in development mode, you can see the full error: 43 Argument for function arrayJoin must be Array or Map: In scope SELECT arrayJoin(query) FROM system.query_log.
|
||||
\`,
|
||||
},
|
||||
"error": deindent\`
|
||||
Error during execution of this query.
|
||||
|
||||
As you are in development mode, you can see the full error: 43 Argument for function arrayJoin must be Array or Map: In scope SELECT arrayJoin(query) FROM system.query_log.
|
||||
\`,
|
||||
},
|
||||
"headers": Headers {
|
||||
"x-stack-known-error": "ANALYTICS_QUERY_ERROR",
|
||||
<some fields may have been hidden>,
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it("does not leak column names from restricted tables via unknown identifier (code 47)", async ({ expect }) => {
|
||||
// ClickHouse resolves identifiers before checking permissions, and suggests
|
||||
// real column names ("Maybe you meant: ..."), so code 47 must be unsafe
|
||||
const response = await runQuery({
|
||||
query: "SELECT qurey FROM system.query_log",
|
||||
});
|
||||
|
||||
expect(stripQueryId(response, expect)).toMatchInlineSnapshot(`
|
||||
NiceResponse {
|
||||
"status": 400,
|
||||
"body": {
|
||||
"code": "ANALYTICS_QUERY_ERROR",
|
||||
"details": {
|
||||
"error": deindent\`
|
||||
Error during execution of this query.
|
||||
|
||||
As you are in development mode, you can see the full error: 47 Unknown expression identifier \\\`qurey\\\` in scope SELECT qurey FROM system.query_log. Maybe you meant: ['query'].
|
||||
\`,
|
||||
},
|
||||
"error": deindent\`
|
||||
Error during execution of this query.
|
||||
|
||||
As you are in development mode, you can see the full error: 47 Unknown expression identifier \\\`qurey\\\` in scope SELECT qurey FROM system.query_log. Maybe you meant: ['query'].
|
||||
\`,
|
||||
},
|
||||
"headers": Headers {
|
||||
"x-stack-known-error": "ANALYTICS_QUERY_ERROR",
|
||||
<some fields may have been hidden>,
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it("does not allow numbers table function with large values", async ({ expect }) => {
|
||||
const response = await runQuery({
|
||||
query: "SELECT * FROM numbers(1000000000)",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user