CVE-2023-32685 (JavaScript, published 2023-05-30T05:15Z)
Description: value: Kanboard is project management software that focuses on the Kanban methodology. Due to improper handling of elements under the `contentEditable` element, maliciously crafted clipboard content can inject arbitrary HTML tags into the DOM. A low-privileged attacker with permission to attach a document on a vulnerable Kanboard instance can trick the victim into pasting malicious screenshot data and achieve cross-site scripting if CSP is improperly configured. This issue has been patched in version 1.2.29.

Severity: nan (CVSS v3 base score: 5.4)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/kanboard/kanboard
Files changed:
assets/js/app.min.js
assets/js/components/screenshot.js
Commit message: Remove content editable element

Non longer necessary. It works on Safari, Chrome and Firefox


Vulnerable code:
this.render=function(){componentElement=buildComponentElement();containerElement.appendChild(componentElement)}});KB.component('screenshot',function(containerElement){var pasteCatcher=null;var inputElement=null;function onFileLoaded(e){createImage(e.target.result)}
function onPaste(e){if(e.clipboardData&&e.clipboardData.items){var items=e.clipboardData.items;if(items){for(var i=0;i<items.length;i++){if(items[i].type.indexOf("image")!==-1){var blob=items[i].getAsFile();var reader=new FileReader();reader.onload=onFileLoaded;reader.readAsDataURL(blob)}}}}else{setTimeout(checkInput,100)}}
function initialize(){destroy();if(!window.Clipboard){pasteCatcher=document.createElement('template');pasteCatcher.id='screenshot-pastezone';pasteCatcher.contentEditable=!0;pasteCatcher.style.opacity=0;pasteCatcher.style.position='fixed';pasteCatcher.style.top=0;pasteCatcher.style.right=0;pasteCatcher.style.width=0;document.body.insertBefore(pasteCatcher,document.body.firstChild);pasteCatcher.focus();document.addEventListener('click',setFocus);document.getElementById('screenshot-zone').addEventListener('click',setFocus)}
window.addEventListener('paste',onPaste,!1)}
function destroy(){if(KB.exists('#screenshot-pastezone')){KB.find('#screenshot-pastezone').remove()}
document.removeEventListener('click',setFocus);pasteCatcher=null}
function setFocus(){if(pasteCatcher!==null){pasteCatcher.focus()}}
function checkInput(){var child=pasteCatcher.childNodes[0];if(child){if(child.tagName==='IMG'){createImage(child.src)}}
pasteCatcher.innerHTML=''}
function createImage(blob){var pastedImage=new Image();pastedImage.src=blob;pastedImage.onload=function(){var sourceSplit=blob.split('base64,');inputElement.value=sourceSplit[1]};var zone=document.getElementById('screenshot-zone');zone.innerHTML='';zone.className='screenshot-pasted';zone.appendChild(pastedImage);destroy();initialize()}
KB.on('modal.close',function(){destroy()});this.render=function(){inputElement=KB.dom('input').attr('type','hidden').attr('name','screenshot').build();containerElement.appendChild(inputElement);initialize()}});KB.component('select-dropdown-autocomplete',function(containerElement,options){var componentElement,inputElement,inputHiddenElement,chevronIconElement,loadingIconElement;function onLoadingStart(){KB.dom(loadingIconElement).show();KB.dom(chevronIconElement).hide()}
    var pasteCatcher = null;
        // Firefox doesn't have the property e.clipboardData.items (only Chrome)
        } else {

            // Handle Firefox
            setTimeout(checkInput, 100);
        destroy();

        if (! window.Clipboard) {
            // Insert the content editable at the top to avoid scrolling down in the board view
            pasteCatcher = document.createElement('template');
            pasteCatcher.id = 'screenshot-pastezone';
            pasteCatcher.contentEditable = true;
            pasteCatcher.style.opacity = 0;
            pasteCatcher.style.position = 'fixed';
            pasteCatcher.style.top = 0;
            pasteCatcher.style.right = 0;
            pasteCatcher.style.width = 0;
            document.body.insertBefore(pasteCatcher, document.body.firstChild);

            pasteCatcher.focus();

            // Set the focus when clicked anywhere in the document
            document.addEventListener('click', setFocus);

            // Set the focus when clicked in screenshot dropzone
            document.getElementById('screenshot-zone').addEventListener('click', setFocus);
        }

    function destroy() {
        if (KB.exists('#screenshot-pastezone')) {
            KB.find('#screenshot-pastezone').remove();
        }

        document.removeEventListener('click', setFocus);
        pasteCatcher = null;
    }
    
    function setFocus() {
        if (pasteCatcher !== null) {
            pasteCatcher.focus();
        }
    }
    
    function checkInput() {
        var child = pasteCatcher.childNodes[0];

        if (child) {
            // If the user pastes an image, the src attribute
            // will represent the image as a base64 encoded string.
            if (child.tagName === 'IMG') {
                createImage(child.src);
            }
        }

        pasteCatcher.innerHTML = '';
    }
    
        destroy();
    KB.on('modal.close', function () {
        destroy();
    });


Fixed code:
this.render=function(){componentElement=buildComponentElement();containerElement.appendChild(componentElement)}});KB.component('screenshot',function(containerElement){var inputElement=null;function onFileLoaded(e){createImage(e.target.result)}
function onPaste(e){if(e.clipboardData&&e.clipboardData.items){var items=e.clipboardData.items;if(items){for(var i=0;i<items.length;i++){if(items[i].type.indexOf("image")!==-1){var blob=items[i].getAsFile();var reader=new FileReader();reader.onload=onFileLoaded;reader.readAsDataURL(blob)}}}}}
function initialize(){window.addEventListener('paste',onPaste,!1)}
function createImage(blob){var pastedImage=new Image();pastedImage.src=blob;pastedImage.onload=function(){var sourceSplit=blob.split('base64,');inputElement.value=sourceSplit[1]};var zone=document.getElementById('screenshot-zone');zone.innerHTML='';zone.className='screenshot-pasted';zone.appendChild(pastedImage);initialize()}
this.render=function(){inputElement=KB.dom('input').attr('type','hidden').attr('name','screenshot').build();containerElement.appendChild(inputElement);initialize()}});KB.component('select-dropdown-autocomplete',function(containerElement,options){var componentElement,inputElement,inputHiddenElement,chevronIconElement,loadingIconElement;function onLoadingStart(){KB.dom(loadingIconElement).show();KB.dom(chevronIconElement).hide()}