Exemple #1
0
def vuln_view(vcdb_id=None):
    vulnerability_details = get_vulnerability_details(vcdb_id)
    view = vulnerability_details.vulnerability_view
    use_template = "vulnerability/view_details.html"
    if view.annotated:
        use_template = "vulnerability/view_overview.html"
    return render_template(use_template, vulnerability_details=vulnerability_details)
Exemple #2
0
def edit_proposal(vuln_id: str = None):
    vulnerability_details = get_vulnerability_details(None,
                                                      vuln_id,
                                                      simplify_id=False)
    view = vulnerability_details.vulnerability_view
    vuln = vulnerability_details.get_or_create_vulnerability()
    ensure(EDIT, vuln)
    form = VulnerabilityDetailsForm(obj=vuln)

    # Populate the form data from the vulnerability view if necessary.
    if form.comment.data == "":
        form.comment.data = view.comment

    if request.method == "POST" and not form.validate():
        flash_error("Your proposal contains invalid data, please correct.")

    form_submitted = form.validate_on_submit()
    if form_submitted and view.is_creator():
        new_products = update_proposal(vuln, form)
        if new_products is not None:
            view.products = [(p.vendor, p.product) for p in new_products]

    return render_template(
        "profile/edit_proposal.html",
        vulnerability_details=vulnerability_details,
        form=form,
    )
Exemple #3
0
def delete_proposal(vuln_id: str = None):
    vulnerability_details = get_vulnerability_details(None,
                                                      vuln_id,
                                                      simplify_id=False)
    vuln = vulnerability_details.get_vulnerability()
    if not vuln:
        abort(404)

    if vuln.state == VulnerabilityState.PUBLISHED:
        flash_error("Can't delete a published entry w/o reverting it first")
        return redirect(url_for("profile.view_proposals"))

    if vuln.state == VulnerabilityState.ARCHIVED:
        flash_error("Can't delete an archived")
        return redirect(url_for("profile.view_proposals"))

    ensure(DELETE, vuln)

    if (request.method != "GET"
            and request.form.get("confirm", "false").lower() == "true"):
        db.session.delete(vuln)
        db.session.commit()
        flash("Entry deleted", "success")
        return redirect(url_for("profile.view_proposals"))
    return render_template("vulnerability/delete.html",
                           vuln_view=vulnerability_details.vulnerability_view)
Exemple #4
0
def _edit_vuln_internal(vcdb_id: str = None):
    vulnerability_details = get_vulnerability_details(vcdb_id, simplify_id=False)
    view = vulnerability_details.vulnerability_view
    vuln = vulnerability_details.get_or_create_vulnerability()

    if not _can_add_proposal(vuln):
        return redirect(url_for("vuln.vuln_view", vcdb_id=vcdb_id))

    # Populate the form data from the vulnerability view if necessary.
    # Updating the vuln instance allows to easier diff the changes.
    if vuln.comment == "":
        vuln.comment = view.comment
    form = VulnerabilityDetailsForm(obj=vuln)

    form_submitted = form.validate_on_submit()
    commit = form.data["commits"][0]

    # TODO: https://github.com/google/vulncode-db/issues/95 -
    #       Add support for non github.com entries long-term again.
    if commit["commit_link"] and "github.com" not in commit["commit_link"]:
        flash_error("Entries without a github.com link are currently not supported.")
        return redirect(url_for("vuln.vuln_view", vcdb_id=vcdb_id))

    if form_submitted and commit["commit_link"]:
        vcs_handler = get_vcs_handler(None, commit["commit_link"])
        if not vcs_handler:
            flash_error("Invalid commit link specified.")
            return render_template(
                "vulnerability/edit.html",
                vulnerability_details=vulnerability_details,
                form=form,
            )

        logging.info("Found name. %r", vcs_handler.repo_name)
        form.commits[0].repo_name.process_data(vcs_handler.repo_name)
        form.commits[0].repo_url.process_data(vcs_handler.repo_url)
        form.commits[0].commit_hash.process_data(vcs_handler.commit_hash)

    if form_submitted:
        proposal_vuln = add_proposal(vuln, form)
        if proposal_vuln:
            return redirect(
                url_for(
                    "vuln.vuln_review", vcdb_id=view.id, vuln_id=proposal_vuln.vcdb_id
                )
            )

    with db.session.no_autoflush:
        return render_template(
            "vulnerability/edit.html",
            vulnerability_details=vulnerability_details,
            form=form,
        )
