fix(security): apply two findings from sharing security review

- get_document: strip extracted_text for share recipients (T-04-04-03 consistency)
- ShareModal: emit 'unshared' when last recipient is revoked; DocumentCard clears is_shared badge

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curo1305
2026-06-01 19:41:15 +02:00
parent a0f6c2f663
commit 089da94d8b
3 changed files with 8 additions and 1 deletions
+5
View File
@@ -545,6 +545,7 @@ async def get_document(
if doc is None:
raise HTTPException(404, "Document not found")
is_recipient = False
if doc.user_id != current_user.id:
# Allow recipients of an active share to view the document
share_result = await session.execute(
@@ -555,10 +556,14 @@ async def get_document(
)
if share_result.scalar_one_or_none() is None:
raise HTTPException(404, "Document not found")
is_recipient = True
meta = await storage.get_metadata(session, doc_id)
if meta is None:
raise HTTPException(404, "Document not found")
# T-04-04-03: recipients get metadata only — extracted_text excluded (consistent with /shares/received)
if is_recipient:
meta.pop("extracted_text", None)
return meta
@@ -85,6 +85,7 @@
v-if="showShareModal"
:doc="doc"
@close="showShareModal = false"
@unshared="doc.is_shared = false"
/>
</div>
</template>
@@ -125,7 +125,7 @@ const props = defineProps({
},
})
const emit = defineEmits(['close'])
const emit = defineEmits(['close', 'unshared'])
const docsStore = useDocumentsStore()
@@ -202,6 +202,7 @@ async function handleRevoke(shareId) {
try {
await docsStore.revokeShare(shareId)
if (shares.value.length === 0) emit('unshared', props.doc.id)
} catch (e) {
// Re-add on failure
if (removed && removedIdx !== -1) {