Skip to content

fix(#43): validate AdminClient inputs against an allow-list before writing privileged Special Keys - #105

Merged
s2x merged 2 commits into
masterfrom
fix-issue-43-pr
Sep 9, 2026
Merged

fix(#43): validate AdminClient inputs against an allow-list before writing privileged Special Keys#105
s2x merged 2 commits into
masterfrom
fix-issue-43-pr

Conversation

@s2x

@s2x s2x commented Sep 9, 2026

Copy link
Copy Markdown
Member

Closes #43

Changes

Branch resurrects fix/issue-43-adminclient-input-validation (cherry-picked onto current master) and completes the second half of the issue: special-key paths are now verified against the documented FDB special-key spec (7.x) for the supported API version.

1. Input validation (allow-list at the PHP trust boundary)

Every caller-supplied input written into a privileged \xff\xff/management/... key is validated before the transaction opens:

Method Validated input Allow-list Max length
createTenant tenant name [A-Za-z0-9._-], start alnum 256 bytes
deleteTenant tenant name same 256 bytes
excludeServer/includeServer/rebootWorker server address [A-Za-z0-9._:-] 256 bytes
configure 1–2 whitespace-split tokens [A-Za-z0-9_-] per token 64 bytes
forceRecovery dcId [A-Za-z0-9_-] 64 bytes

Rejections throw \InvalidArgumentException synchronously with a printable (control-byte-escaped) rendering of the offending value — reproductions like createTenant('foo/bar') or excludeServer('127.0.0.1/24') can no longer silently address a different management sub-key.

2. Unverified special-key paths corrected (removed)

Verified against the special-keys documentation and FDB sources:

  • The \xff\xff/configuration/ module only covers process class types and coordinators — there is no redundancy/storage key. Live-cluster check confirmed writes fail at commit with special_keys_no_module_found.
  • Forced recovery is a cluster-controller RPC (fdbcli force_recovery_with_data_loss), not a special key — no \xff\xff/management/force_recovery exists.

Therefore configure() and forceRecovery() are deprecated and now throw \LogicException synchronously (after input validation) instead of failing opaquely at commit. \xff\xff/management/consistency_check_suspended and the tenant/excluded paths are documented and are covered by live integration tests.

Tests

  • Unit: AdminClientInputValidationTest (47 cases), AdminClientTest (+4 cases for the LogicException paths)
  • Integration: AdminInputValidationTest — tenant create/delete happy paths, exclude/include with special-key read-back, rejection paths, and "nothing written" assertions for the removed operations (26 tests, green against the 5-node Docker cluster; full integration suite 265 tests green)

Docs

  • docs/admin.md — Cluster Configuration / Force Recovery sections rewritten; validation contract table updated
  • CHANGELOG.md[#43] entries under Added and Changed

CI: composer lint + composer test:unit + full integration suite green locally.

Piotr Hałas and others added 2 commits September 9, 2026 07:19
…iting privileged Special Keys

AdminClient spliced caller-supplied bytes directly into the
privileged Special Key paths
(\xff\xff/management/tenant/map/<name>,
 \xff\xff/management/excluded/<addr>,
 \xff\xff/management/force_recovery,
 \xff\xff/configuration/{redundancy,storage})
with no content validation. A tenant name like 'foo/bar' silently
wrote \xff\xff/management/tenant/map/foo/bar (a different
management sub-key than intended), and a server address like
'127.0.0.1/24' silently produced
\xff\xff/management/excluded/127.0.0.1/24. configure() accepted
any whitespace-split string with no token validation.

The fix routes every caller-supplied identifier through private
helpers (validateTenantName, validateAddress, validateToken,
parseConfiguration) on AdminClient that throw
\InvalidArgumentException with a printable rendering of the
offending input before any transaction begins. Allow-list:

  createTenant/deleteTenant  [A-Za-z0-9._-]   start alnum   256B
  exclude/include/reboot     [A-Za-z0-9._:-]                256B
  configure (per token)      [A-Za-z0-9_-]                 64B
  forceRecovery              [A-Za-z0-9_-]                 64B

Unit tests (47 cases) cover every allow-list boundary, length
bound, leading-character rule, printable-output safety, and
parseConfiguration rejection shapes. Integration tests (24 cases)
exercise createTenant, deleteTenant, excludeServer, includeServer,
configure against a live cluster and assert that rejected inputs
do not reach the Special Key range.

Affected files:
- src/AdminClient.php
- docs/admin.md
- CHANGELOG.md
- tests/Unit/AdminClientInputValidationTest.php (new)
- tests/Integration/AdminInputValidationTest.php (new)
@s2x
s2x merged commit dceae52 into master Sep 9, 2026
6 checks passed
@s2x
s2x deleted the fix-issue-43-pr branch September 9, 2026 05:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security] AdminClient writes unvalidated input into privileged special keys; several special-key paths unverified

1 participant