Exemple #5
0
def annotation_data(vcdb_id):
    vulnerability_details = get_vulnerability_details(vcdb_id)
    vulnerability_details.validate_and_simplify_id()
    view = vulnerability_details.vulnerability_view
    master_commit = view.master_commit
    if not master_commit:
        logging.error("Vuln (id: %r) has no linked Git commits!", view.id)
        return create_json_response("Entry has no linked Git link!", 404)

    master_commit = vulnerability_details.get_master_commit()
    files_schema = RepositoryFilesSchema(many=True)
    return files_schema.jsonify(master_commit.repository_files)
Exemple #6
0
def delete_vuln(vcdb_id=None):
    # TODO implement revert & delete
    del vcdb_id
    abort(404)

    vulnerability_details = get_vulnerability_details(vcdb_id, None, simplify_id=False)
    vuln = vulnerability_details.get_vulnerability()
    if not vuln:
        abort(404)

    if vuln.state == VulnerabilityState.PUBLISHED:
        flash_error("Can't delete a published entry w/o reverting it first")
        return redirect(url_for("vuln.vuln_view"))
    if vuln.state == VulnerabilityState.ARCHIVED:
        flash_error("Can't delete an archived")
        return redirect(url_for("vuln.vuln_view"))
Exemple #7
0
def vuln_file_tree(vcdb_id):
    vulnerability_details = get_vulnerability_details(vcdb_id)
    view = vulnerability_details.vulnerability_view
    master_commit = view.master_commit

    if not master_commit:
        abort(404)

    status_code = 200
    content_type = "text/json"
    response_msg = master_commit.tree_cache
    if not response_msg:
        try:
            vulnerability_details.fetch_tree_cache(skip_errors=False, max_timeout=10)
            response_msg = master_commit.tree_cache
        except urllib.error.HTTPError as err:
            status_code = err.code
            with err:
                body = repr(err.read())
            response_msg = "".join(
                [
                    "VCS proxy is unreachable (it might be down).",
                    "\r\nHTTPError\r\n",
                    body,
                ]
            )
            content_type = "text/plain"
        except urllib.error.URLError as err:
            status_code = 400
            response_msg = "".join(
                [
                    "VCS proxy is unreachable (it might be down).",
                    "\r\nURLError\r\n",
                    str(err.reason),
                ]
            )
            content_type = "text/plain"
        except Exception:  # pylint: disable=broad-except
            status_code = 400
            content_type = "text/plain"
            response_msg = "VCS proxy is unreachable (it might be down)."

    return Response(
        response=response_msg, status=status_code, content_type=content_type
    )
Exemple #8
0
def file_provider(vcdb_id):
    vulnerability_details = get_vulnerability_details(vcdb_id)
    vulnerability_details.validate_and_simplify_id()

    item_hash = request.args.get("item_hash", 0, type=str)
    item_path = request.args.get("item_path", None, type=str)

    proxy_target = cfg.GCE_VCS_PROXY_URL + url_for(
        "vcs_proxy.main_api",
        repo_url=vulnerability_details.repo_url,
        item_path=item_path,
        item_hash=item_hash,
    )[1:]
    try:
        ctx = ssl.create_default_context()
        ctx.check_hostname = False
        ctx.load_verify_locations(cafile=cfg.APP_CERT_FILE)
        ctx.verify_mode = ssl.CERT_REQUIRED
        result = urllib.request.urlopen(proxy_target, context=ctx)  # nosec
    except urllib.error.HTTPError as err:
        return Response(response=err.read(), status=err.code, content_type="text/plain")
    return send_file(result, mimetype="application/octet-stream")
