v0.6.2
BeechCMS v0.6.2
Release Date: July 11, 2026
Pull Request: [#237 — Fix validation issues, enhance API logic, and improve security](#237)
🔒 Security Fixes
- Public API data masking — Non-string branch values (numbers, booleans, dates, JSON, tags, files) were leaked raw through the public API instead of being nulled out. They are now masked consistently, mirroring
apply-policies.tsbehaviour. ((#200)) - Public add endpoint policy enforcement —
public-add.tswas writing sanitized data directly to the repository, bypassingapplyPrivacy(). Fields withprivacy: 'hash'were stored in plaintext andpublic: falsefields could be seeded on create. Privacy policies are now fully enforced on entry creation. ((#201)) - Filter condition policy enforcement — Public filter conditions were not checked against
policies.public/policies.filter, allowing non-public branches (e.g. a field markedpublic: false) to be used as a data-inference oracle. Filters on hidden branches are now rejected. ((#202)) - CDN origin spoofing prevention —
extractMediaKeyusedstartsWithto matchMEDIA_CDN_URL, which could be confused by subdomain or suffix-crafted URLs, allowing unauthorized deletion of unrelated R2 media objects. Now uses exact parsed-origin comparison. ((#222)) - FTS search index leaking non-public fields —
indexableSearchBranchescheckedpolicies.searchbut neverpolicies.public, so full-text search matches on hidden fields (e.g. SSN) could leak content viameta.total. Non-public branches are now excluded from the FTS index. ((#234))
🐛 Bug Fixes
- Draft
_touched_fieldsrace condition — ConcurrentsaveDraftcalls for the same entry could interleave their read-modify-write of_touched_fields, causing a later write to clobber an earlier one. On publish, relation branches missing from_touched_fieldswould have their junction rows silently deleted without promotion to live. The merge is now handled in a single atomicINSERT ... ON CONFLICT DO UPDATESQL statement usingjson_each/json_group_array. ((#210)) - Hash serialization collision —
String(value)coerced JSON, repeater, and richtext branches to the literal"[object Object]"and comma-joined arrays, so every distinct object hashed to the same digest underprivacy: 'hash'. All non-string values are now serialized withJSON.stringifybefore hashing. ((#215)) - Avatar upload bypassing presigned flow —
settingsApi.uploadAvatarposted raw file bytes to a nonexistent/uploadroute (returning 404), bypassing the required presign → PUT → confirm flow. It now delegates to the existinguploadFile()helper used byRichtextEditorandmedia.tsx. ((#226))
🛠️ Internal & Maintenance
- Deduplicated validation cache implementations — A squash-merge of independent fixes (#185 and #190) left stale duplicate implementations of
getCachedSchema/setCachedSchemaandbyteLengthincache.tsandprimitives.ts, causingtscto reject the build. Duplicate implementations have been removed. ((#236))
Upgrading
This release contains critical security fixes for the public API. Upgrading is strongly recommended for all deployments that expose public-facing endpoints. No breaking changes to the existing API contract or schema format are introduced.