microsoft / microsoft/multiclouddb-sdk-for-java

πŸ” Deep Repository Review: 16 Critical, 34 High, 48 Medium findings

Open
#64 2 comments 0 reactions 1 assignee View on GitHub

@allenkim0129 is already working on this.

Since Jul 8, 2026.

Dominant language
Java
Stars
7
Forks
7
Avg merge
1d 22h
Merged PRs (30d)
1

Description

πŸ” Deep Repository Review: microsoft/multiclouddb-sdk-for-java

Date: 2026-04-27
Repo: https://github.com/microsoft/multiclouddb-sdk-for-java
Reviewer: Copilot deep-review pipeline (7 parallel agents)


πŸ“Š Aggregate Finding Counts

Severity API/Arch Cosmos DB DynamoDB Spanner Query DSL CI/CD Tests Total
πŸ”΄ CRITICAL 3 2 0 3 2 3 3 16
🟠 HIGH 7 4 4 4 5 6 4 34
🟑 MEDIUM 8 6 7 8 6 7 6 48
🟒 LOW 6 4 7 6 5 5 3 36
Total 24 16 18 21 18 21 16 134

🚨 CRITICAL Findings (Must Fix Before GA)

C1. Spanner Provider Storage Model Is Fundamentally Broken

Source: SpannerProviderClient.java, SpannerConstants.java

DDL creates tables with 3 columns (partitionKey, sortKey, data STRING(MAX)), but writeMutationFields() writes each document field as an individual Spanner column. The data column is never written to. Every write on a provisioned table fails.

Fix: Serialize docs to JSON in data column, or generate DDL matching the document schema.

C2. SQL Injection via Unquoted Table Names in Spanner

Source: SpannerExpressionTranslator.java, SpannerProviderClient.java

Table names injected via String.format() without backtick-quoting. "users; DROP TABLE users--" achieves full injection. Cosmos (fixed c alias) and DynamoDB (double-quotes) are safe.

Fix: Backtick-quote all identifiers + validate names against [a-zA-Z_][a-zA-Z0-9_]*.

C3. String Literal Injection in Expression Translators

Source: All three translator files

Inline string literals bypass parameterization. Spanner translator also missing backslash escaping.

C4. Spanner ABORTED Mapped to CONFLICT Instead of Retry

Source: SpannerErrorMapper.java

Should be TRANSIENT_FAILURE per GCP docs.

C5. No Maven Central Publishing in Release Pipeline

Source: .github/workflows/release.yml

No GPG signing, no Sonatype, no distributionManagement. Consumers can't <dependency> on this.

C6. No Spanner Emulator Integration Tests in CI

CI covers Cosmos + DynamoDB but not Spanner. Regressions ship undetected.

C7. Mutable Exception β€” Thread Safety Violation

Source: MulticloudDbException.java

withDiagnostics() mutates non-final field in-place. Data race across threads.

C8. Dead Conformance Tests β€” Never Execute

ResultSetControlConformanceTest and TtlAndMetadataConformanceTest are abstract with zero subclasses. Spanner missing from SortKeyOrderingConformanceTest.

C9. No Document Size Validation in Cosmos Provider

399KB limit mentioned in README but not enforced in provider write path.


🟠 HIGH Findings

API & Architecture
ID Finding
A-H1 Jackson ObjectNode leaked in public API β€” DocumentResult returns ObjectNode, writes use Map
A-H2 Inconsistent document type across read/write/query
A-H3 read() returns null instead of Optional<DocumentResult>
A-H4 Missing TIMEOUT and PRECONDITION_FAILED error categories
A-H5 expressionTranslator volatile + setter β€” race condition window
A-H6 QueryPage deep-copies all items on construction
A-H7 No module-info.java β€” internal package accessible
Cosmos DB Provider
ID Finding Best Practice
Co-H1 No retry-after for 429 throttling MS 429 docs
Co-H2 Default Gateway mode (not Direct) β€” latency penalty MS Direct vs Gateway
Co-H3 RU charge missing from point-op diagnostics
Co-H4 Consistency level hardcoded β€” not configurable
DynamoDB Provider
ID Finding Best Practice
Dy-H1 Client-side sort on scan mixes partitions Scan has no ordering
Dy-H2 No Binary/Binary Set support β€” data silently dropped AWS Data Types
Dy-H3 toAttributeValue() can't handle List/Map params
Dy-H4 update() bypasses DynamoErrorMapper
Spanner Provider
ID Finding Best Practice
Sp-H1 OFFSET pagination is O(nΒ²) GCP keyset pagination
Sp-H2 TRANSACTIONS_CAP declared but unimplemented GCP R/W Transactions
Sp-H3 Spanner client leak on construction failure
Sp-H4 ORDER BY fields not sanitized β€” injection
Query DSL
ID Finding
Q-H1 No recursion depth limit β†’ StackOverflow
Q-H2 No expression length limit β†’ OOM
Q-H3 BetweenExpression/InExpression accept unvalidated Objects
Q-H4 Silent no-op on unknown Expression types
Q-H5 DynamoDB reserved words not quoted (status, name, count…)
CI/CD
ID Finding
CI-H1 No static analysis (Checkstyle/SpotBugs/PMD)
CI-H2 No JaCoCo coverage
CI-H3 No Dependabot/Renovate
CI-H4 No OWASP dependency-check
CI-H5 Release has no integration test gate
CI-H6 junit-jupiter missing <scope>test</scope> in conformance POM
Tests
ID Finding
T-H1 No thread-safety tests
T-H2 No Testcontainers β€” manual emulator setup
T-H3 Spanner has only 2 unit tests
T-H4 Inconsistent @Tag usage