Exemple #9
0
def vuln_review(vcdb_id, vuln_id):
    vulnerability_details = get_vulnerability_details(vcdb_id, simplify_id=False)
    vuln = vulnerability_details.get_or_create_vulnerability()

    proposal_vulnerability_details = get_vulnerability_details(
        None, vuln_id=vuln_id, simplify_id=False
    )
    proposal_vuln = proposal_vulnerability_details.get_or_create_vulnerability()

    ensure(READ, proposal_vuln)

    form_reject = VulnerabilityProposalReject()
    form_approve = VulnerabilityProposalApprove()
    form_assign = VulnerabilityProposalAssign()
    form_unassign = VulnerabilityProposalUnassign()
    form_publish = VulnerabilityProposalPublish()

    if request.method == "POST":
        if (
            request.form["review_response"] == "assign"
            and form_assign.validate_on_submit()
        ):
            ensure(ASSIGN, proposal_vuln)
            if proposal_vuln.is_reviewable:
                proposal_vuln.accept_review(g.user)
                db.session.add(proposal_vuln)
                db.session.commit()
                flash("The review was successfully assigned to you.", "success")
                return redirect(request.url)

            flash_error("This entry is not in a reviewable state.")

        if (
            request.form["review_response"] == "unassign"
            and form_unassign.validate_on_submit()
        ):
            ensure(ASSIGN, proposal_vuln)
            if proposal_vuln.is_reviewer(g.user):
                proposal_vuln.deny_review()
                db.session.add(proposal_vuln)
                db.session.commit()
                flash(
                    "You successfully unassigned yourself from this review.", "success"
                )
                return redirect(request.url)

            flash_error("This entry is not assigned to you.")

        if (
            request.form["review_response"] == "approve"
            and form_approve.validate_on_submit()
        ):
            ensure(APPROVE, proposal_vuln)
            proposal_vuln.accept_change()
            db.session.add(proposal_vuln)
            db.session.commit()
            flash(
                "You approved the proposal. "
                "Waiting for the entry to be published by an admin.",
                "success",
            )
            return redirect(request.url)

        if (
            request.form["review_response"] == "reject"
            and form_reject.validate_on_submit()
        ):
            ensure(REJECT, proposal_vuln)
            proposal_vuln.deny_change(g.user, form_reject.data["review_feedback"])
            db.session.add(proposal_vuln)
            db.session.commit()
            flash("Waiting for the author to address your feedback.", "success")
            return redirect(request.url)

        if (
            request.form["review_response"] == "publish"
            and form_publish.validate_on_submit()
        ):
            ensure("PUBLISH", proposal_vuln)
            proposal_vuln.publish_change()
            db.session.add(proposal_vuln)
            db.session.commit()
            # This might be the first entry of its kind
            # so no archiving is necessary.
            if vuln.state:
                vuln.archive_entry()
                db.session.add(vuln)
                db.session.commit()
            flash("Entry was successfully published.", "success")
            return redirect(request.url)

    # Published entries can't be reviewed.
    # if view.state == VulnerabilityState.PUBLISHED:
    #    raise RequestRedirect("/" + str(vcdb_id))
    return render_template(
        "vulnerability/review/review.html",
        proposal_vulnerability_details=proposal_vulnerability_details,
        vulnerability_details=vulnerability_details,
        form_assign=form_assign,
        form_unassign=form_unassign,
        form_reject=form_reject,
        form_approve=form_approve,
        form_publish=form_publish,
    )
Exemple #10
0
def vuln_editor(vcdb_id):
    vulnerability_details = get_vulnerability_details(vcdb_id)
    ensure(ANNOTATE, vulnerability_details.get_vulnerability())
    return view_vuln(vcdb_id, "vulnerability/code_editor.html")