CVE-2023-36463 (JavaScript, published 2023-06-27T20:15Z)
Description: value: Meldekarten generator is an open source project to create a program, running locally in the browser without the need for an internet-connection, to create, store and print registration cards for volunteers. All text fields on the webpage are vulnerable to XSS attacks. The user input isn't (fully) sanitized after submission. This issue has been addressed in commit `77e04f4af` which is included in the `1.0.0b1.1.2` release. Users are advised to upgrade. There are no known workarounds for this vulnerability. 
Severity: nan (CVSS v3 base score: 6.1)
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/jucktnich/meldekarten-generator
Files changed:
app.js
Commit message: Fix XSS (no working exploit found)

This is adds some checks in form of .replace function calls on some user input. I was not able to exploit the issue in a security-relevant way, i only was able to render the site completly unresponsive.

Tried exploits:
" classs="first-name" type="text" placeholder="Vorname"><script>console.log('Hello World')</script><input value="
If you click on the "Neue Person" button, the script tag gets in the HTML, the code inside of it gets never executed, so you only can only break the site, without the possibility to execute any code.

<script>console.log('Hello World')</script>
If you print the document, the field is empty, but no code gets executed

;
If you export it to a CSV-file you can add an arbitrary number of fields.

\n
Did nothing, was included in the CSV as \n and did not cause a new line.

Vulnerable code:
            if (arrayForEntry[j] != undefined) entryString += arrayForEntry[j] + ";";
                <input value="${entry.name}" class="name" type="text" placeholder="Nachname">
                <input value="${entry.firstName}" class="first-name" type="text" placeholder="Vorname">
        <input value="${entry.birthdate}" class="birthdate" type="${birthdateType}" max="${new Date().toISOString().split('T')[0]}" placeholder="Geburtsdatum"
            <label aria-label="männlich"> <input value="m" type="radio" name="sex" ${maleChecked}>♂</label>
            <label aria-label="weiblich"> <input value="f" type="radio" name="sex" ${femaleChecked}>♀</label>
            <label aria-label="divers"> <input value="d" type="radio" name="sex" ${diverseChecked}>⚧</label>
        <input value="${entry.nationality}" class="nationality" type="text" placeholder="Nationalität">
        <input value="${entry.street}" class="street" type="text" placeholder="Straße">
        <input value="${entry.zip}" class="zip" type="text" placeholder="PLZ" pattern="[0-9]{5}" inputmode="numeric">
        <input value="${entry.residency}" class="residency" type="text" placeholder="Wohnort">
        <input value="${entry.identityDisk}" aria-label="Nummer der Erkennungsmarke" class="identity-disk" type="text" placeholder="Nr. der Erk.-Marke">
        <input value="${entry.district}" class="district" type="text" placeholder="Kreisverband">
        <input value="${entry.rcUnit}" class="rc-unit" type="text" placeholder="Gemeinschaft">
        <input value="${entry.place}" class="place" type="text" placeholder="Einsatzort">
        <input value="${entry.unit}" class="unit" type="text" placeholder="Einsatzformation">
        <input value="${entry.start}" class="start" type="${startType}" placeholder="Einsatzbeginn"
            <p class="name">${entry.name}</p>
            <p class="residency">${entry.residency}</p>
            <p class="street">${entry.street}</p>
            <p class="district">${entry.district}</p>
            <p class="place">${entry.place}</p>
            <p class="first-name">${entry.firstName}</p>
            <p class="${entry.sex}">&times;</p>
            <p class="nationality">${entry.nationality}</p>
            <p class="identity-disk">${entry.identityDisk}</p>
            <p class="rc-unit">${entry.rcUnit}</p>
            <p class="unit">${entry.unit}</p>

Fixed code:
            if (arrayForEntry[j] != undefined) entryString += arrayForEntry[j].replace(/;/g, ",") + ";";
                <input value="${entry.name.replace(/"/g, "&quot;")}" class="name" type="text" placeholder="Nachname">
                <input value="${entry.firstName.replace(/"/g, "&quot;")}" class="first-name" type="text" placeholder="Vorname">
        <input value="${entry.birthdate.replace(/"/g, "&quot;")}" class="birthdate" type="${birthdateType}" max="${new Date().toISOString().split('T')[0]}" placeholder="Geburtsdatum"
            <label aria-label="männlich"> <input value="m" type="radio" name="sex" ${maleChecked.replace(/"/g, "&quot;")}>♂</label>
            <label aria-label="weiblich"> <input value="f" type="radio" name="sex" ${femaleChecked.replace(/"/g, "&quot;")}>♀</label>
            <label aria-label="divers"> <input value="d" type="radio" name="sex" ${diverseChecked.replace(/"/g, "&quot;")}>⚧</label>
        <input value="${entry.nationality.replace(/"/g, "&quot;")}" class="nationality" type="text" placeholder="Nationalität">
        <input value="${entry.street.replace(/"/g, "&quot;")}" class="street" type="text" placeholder="Straße">
        <input value="${entry.zip.replace(/"/g, "&quot;")}" class="zip" type="text" placeholder="PLZ" pattern="[0-9]{5}" inputmode="numeric">
        <input value="${entry.residency.replace(/"/g, "&quot;")}" class="residency" type="text" placeholder="Wohnort">
        <input value="${entry.identityDisk.replace(/"/g, "&quot;")}" aria-label="Nummer der Erkennungsmarke" class="identity-disk" type="text" placeholder="Nr. der Erk.-Marke">
        <input value="${entry.district.replace(/"/g, "&quot;")}" class="district" type="text" placeholder="Kreisverband">
        <input value="${entry.rcUnit.replace(/"/g, "&quot;")}" class="rc-unit" type="text" placeholder="Gemeinschaft">
        <input value="${entry.place.replace(/"/g, "&quot;")}" class="place" type="text" placeholder="Einsatzort">
        <input value="${entry.unit.replace(/"/g, "&quot;")}" class="unit" type="text" placeholder="Einsatzformation">
        <input value="${entry.start.replace(/"/g, "&quot;")}" class="start" type="${startType.replace(/"/g, "&quot;")}" placeholder="Einsatzbeginn"
            <p class="name">${entry.name.replace(/</g, "&lt;")}</p>
            <p class="residency">${entry.residency.replace(/</g, "&lt;")}</p>
            <p class="street">${entry.street.replace(/</g, "&lt;")}</p>
            <p class="district">${entry.district.replace(/</g, "&lt;")}</p>
            <p class="place">${entry.place.replace(/</g, "&lt;")}</p>
            <p class="first-name">${entry.firstName.replace(/</g, "&lt;")}</p>
            <p class="${entry.sex.replace(/</g, "&lt;")}">&times;</p>
            <p class="nationality">${entry.nationality.replace(/</g, "&lt;")}</p>
            <p class="identity-disk">${entry.identityDisk.replace(/</g, "&lt;")}</p>
            <p class="rc-unit">${entry.rcUnit.replace(/</g, "&lt;")}</p>
            <p class="unit">${entry.unit.replace(/</g, "&lt;")}</p>