🟑 MEDIUM Findings (48 total β€” summarized by area)

API (8): Missing equals/hashCode on error types, no timeout validation, capability naming collision, unbounded thread pool in provisionSchema, missing toString fields, no @Nullable annotations

Cosmos (6): No throughput/indexing in provisioning, sync-only API, query results leak system fields, setMaxBufferedItemCount misuse, capability docs wrong on TTL field name, no projection support

DynamoDB (7): No 400KB size check, binary keys break pagination, strong consistency not configurable, incompatible token formats, reserved words unquoted, number precision loss, TTL not enabled on table

Spanner (8): read() uses SQL not readRow(), translator doesn't quote tables, BATCH/CHANGE_FEED caps unimplemented, toString() for complex objects, fragile WHERE detection, brittle DDL error check, missing type handling

Query DSL (6): Negative number ambiguity, dead isAtBetweenAnd(), no function arity validation, Cosmos ignores container param, Literal accepts arbitrary Objects, DynamoDB drops missing params

CI/CD (7): Javadoc lint disabled, PAT for docs deploy, test modules not excluded from deploy, no dependency convergence, no BOM, stale plugins, no permissions block

Tests (6): Size test only on DynamoDB, fragile @Order cleanup, new client per test, no edge cases, user-agent test only on DynamoDB


βœ… What's Done Well

Area Assessment
API Design Clean builders, good Javadoc, solid SPI, extensible value objects
Error Model Comprehensive categories with retryability flags
Query DSL Sealed interfaces + records, correct precedence, parameterized queries
DynamoDB Excellent error mapping, correct Query vs Scan routing, PAY_PER_REQUEST default
Cosmos Singleton client, session consistency, point-read optimization, user-agent
Module Structure Clean multi-module layout, independent versioning, centralized deps
Community Complete CONTRIBUTING, SECURITY, CLA, CODE_OF_CONDUCT, PR/issue templates
Tests 281+ tests, good parser/validator/translator coverage

Provider Best Practice Cross-Check

Azure Cosmos DB
Practice Status
Singleton client βœ…
Direct mode default ⚠️ Defaults to Gateway
Session consistency βœ…
Retry-after on 429 ❌
RU tracking ⚠️ Queries only
Point read via readItem βœ…
User-agent tagging βœ…
Amazon DynamoDB
Practice Status
AWS SDK v2 βœ…
PAY_PER_REQUEST βœ…
Query vs Scan routing βœ…
GetItem for reads βœ…
ReturnConsumedCapacity βœ… (except PartiQL)
Reserved word quoting ❌
Binary support ❌ Silently dropped
TTL enablement ❌
Google Cloud Spanner
Practice Status
readRow for point reads ❌ Uses SQL
Keyset pagination ❌ Uses OFFSET
R/W transactions ❌ Bare mutations
ABORTED retry ❌ Mapped to CONFLICT
Identifier quoting ❌ Injection risk
JSON document storage ❌ DDL mismatch
Emulator support βœ…

🎯 Top 10 Priority Actions

# Action Impact
1 Fix Spanner storage model (serialize to data JSON column) Provider non-functional
2 Fix SQL injection (backtick-quote Spanner identifiers) Security
3 Fix Spanner ABORTED β†’ TRANSIENT_FAILURE Retry handling
4 Add parser recursion/length limits DoS prevention
5 Unify document type to Map<String, Object> API consistency
6 Add Spanner CI tests + fill conformance gaps Coverage
7 Quote DynamoDB field names in PartiQL Correctness
8 Enable TTL on DynamoDB tables during provisioning Silent failure
9 Add Dependabot + OWASP + SpotBugs Security/quality
10 Cosmos: default Direct mode + configurable consistency Performance

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up β€” it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.