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
"""PyPI-related functionality"""

import ast
import subprocess
import urllib
from urllib.parse import urlparse


import requests
import requirements


def python_requirements_dot_text_analysis(filepath):
    """Execute overall analysis of Python's requirements.txt

    Combines python-related functionality to perform end-to-end
    analysis of requirements.txt. Prints output to terminal.

    Args:
        filepath (str): filepath to a requirements.txt file

    Returns:
        None
    """
    top_level_pkgs = parse_requirements_dot_text(filepath)

    # Retrieve all dependencies, both top-level and transitive, and keep a
    # unique list
    all_pkgs = []
    for pkg in top_level_pkgs:
        all_deps = get_pypi_package_dependencies(pkg)
        for dep in all_deps:
            if dep not in all_pkgs:
                all_pkgs.append(dep)

    # retrieve github urls for unique pypi packages and store date
    # on any packages without a PyPI entry or a gitHub
    github_urls = []
    pkgs_without_pypi_data = []
    pkgs_without_githubs = []
    for pkg in all_pkgs:

        pypi_json = get_pypi_data_json(pkg)
        if not pypi_json:
            pkgs_without_pypi_data.append(pkg)

        github_url = get_github_url_from_pypi_json(pypi_json)
        if pypi_json and not github_url:
            pkgs_without_githubs.append(pkg)

        if github_url:
            github_urls.append(github_url)

    # print all results, making sure to print any packages without
    # a PyPI entry or GitHub first to ensure an informed user
    if pkgs_without_pypi_data:
        print("\nWARNING: Some of these packages are not on PyPI:")
        for pkg in pkgs_without_pypi_data:
            print(pkg)
        print("")

    if pkgs_without_githubs:
        print("\nWARNING: Some of the packages found on PyPI do not have GitHubs:")
        for pkg in pkgs_without_githubs:
            print(pkg)
        print("")

    for url in github_urls:
        print(url)


def parse_requirements_dot_text(filepath):
    """Convert requirements.txt to list of package names

    TODO: considering making this parsing more general such that
    pipfiles can be parsed too. See this library for one
    potential solution: https://github.com/sarugaku/requirementslib

    Args:
        filepath (str): filepath to a requirements.txt file

    Returns:
        pkgs: list of packages
    """

    # pylint: disable="no-member"

    pkgs = []
    with open(filepath, "r") as file:
        for req in requirements.parse(file):
            pkgs.append(req.name)

    return pkgs


def get_pypi_package_dependencies(pkg):
    """Determine dependencies for a PyPI package

    Use module pipgrip to create a dictionary of dependencies
    for a given Python package from PyPI.

    Args:
        pkg (str): the name of a python package found on PyPI

    Returns:
        dict_result: dict of package dependencies
    """
    try:
        command = f"pipgrip --json {pkg}"
        result = subprocess.run(command.split(), capture_output=True, check=True)

        # convert ouput to string and then dict
        str_result = result.stdout.decode("UTF-8")
        dict_result = ast.literal_eval(str_result)
    # if pkg doesn't exist, return empty dict
    except subprocess.CalledProcessError:
        dict_result = {}

    return dict_result


def get_pypi_data_json(pkg):
    """Return PyPI json associated with a python package.

    Args:
        pkg (str): the name of a python package found on PyPI

    Returns:
        dict: data related to a PyPI package
    """
    try:
        pkg_url = "https://pypi.org/pypi/" + pkg + "/json"
        response = requests.get(pkg_url)
        pypi_pkg_json = response.json()
    # if no package found, return empty json
    except urllib.error.HTTPError:
        pypi_pkg_json = {}

    return pypi_pkg_json


def get_github_url_from_pypi_json(pypi_pkg_json):
    """Retrieve GitHub URL associated with a PyPI json.

    Search for potential GitHub URLs, identify them,
    and then return a properly formatted GitHub repository link.

    Args:
        pypi_pkg_json: a json blob of PyPI package data

    Returns:
        str: GitHub URL
    """
    github_page = ""
    potential_github_fields = []

    # check home page url
    if "github.com" in pypi_pkg_json["info"]["home_page"]:
        potential_github_fields.append(pypi_pkg_json["info"]["home_page"])

    # check project url fields if url fields present
    if pypi_pkg_json["info"]["project_urls"]:
        for _, url in pypi_pkg_json["info"]["project_urls"].items():
            if "github.com" in url:
                potential_github_fields.append(url)

    # check PyPI description text for any GitHub mentions
    description = pypi_pkg_json["info"]["description"]
    if potential_github_fields == [] and description:
        for token in description.split():
            if "github.com" in token:
                potential_github_fields.append(token)

    for field in potential_github_fields:
        # Any field with github in it must be github link
        if "github" in field:
            github_page = field
            break

    if github_page:
        page = urlparse(github_page)
        github_page = (
            # Only extract first couple parts of github page path to avoid
            # issues page, for instance
            "https://"
            + page.netloc
            + "/"
            + "/".join(page.path.split("/")[1:3])
        )

    return github_page

```

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-776: Improper Restriction of Recursive Entity References in DTDs ('XML Entity Expansion')
  C) CWE-20: Improper Input Validation
  D) CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
  E) CWE-74: Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection')
  F) CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
Answer: C