Releases: youssefboutaleb/kanboard-file-attachment-interaction
Release list
v1.1.1
Licensing and documentation follow-up to 1.1.0. No functional change — no behaviour,
route, handler or permission check differs from 1.1.1's predecessor.
Added
- MIT license banner on
Assets/js/vendor/pptx-viewer.umd.js. The bundle shipped in every
previous release carrying no license, copyright, version or origin of any kind, which made
it indistinguishable from unattributed third-party code to anyone reviewing the archive —
a listing risk for the plugin directory. It is first-party work by the copyright holder and
is covered by this project's own MIT license.
Changed
NOTICEnow classifies each bundle inAssets/js/vendor/as first-party or third-party,
and records that docx-preview stays Apache-2.0 inside this MIT work — permitted, since
Apache-2.0 is permissive and its attribution travels with it inNOTICE.scripts/patch_pptx_viewer.jsheader rewritten: now that the bundle is known to be
first-party, the correct fix is to fold its six patches into the bundle's own source and
delete this script, rather than patching a build artifact after every rebuild.docs/kanboard-directory-submission.mdunblocked and ready to submit.docs/CONTRIBUTABILITY_REPORT.mdverdict raised to READY.
v1.1.0
Security release. Upgrading is strongly recommended for every installation.
Security
-
Fixed cross-project attachment disclosure and overwrite (object-level authorization / IDOR).
Kanboard authorizes these routes throughprojectAccessMap, which proves the caller
holds a role on theproject_idin the URL and inspects nothing aboutfile_id.
The controllers meanwhile loaded attachments withgetById($fileId), keyed on the id
alone, and only fell back to the row's owntask_id/project_idwhen the URL values
were0— so on the real routes the file's true owner was never compared to anything.Any user could therefore name a project they legitimately belong to in the path and a
foreign attachment id in the query:/b/<project the caller can access>/task/<any>/file/<file in a FOREIGN project>/previewThe ACL passed and the foreign file's bytes were previewed, streamed, opened in the
editor, or — throughFileEditController::update()— overwritten.HandlesAttachmentInteraction::assertAttachmentOwnership()now joinsfile_idto the
task and project named in the URL before any bytes are read, on all four actions
(preview,stream,edit,update). Covered bytests/Unit/AttachmentAuthorizationTest.php. -
Fixed the plugin's ACL layer being inert at runtime.
PermissionServicedefaulted toMockPermissionChecker(true)— an allow-everything
stub written for unit tests — and no controller ever injected anything else, so every
canUserReadFile()/canUserWriteFile()call returnedtruein production. The new
KanboardPermissionCheckeris backed by Kanboard's ownprojectPermissionModeland
userSessionand is installed automatically whenever the container provides them. It
fails closed: a checker that cannot reach the models it needs answers "no". -
Project viewers can no longer overwrite attachments.
canUserWriteFile()aliasedcanUserReadFile(), so read access implied write access.
Write now requiresisMember()rather thanisUserAllowed().
Added
Plugin::getCompatibleVersion()returning>=1.2.23— the release in which Kanboard
added thetemplate:project-overview:documents:dropdownhook this plugin attaches to.
Without the override, the inherited default claims compatibility with whatever core is
running and the hook fails silently on older versions.NOTICErecording the license and provenance of the bundled third-party JavaScript.tests/Integration/PackagingTest.phpandtests/bootstrap.php.
Changed
- Packaging is now an allow-list. The exclude-based rsync shipped
CLAUDE.md,
AGENTS.md,implementation_plan.md,settings.json,.phpunit.result.cacheand
154 KB ofwalkthrough.mdto end users. The archive now contains only the runtime plus
LICENSE/NOTICE/README/CHANGELOG, and the build fails if a development file
appears in it or if the archive root entry is notFileInteractionCore/. - Licensing is consistent.
LICENSEand the metadata had drifted apart — the LICENSE
file said one thing whilecomposer.jsonand the README said another. Everything now
declares MIT, matching theLICENSEfile, andtests/Integration/PackagingTest.php
fails if they ever disagree again.
Removed
Assets/js/preview-language-selector.js— a verbatim duplicate of the language-picker
handler already inpreview-controls.js. Both registered their own delegatedchange
listener, so a single language change fired twoKB.modal.replace()calls and the
modal was fetched and rebuilt twice.require_once __DIR__ . '/../../tests/stubs/BaseController.php'from
FilePreviewControllerandFileStreamController. Production classes must not
referencetests/, which the release archive excludes; the stub now loads from
tests/bootstrap.phpinstead.
Known issues
Assets/js/vendor/pptx-viewer.umd.jshas unresolved provenance — no license
banner, copyright, version or upstream identifier. SeeNOTICE. This must be closed
before the plugin is submitted to the Kanboard plugin directory or a release archive
containing it is published.
v1.0.1
Author Metadata Update & Patch Release.
Changed
- Updated plugin author metadata to Youssef BOUTALEB in
Plugin.php,composer.json, and technical specifications. - Bumped plugin version to
1.0.1.
v1.0.0
Production Architecture Refactoring, Visual Documentation & Open-Source Release.
Added
AbstractPreviewHandler: Centralized base class encapsulating size truncation, line counting, character counting, string normalization, and output escaping across all format strategies.HandlesAttachmentInteractionTrait: Shared concern trait unifying container probing, attachment metadata lookup, project ID resolution, traversal-safe storage reads, layout rendering, and error modals across controllers.CONTRIBUTING.md: Comprehensive open-source contributor guide with coding standards, architecture diagrams, step-by-step handler implementation guide, and testing workflows.- Visual Technical Diagrams:
- Security & Safety Model diagram in
README.mdanddocs/SECURITY.mdillustrating the multi-layer defense-in-depth architecture. - System Component Architecture and Interaction Lifecycle Sequence diagrams in
docs/ARCHITECTURE.md.
- Security & Safety Model diagram in
- GitHub Release & Open Source Documentation in
README.md: Complete feature breakdown, supported format table, step-by-step release archive installation, Git setup, and Docker testing. - Strategic Next-Generation Roadmap in
docs/ROADMAP.md: Strategic evolution plan spanning v1.0.0 through v2.0.0 (visual revision diffs, full-text search, external office document servers).
Changed
- Refactored all concrete handlers (
TextPreviewHandler,HtmlPreviewHandler,MarkdownPreviewHandler,JsonPreviewHandler,CodePreviewHandler,DocxPreviewHandler,PptxPreviewHandler,ExcelPreviewHandler,PdfPreviewHandler,CsvPreviewHandler) to extendAbstractPreviewHandler. - Refactored
FilePreviewController,FileEditController, andFileStreamControllerto useHandlesAttachmentInteraction. - Modernized
phpunit.xmlremoving deprecatedverboseattribute and migrating coverage nodes to PHPUnit 10<source>schema. - Bumped plugin version to
1.0.0inPlugin.php.
v0.9.0
DOCX & PPTX Document Preview Engine.
Added
- High-Fidelity In-Browser Office Document & Presentation Preview Engines:
docx-preview.min.js&jszip.min.js: Client-side high-fidelity Word document rendering preserving pagination, margins, typography, tables, drawings, and embedded images.pptx-viewer.umd.js: Client-side high-fidelity PowerPoint presentation rendering preserving slide aspect ratios, background themes, shapes, typography, tables, and slide deck layout.Assets/js/office-viewer.js: Automated controller initializing.fic-docx-containerand.fic-pptx-containerviewers, fetching binary payloads via stream routes, and providing slide navigation controls (Prev, Next, slide counter, tabs, keyboard shortcuts).- Stream route integration in
FileStreamControllerwithdocx,dotx,pptx,potxinINLINE_MIME_TYPESandMAGIC_SIGNATURES.
- OpenXML Word Document (
.docx,.dotx,.doc) Preview Engine:DocxParserService: Pure-PHP memory-safe OpenXML DOM parser extracting headings (H1-H4), formatted text runs (bold, italic, underline, strike, monospace code), bullet/numbered lists, and tables with pre-escaped HTML (htmlspecialchars()).DocxPreviewHandler: Handler for Word documents returning structured HTML and metadata (paragraphCount,headingCount,tableCount,wordCount). Gracefully detects legacy.doc(OLE2 binary format) to emit safe download notices without memory bloat.Template/file/docx_preview.php: Word Document reading pane with summary badges and clean typography.
- OpenXML PowerPoint Presentation (
.pptx,.potx,.ppt) Preview Engine:PptxParserService: Pure-PHP memory-safe presentation parser resolving slide ordering viappt/presentation.xml&ppt/_rels/presentation.xml.rels, extracting slide titles, bullet points, text blocks, and structured slide tables.PptxPreviewHandler: Handler for PowerPoint presentations returning slide deck arrays and metadata (slideCount,title). Gracefully detects legacy.pptformat.Template/file/pptx_preview.php: Interactive presentation viewer with slide switcher tabs (Slide 1,Slide 2...), active slide canvas, and presentation title header.
- Expanded Test Suite:
- 30 new unit and integration tests covering synthetic OpenXML ZIP document & presentation parsing, slide ordering, bullet point extraction, table extraction, legacy format notices, streaming MIME types, and template rendering (total 755 tests, 2562 assertions).
Changed
- Updated
FileValidationServiceto whitelistdocx,dotx,doc(10 MB cap) andpptx,potx,ppt(15 MB cap) with strict MIME mappings. - Updated
PreviewViewModeRegistrywith "Word Document" and "PowerPoint Presentation" labels. - Updated
FilePreviewControllerto registerDocxPreviewHandlerandPptxPreviewHandlerand route todocx_previewandpptx_previewtemplates. - Updated
Template/file/dropdown.phpto include docx and pptx extensions in the Safe Preview menu. - Bumped plugin version to
0.9.0inPlugin.php.
v0.6.0
Added
- Excel Spreadsheet Interactive Preview Engine:
ExcelParserService: Memory-safe.xlsxOpenXML parser extracting sheet names (xl/workbook.xml), shared string lookup tables (xl/sharedStrings.xml), and row/column data matrices capped at 100 rows x 50 columns.ExcelPreviewHandler: Handler supporting.xlsxand.xlsattachments, returning multi-sheet workbook structure and metadata.Template/file/excel_preview.php: Multi-sheet tabbed spreadsheet modal view with worksheet navigation tabs (Sheet1,Sheet2), A/B/C column headers, row index gutter, cell HTML entity escaping, and legacy format / truncation banners.- Added
'xlsx'and'xls'extensions to attachment dropdown whitelist (Template/file/dropdown.php) with 5 MB file size caps inFileValidationService.
- Expanded Test Suite:
- 39 new unit & integration tests covering OpenXML spreadsheet parsing, multi-sheet tab rendering, legacy
.xlsnotification, XSS cell escaping, and 5 MB size cap enforcement (total 279 tests, 925 assertions).
- 39 new unit & integration tests covering OpenXML spreadsheet parsing, multi-sheet tab rendering, legacy
Fixed
- Registered
ExcelPreviewHandlerinFilePreviewControllerhandler registry (7-handler registry order).
Changed
- Updated
Plugin.phpversion to0.6.0.
v0.5.0
Added
- Safe In-App Text & JSON Live Editor:
FileEditController: Live editor controller handlingedit()modal rendering andupdate()POST save actions.FileEditValidationService: Pre-save validation engine checking payload size bounds (500 KB limit) and JSON syntax error line detection (json_decode()error reporting).FileVersionService: Attachment revision engine supporting overwrite updates and versioned revision file creation (filename_v2.ext).Template/file/edit.php: Interactive editor modal view with syntax status indicators, line-number gutter, live character counters, and save mode selection (overwrite vs revision).- "Edit File" action link added to file attachment dropdown (
Template/file/dropdown.php) for text/JSON/Markdown attachments when user has write access.
- Expanded Test Suite:
- 54 new unit & integration tests covering pre-save validation, JSON syntax error estimation, version filename generation, edit modal rendering, and write ACL enforcement (total 240 tests, 789 assertions).
Changed
- Updated
Plugin.phpversion to0.5.0and registered/b/:project_id/task/:task_id/file/:file_id/editandupdateroutes.
v0.4.0
Added
- PDF Embedded Read-Only Viewer Engine:
PdfPreviewHandler: Binary-safe handler for.pdfattachments andapplication/pdf/application/x-pdfMIME types. The payload is never parsed, decoded, or executed — only size metadata is emitted.Template/file/pdf_preview.php: Embedded modal viewer streaming the document into an<object type="application/pdf">container through Kanboard core's inlineFileViewerController::browseraction.- Graceful fallback banner with a secure download link (
rel="noopener noreferrer") for browsers without an inline PDF renderer. - Dedicated 10 MB size ceiling for PDF attachments.
- Per-Extension Size Cap Mechanism:
FileValidationService::EXTENSION_MAX_SIZE_BYTESoverrides the global 500 KB default on a per-format basis;validateFileSize()accepts an optional$extensionargument.getMaxSizeForExtension()accessor, with constructor-injectable caps for testing.
- Test Suite Expansion:
- 44 new unit & integration tests covering PDF handler resolution, registration precedence, 10 MB boundary enforcement, MIME spoofing rejection, modal template dispatching, inline-vs-download URL targeting, and filename escaping (total 186 tests, 582 assertions).
Changed
- Updated
FileValidationServiceto whitelistpdf.MIME_MAP['pdf']acceptsapplication/pdf,application/x-pdf, andapplication/octet-stream, and deliberately rejectstext/*— a PDF announcing itself as renderable text is treated as a spoofing attempt. - Updated
FilePreviewControllerto register 6 format handlers withPdfPreviewHandlerFIRST, so binary payloads never fall through to theTextPreviewHandlertext/*catch-all, and to dispatchFileInteractionCore:file/pdf_preview. - Updated
Template/file/dropdown.phpto expose "Safe Preview" for.pdfattachments. - Bumped plugin version to
0.4.0inPlugin.phpandcomposer.json.
Fixed
- PDF viewer
<object>container now targets the inlinebrowseraction instead ofdownload. Thedownloadaction setsContent-Disposition: attachment, which made browsers open a save dialog instead of rendering the document inside the modal.
Build & CI
- Removed the top-level
versionfield fromcomposer.json. It madecomposer validate --strictexit non-zero, failing the GitHub Actions CI job.Plugin.php::getPluginVersion()is now the single source of truth, andscripts/package-plugin.shreads the archive version from it. dist/is now git-ignored. Release archives are published as GitHub Release assets by the new.github/workflows/release.yml, which fires onv*tag pushes, verifies the tag matchesPlugin.php, and uses the matchingCHANGELOG.mdsection as release notes.
Known Limitations
- Spec 004 AC-3 specifies a
sandboxattribute, which the HTML<object>element does not support (it is an<iframe>-only attribute). Script containment currently relies on the browser's built-in PDF viewer. Migrating the container to a sandboxed<iframe>is tracked as a follow-up.