matrixorigin / matrixorigin/matrixone
[Bug]: Arrow S3 LOAD reads object before denying INSERT privilege
- Dominant language
- Go
- Stars
- 1.9k
- Forks
- 311
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 768
Description
## Description
An Arrow IPC `LOAD DATA` issued by a user without INSERT privilege reaches the configured S3 object store before MatrixOne rejects the statement for privilege denial.
The statement does not write rows, but authorization is not enforced before the external-object access. This can expose unnecessary object reads and makes denied requests depend on object-store availability.
## Environment
- Branch: `main`
- Commit: `269d59addd032d20897cc4d86f58de3e387a6d76`
- Deployment: isolated 1-CN embedded MatrixOne cluster; Arrow LOAD and S3 Arrow LOAD explicitly enabled; local version-compatible MinIO and an HTTP observing proxy.
- Date: 2026-09-10
## Steps to reproduce
1. Create a database/table and insert one owner-controlled seed row.
2. Start local MinIO with a valid Arrow IPC File object. Route its S3 endpoint through a proxy that records any object-store request.
3. Create a non-owner user/role with only `CONNECT` on the account; grant no INSERT/table privilege.
4. Connect through the MySQL protocol as that user and execute Arrow `LOAD DATA URL S3OPTION ...` into the owner table.
5. Observe the SQL result, proxy state, and owner-side row count. Then execute the same LOAD as the owner as a happy-path control.
## Actual behavior
- The non-owner statement is rejected with: `internal error: do not have privilege to execute the statement`.
- The proxy records an S3 request before that denial.
- The table remains seed-only after the denied statement.
- The owner retry succeeds and produces the expected second row.
## Expected behavior
A user who lacks INSERT permission should be rejected before MatrixOne performs S3/Arrow object access. The rejected request must leave the target table unchanged, and the normal owner control must continue to succeed.
## Stability and controls
- Reproducer: 3/3 failures on the latest official main.
- Happy-path control: 3/3 owner retries succeeded using the same valid Arrow object.
- Failure atomicity: 3/3 denied statements left exactly the original seed row.
## Evidence
Reproducer command:
```text
go test ./pkg/tests/arrowload -run '^TestArrowLoadPermissionDeniedDoesNotReadOrWrite$' -count=3 -timeout=180s
```
Each run failed only because the proxy observed object access. The denial and row-count checks completed as expected.
## Code analysis
Observed behavior is consistent with Arrow external-scan compile setup obtaining the external file list/size and Arrow planning data before the later execution privilege rejection. This is a hypothesis based on the reproduction, not a proposed fix.
## Regression coverage
A focused public-protocol regression is prepared in `pkg/tests/arrowload/arrow_load_lifecycle_test.go` as `TestArrowLoadPermissionDeniedDoesNotReadOrWrite`. It intentionally remains failing until the product ordering is fixed and should be landed with that fix.
## Related
- #23684
Contributor guide
Assessment
This issue has not been assessed yet.