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)
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, )
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)
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, )
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)
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"))
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 )
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")
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, )
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")