system: You are an expert security code reviewer. You will be shown a source code file along with a multi-select question listing several CWE (Common Weakness Enumeration) categories. Your task is to identify which of the listed CWEs are present in the code.

OUTPUT FORMAT: Respond with the letter(s) of all correct options, sorted alphabetically and comma-separated, wrapped in a single \boxed{...}. Examples: `\boxed{A}` for one correct, `\boxed{A,C}` for two, `\boxed{A,C,E}` for three. Output the boxed answer ONLY -- no explanation, no other text.

user: ```python
#!/usr/bin/env python
"""
Usage:
    create_koha_csv.py <prox_report.csv> --end <YYYY-MM-DD>

Options:
    --end=DATE  last day of the semester in YYYY-MM-DD format

This script takes JSON data from Workday and maps it into a format appropriate
for import into Koha. We run it once per semester just prior to the semester's
start. Note that a few things should be manually checked:

    Ensure mappings (patron category, student major) haven't changed (see
        koha_mappings.py and new-programs.sh)
    Look up last day of the semester (expiration dates use this, captured in
        the "--end" flag when the script is run)
"""
import csv
from datetime import date, timedelta
import json
import os

from docopt import docopt
from termcolor import colored

from koha_mappings import category, fac_depts, stu_major
from koha_patron.utils import trim_first_two_lines

today = date.today()


def create_prox_map(proxfile):
    # Prox report CSV is invalid with a title line & an empty line
    trim_first_two_lines(proxfile, 'List of Changed Secondary Account Numbers')
    with open(proxfile, mode='r') as infile:
        reader = csv.reader(infile)
        next(reader) # skip header row
        # Universal ID => prox number mapping
        # Numbers in prox report have a varying number of leading zeroes, e.g.
        # "001000001", "010000001", so we strip them out
        map = {rows[0].lstrip("0"): rows[1].lstrip("0") for rows in reader if
               int(rows[1]) != 0}
        return map


def warn(string):
    print(colored('Warning: ' + string, 'red'))


def make_student_row(student):
    # some students don't have CCA emails, skip them
    # one student record in Summer 2021 lacked a last_name
    if student.get("inst_email") is None or student.get("last_name") is None:
        return None

    patron = {
        "branchcode": 'SF',
        "categorycode": category[student["academic_level"]],
        # fill in Prox number if we have it, or default to UID
        "cardnumber": prox_map.get(student["universal_id"],
                                   student["universal_id"]).strip(),
        "dateenrolled": today.isoformat(),
        "dateexpiry": args['--end'],
        "email": student["inst_email"],
        "firstname": student["first_name"],
        "patron_attributes": "UNIVID:{},STUID:{}".format(
            student["universal_id"], student["student_id"]),
        "phone": student.get("phone", ''),
        "surname": student["last_name"],
        "userid": student["username"],
    }

    # note for pre-college and skip student major calculation
    if student.get('academic_level') == 'Pre-College':
        patron['borrowernotes'] = f'Pre-college {today.year}'
    else:
        # handle student major (additional patron attribute)
        major = None
        if student["primary_program"] in stu_major:
            major = str(stu_major[student["primary_program"]])
            patron["patron_attributes"] += ',STUDENTMAJ:{}'.format(major)
        else:
            for program in student["programs"]:
                if program["program"] in stu_major:
                    major = str(stu_major[program["program"]])
                    patron["patron_attributes"] += ',STUDENTMAJ:{}'.format(major)
                    break
        # we couldn't find a major, print a warning
        if major is None:
            warn(f"""Unable to parse major for student {student["username"]}
Primary program: {student["primary_program"]}
Program credentials: {student["programs"]}""")

    return patron


def expiration_date(person):
    """Calculate patron expiration date based on personnel data and the last
    day of the semester.

    Parameters
    ----------
    person : dict
        Dict of user data. "etype" and "future_etype" are most important here.

    Returns
    -------
    str (in YYYY-MM-DD format)
        The appropriate expiration date as an ISO-8601 date string. For faculty
        added during Fall, this is Jan 31 of the next year. For faculty added
        during Spring, this is May 31 of the current year. For staff, it is the
        last day of the last month of the impending semester.

    """
    # there are 3 etypes: Staff, Instructors, Faculty. Sometimes we do not have
    # an etype but _do_ have a "future_etype".
    type = person.get('etype') or person.get('etype_future')
    if not type:
        warn(('Employee {} does not have an etype nor a etype_future. They '
               'will be assigned the Staff expiration date.'
               .format(person["username"])))
        type = 'Staff'
    d = date.fromisoformat(args['--end'])
    if type == 'Staff' or type == 'Instructors':
        # go into next month then subtract the number of days from next month
        next_mo = d.replace(day=28) + timedelta(days=4)
        return str(next_mo - timedelta(days=next_mo.day))
    else:
        # implies faculty
        # Spring => May 31
        if d.month == 5:
            return str(d.replace(day=31))
        # Fall => Jan 31 of the following year
        if d.month == 12:
            return str(d.replace(year=d.year + 1, month=1, day=31))
        # @TODO how do we handle Summer?
        else:
            raise Exception('Summer expiration dates for faculty not'
                            ' implemented yet.')
    pass


def make_employee_row(person):
    # skip 1) people who are inactive (usually hire date hasn't arrived yet),
    # 2) people w/o emails, 3) the one random record for a student
    if (person["active_status"] == "0" or not person.get("work_email") or
        person["etype"] == "Students"):
        return None

    # create a hybrid program/department field
    # some people have neither (tend to be adjuncts or special programs staff)
    person["prodep"] = None
    if person.get("program"):
        person["prodep"] = person["program"]
    elif person.get("department"):
        person["prodep"] = person["department"]
    elif person["job_profile"] in fac_depts:
        person["prodep"] = person["job_profile"]

    # skip inactive special programs faculty
    if person["job_profile"] == "Special Programs Instructor (inactive)":
        return None
    # skip contingent employees
    if person["etype"] == "Contingent Employees/Contractors":
        return None
    # we assume etype=Instructors => special programs faculty
    if (person["etype"] == "Instructors"
        and person["job_profile"] != "Special Programs Instructor"
        and person["job_profile"] != "Atelier Instructor"
        and person["job_profile"] not in fac_depts):
        warn(('Instructor {} is not a Special Programs Instructor, check '
               'record.').format(person["username"]))

    patron = {
        "branchcode": 'SF',
        "categorycode": category[person["etype"]],
        # fill in Prox number if we have it, or default to UID
        "cardnumber": prox_map.get(person["universal_id"],
                                   person["universal_id"]).strip(),
        "dateenrolled": today.isoformat(),
        # @TODO this date varies by categorycode now
        "dateexpiry": expiration_date(person),
        "email": person["work_email"],
        "firstname": person["first_name"],
        "patron_attributes": "UNIVID:" + person["universal_id"],
        "phone": person.get("phone", ''),
        "surname": person["last_name"],
        "userid": person["username"],
    }

    # handle faculty/staff department (additional patron attribute)
    if person["prodep"] and person["prodep"] in fac_depts:
        code = str(fac_depts[person["prodep"]])
        patron["patron_attributes"] += ',FACDEPT:{}'.format(code)
    elif person["prodep"]:
        # there's a non-empty program/department value we haven't accounted for
        warn("""No mapping in koha_mappings.fac_depts for faculty/staff prodep
        "{}", see patron {}""".format(person["prodep"], person["username"]))

    if person["prodep"] is None:
        warn('Employee {} has no academic program or department:'
              .format(person["username"]))
        print(person)

    return patron


def file_exists(fn):
    if not os.path.exists(fn):
            warn(f'Did not find "{fn}" file')
            return False
    return True


def proc_students(pc=False):
    if pc:
        IN_FILE = 'student_pre_college_data.json'
        prefix = ' pre-college '
    else:
        IN_FILE = 'student_data.json'
        prefix = ' '

    if file_exists(IN_FILE):
        print(f'Adding{prefix}students to Koha patron CSV.')
        with open(IN_FILE, 'r') as file:
            students = json.load(file)["Report_Entry"]
            with open(OUT_FILE, 'a') as output:
                writer = csv.DictWriter(output, fieldnames=koha_fields)
                for stu in students:
                    row = make_student_row(stu)
                    if row:
                        writer.writerow(row)


def proc_staff():
    EMP_FILE = 'employee_data.json'
    if file_exists(EMP_FILE):
        print('Adding Faculty/Staff to Koha patron CSV.')
        with open(EMP_FILE, 'r') as file:
            employees = json.load(file)["Report_Entry"]
            # open in append mode & don't add header row
            with open(OUT_FILE, 'a') as output:
                writer = csv.DictWriter(output, fieldnames=koha_fields)
                for employee in employees:
                    row = make_employee_row(employee)
                    if row:
                        writer.writerow(row)


def main():
    # write header row
    with open(OUT_FILE, 'w+') as output:
        writer = csv.DictWriter(output, fieldnames=koha_fields)
        writer.writeheader()
    proc_students()
    proc_students(pc=True)
    proc_staff()

    print('Done! Upload the CSV at '
    'https://library-staff.cca.edu/cgi-bin/koha/tools/import_borrowers.pl')


if __name__ == '__main__':
    args = docopt(__doc__, version='Create Koha CSV 1.0')
    PROX_FILE = args['<prox_report.csv>']
    if not file_exists(PROX_FILE):
        exit(1)
    prox_map = create_prox_map(PROX_FILE)
    OUT_FILE = str(today.isoformat()) + '-koha-patrons.csv'
    koha_fields = ['branchcode', 'cardnumber', 'categorycode', 'dateenrolled',
                   'dateexpiry', 'email', 'firstname', 'patron_attributes',
                   'surname', 'userid', 'phone', 'borrowernotes' ]
    main()

```

Which of the following CWE vulnerability categories are present in this code? Multiple options may be correct.

  A) CWE-295: Improper Certificate Validation
  B) CWE-209: Generation of Error Message Containing Sensitive Information
  C) CWE-215: Insertion of Sensitive Information Into Debugging Code
  D) CWE-312: Cleartext Storage of Sensitive Information
  E) CWE-377: Insecure Temporary File
  F) CWE-730: OWASP Top Ten 2004 Category A9 - Denial of Service
Answer: D