- Shipped
- September 23, 2026 at 2:44 AM UTC
- Author
- Kamo
- Commit
- 3a74027
BinderItem pins the Img row it was built from at assembly time. BinderRenderer.renderItem handed that Img straight to **************** with no check at all for the member actually rendering the binder NOW — so a template binder assembled once (an org's standard loan package, an HR onboarding packet) and rendered later by a different member, or by the same member after their access changed, served that Img's bytes to whoever could render the binder, regardless of whether they could ever have opened the document itself through /download, /stream or any other document endpoint. Each DOC item's Img is now re-resolved through **************** for the rendering token before its bytes are fetched — the same org+clearance check every generic byte-serving endpoint runs. A refusal (org mismatch, insufficient clearance, row gone) renders the same "Could not include: <name>" placeholder page the code already used for an unconvertible document, rather than propagating and failing the whole binder. Scoped to org+clearance only, matching the finding text exactly ("the normal clearance/ownership check"): per-party (ACCOUNT_MEMBER_VAULT/LOAN), issued-document and media-association (chat/voicemail/call-recording) rules are checked in ImagingController, not here, and are NOT additionally re-verified in this pass — binders are a document-package/template feature, not a place those narrower association types are expected to appear, and wiring all three in is a larger change than this finding calls for. Noted as a residual, narrower gap. New test: BinderRendererAccessTest (BinderRenderer had no test at all before this). Mutation- checked: reverting renderItem's case DOC to call getDocumentPdf(item.getImg(), true) directly turns both cases red. Full suite: 743 tests green (was 741; +2 new).
