feat: secure direct download links - only show for password-free shares
SECURITY: Fix potential password bypass vulnerability by: Frontend changes: - Add password_hash field to Share interface - Only show direct download button for single files without password protection - Update hasDownloadLink() to check both file type and password status Backend changes: - Remove token-based authentication bypass for password-protected shares - Enforce password authentication for all protected shares, even with valid tokens - Add security comments explaining the rationale This ensures that password-protected shares cannot be accessed via direct download links, closing the security vulnerability while preserving the convenience of direct downloads for public shares. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
49203f7599
commit
aa0338a1c4
@ -32,7 +32,7 @@
|
|||||||
<i class="material-icons">content_paste</i>
|
<i class="material-icons">content_paste</i>
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
<td class="small" v-if="hasDownloadLink()">
|
<td class="small" v-if="hasDownloadLink(link)">
|
||||||
<button
|
<button
|
||||||
class="action copy-clipboard"
|
class="action copy-clipboard"
|
||||||
:aria-label="$t('buttons.copyDownloadLinkToClipboard')"
|
:aria-label="$t('buttons.copyDownloadLinkToClipboard')"
|
||||||
@ -257,10 +257,11 @@ export default {
|
|||||||
buildLink(share) {
|
buildLink(share) {
|
||||||
return api.getShareURL(share);
|
return api.getShareURL(share);
|
||||||
},
|
},
|
||||||
hasDownloadLink() {
|
hasDownloadLink(link) {
|
||||||
return (
|
// Only show direct download link for single files without password protection
|
||||||
this.selectedCount === 1 && !this.req.items[this.selected[0]].isDir
|
const isSingleFile = this.selectedCount === 1 && !this.req.items[this.selected[0]].isDir;
|
||||||
);
|
const hasNoPassword = !link.password_hash || link.password_hash === "";
|
||||||
|
return isSingleFile && hasNoPassword;
|
||||||
},
|
},
|
||||||
buildDownloadLink(share) {
|
buildDownloadLink(share) {
|
||||||
return pubApi.getDownloadURL(share);
|
return pubApi.getDownloadURL(share);
|
||||||
|
|||||||
1
frontend/src/types/api.d.ts
vendored
1
frontend/src/types/api.d.ts
vendored
@ -27,6 +27,7 @@ interface Share {
|
|||||||
userID?: number;
|
userID?: number;
|
||||||
token?: string;
|
token?: string;
|
||||||
username?: string;
|
username?: string;
|
||||||
|
password_hash?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SearchParams {
|
interface SearchParams {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user