def show_generated_advisory(advisory_id, raw=False): entries = (db.session.query(Advisory, CVEGroup, CVEGroupPackage, CVE) .filter(Advisory.id == advisory_id) .join(CVEGroupPackage).join(CVEGroup).join(CVEGroupEntry).join(CVE) .order_by(CVE.id) ).all() if not entries: return not_found() advisory = entries[0][0] group = entries[0][1] package = entries[0][2] issues = [issue for (advisory, group, package, issue) in entries] severity_sorted_issues = sorted(issues, key=lambda issue: issue.issue_type) severity_sorted_issues = sorted(severity_sorted_issues, key=lambda issue: issue.severity) remote = any([issue.remote is Remote.remote for issue in issues]) issues_listing_formatted = (('\n{}'.format(' ' * len('CVE-ID : '))) .join(list(map(' '.join, chunks([issue.id for issue in issues], 4))))) link = TRACKER_ADVISORY_URL.format(advisory.id, group.id) upstream_released = group.affected.split('-')[0].split('+')[0] != group.fixed.split('-')[0].split('+')[0] upstream_version = group.fixed.split('-')[0].split('+')[0] if ':' in upstream_version: upstream_version = upstream_version[upstream_version.index(':') + 1:] unique_issue_types = [] for issue in severity_sorted_issues: if issue.issue_type not in unique_issue_types: unique_issue_types.append(issue.issue_type) references = [] if group.bug_ticket: references.append(TRACKER_BUGTRACKER_URL.format(group.bug_ticket)) references.extend([ref for ref in multiline_to_list(group.reference) if ref not in references]) list(map(lambda issue: references.extend( [ref for ref in multiline_to_list(issue.reference) if ref not in references]), issues)) raw_asa = render_template('advisory.txt', advisory=advisory, group=group, package=package, issues=issues, remote=remote, issues_listing_formatted=issues_listing_formatted, link=link, workaround=advisory.workaround, impact=advisory.impact, upstream_released=upstream_released, upstream_version=upstream_version, unique_issue_types=unique_issue_types, references=references, TRACKER_ISSUE_URL=TRACKER_ISSUE_URL, TRACKER_GROUP_URL=TRACKER_GROUP_URL) if raw: return raw_asa raw_asa = '\n'.join(raw_asa.split('\n')[2:]) raw_asa = str(escape(raw_asa)) raw_asa = advisory_extend_html(raw_asa, issues, package) return render_html_advisory(advisory=advisory, package=package, group=group, raw_asa=raw_asa, generated=True)
def get_bug_data(cves, pkgs, versions, group): references = [] references = [ ref for ref in multiline_to_list(group.reference) if ref not in references ] list( map( lambda issue: references.extend([ ref for ref in multiline_to_list(issue.reference) if ref not in references ]), cves)) severity_sorted_issues = sorted(cves, key=lambda issue: issue.issue_type) severity_sorted_issues = sorted(severity_sorted_issues, key=lambda issue: issue.severity) unique_issue_types = [] for issue in severity_sorted_issues: if issue.issue_type not in unique_issue_types: unique_issue_types.append(issue.issue_type) bug_desc = render_template('bug.txt', cves=cves, group=group, references=references, pkgs=pkgs, unique_issue_types=unique_issue_types, TRACKER_ISSUE_URL=TRACKER_ISSUE_URL, TRACKER_GROUP_URL=TRACKER_GROUP_URL) pkg_str = ' '.join((pkg.pkgname for pkg in pkgs)) group_type = 'multiple issues' if len( unique_issue_types) > 1 else unique_issue_types[0] summary = '[{}] [Security] {} ({})'.format( pkg_str, group_type, ' '.join([cve.id for cve in cves])) if TRACKER_SUMMARY_LENGTH_MAX != 0 and len( summary) > TRACKER_SUMMARY_LENGTH_MAX: summary = "[{}] [Security] {} (Multiple CVE's)".format( pkg_str, group_type) # 5: critical, 4: high, 3: medium, 2: low, 1: very low. severitiy_mapping = { 'unknown': 3, 'critical': 5, 'high': 4, 'medium': 3, 'low': 2, } task_severity = severitiy_mapping.get(group.severity.name) project = get_bug_project((pkg.database for pkg in versions)) return { 'project': project, 'product_category': 13, # security 'item_summary': summary, 'task_severity': task_severity, 'detailed_desc': bug_desc }
def get_bug_data(cves, pkgs, group): references = [] # TODO: add backreference to AVG tracker page references = [ ref for ref in multiline_to_list(group.reference) if ref not in references ] list( map( lambda issue: references.extend([ ref for ref in multiline_to_list(issue.reference) if ref not in references ]), cves)) severity_sorted_issues = sorted(cves, key=lambda issue: issue.issue_type) severity_sorted_issues = sorted(severity_sorted_issues, key=lambda issue: issue.severity) unique_issue_types = [] for issue in severity_sorted_issues: if issue.issue_type not in unique_issue_types: unique_issue_types.append(issue.issue_type) bug_desc = render_template('bug.txt', cves=cves, group=group, references=references, pkgs=pkgs, unique_issue_types=unique_issue_types) pkg_str = ' '.join((pkg.pkgname for pkg in pkgs)) group_type = 'multiple issues' if len( unique_issue_types) > 1 else unique_issue_types[0] summary = '[{}] [Security] {} ({})'.format( pkg_str, group_type, ' '.join([cve.id for cve in cves])) # 5: critical, 4: high, 3: medium, 2: low, 1: very low. severitiy_mapping = { 'unknown': 3, 'critical': 5, 'high': 4, 'medium': 3, 'low': 2, } task_severity = severitiy_mapping.get(group.severity.name) return { 'project': 1, # all packages 'product_category': 13, # security 'item_summary': summary, 'task_severity': task_severity, 'detailed_desc': bug_desc }
def add_group(): form = GroupForm() if not form.validate_on_submit(): return render_template('form/group.html', title='Add AVG', form=form, CVEGroup=CVEGroup) issues = [] cve_ids = multiline_to_list(form.cve.data) cve_ids = set(filter(lambda s: s.startswith('CVE-'), cve_ids)) issues = CVE.query.filter(CVE.id.in_(cve_ids)).all() issue_ids = [issue.id for issue in issues] for cve_id in list(filter(lambda issue: issue not in issue_ids, cve_ids)): cve = db.create(CVE, id=cve_id) issues.append(cve) flash('Added {}'.format(cve.id)) pkgnames = multiline_to_list(form.pkgnames.data) fixed = form.fixed.data affected = Affected.fromstring(form.status.data) status = affected_to_status(affected, pkgnames[0], fixed) severity = highest_severity([issue.severity for issue in issues]) advisory_qualified = form.advisory_qualified and status is not Status.not_affected group = db.create(CVEGroup, affected=form.affected.data, status=status, fixed=fixed, bug_ticket=form.bug_ticket.data, reference=form.reference.data, notes=form.notes.data, severity=severity, advisory_qualified=advisory_qualified) db.session.commit() for cve in issues: db.create(CVEGroupEntry, group=group, cve=cve) for pkgname in pkgnames: db.get_or_create(CVEGroupPackage, pkgname=pkgname, group=group) flash('Added {}'.format(pkgname)) db.session.commit() flash('Added {}'.format(group.name)) return redirect('/{}'.format(group.name))
def __call__(self, form, field): pkgnames = set(multiline_to_list(field.data)) pkgbases = db.session.query(Package) \ .filter(Package.name.in_(pkgnames)) \ .group_by(Package.base).all() pkgbases = [pkg.base for pkg in pkgbases] if len(pkgbases) > 1: self.fail(', '.join(pkgbases))
def __call__(self, form, field): pkgnames = set(multiline_to_list(field.data)) for pkgname in pkgnames: if not match(pkgname_regex, pkgname): self.fail(pkgname) db_packages = db.session.query(Package) \ .filter(Package.name.in_(pkgnames)) \ .group_by(Package.name).all() db_packages = set([pkg.name for pkg in db_packages]) diff = [pkg for pkg in pkgnames if pkg not in db_packages] for pkgname in diff: self.fail(pkgname)
def edit_group(avg): group_id = avg.replace('AVG-', '') group_data = (db.session.query( CVEGroup, CVE, func.group_concat(CVEGroupPackage.pkgname, ' '), Advisory).filter(CVEGroup.id == group_id).join(CVEGroupEntry).join( CVE).join(CVEGroupPackage).outerjoin( Advisory, Advisory.group_package_id == CVEGroupPackage.id).group_by( CVEGroup.id).group_by(CVE.id).order_by(CVE.id)).all() if not group_data: return not_found() group = group_data[0][0] issues = [cve for (group, cve, pkg, advisory) in group_data] issue_ids = [cve.id for cve in issues] pkgnames = set( chain.from_iterable( [pkg.split(' ') for (group, cve, pkg, advisory) in group_data])) advisories = set(advisory for (group, cve, pkg, advisory) in group_data if advisory) if not user_can_edit_group(advisories): return forbidden() form = GroupForm(pkgnames) if not form.is_submitted(): form.affected.data = group.affected form.fixed.data = group.fixed form.pkgnames.data = "\n".join(sorted(pkgnames)) form.status.data = status_to_affected(group.status).name form.reference.data = group.reference form.notes.data = group.notes form.bug_ticket.data = group.bug_ticket form.advisory_qualified.data = group.advisory_qualified and group.status is not Status.not_affected form.cve.data = "\n".join(issue_ids) if not form.validate_on_submit(): if advisories: flash( 'WARNING: This is referenced by an already published advisory!', 'warning') return render_template('form/group.html', title='Edit {}'.format(avg), form=form, CVEGroup=CVEGroup) pkgnames_edited = multiline_to_list(form.pkgnames.data) group.affected = form.affected.data group.fixed = form.fixed.data group.status = affected_to_status(Affected.fromstring(form.status.data), pkgnames_edited[0], group.fixed) group.bug_ticket = form.bug_ticket.data group.reference = form.reference.data group.notes = form.notes.data group.advisory_qualified = form.advisory_qualified.data and group.status is not Status.not_affected cve_ids = multiline_to_list(form.cve.data) cve_ids = set(filter(lambda s: s.startswith('CVE-'), cve_ids)) issues_removed = set(filter(lambda issue: issue not in cve_ids, issue_ids)) issues_added = set(filter(lambda issue: issue not in issue_ids, cve_ids)) issues_final = set( filter(lambda issue: issue.id not in issues_removed, issues)) if issues_removed: (db.session.query(CVEGroupEntry).filter( CVEGroupEntry.group_id == group.id).filter( CVEGroupEntry.cve_id.in_(issues_removed)).delete( synchronize_session=False)) for removed in issues_removed: flash('Removed {}'.format(removed)) severities = [ issue.severity for issue in list( filter(lambda issue: issue.id not in issues_removed, issues)) ] for cve_id in issues_added: cve = db.get_or_create(CVE, id=cve_id) db.get_or_create(CVEGroupEntry, group=group, cve=cve) severities.append(cve.severity) issues_final.add(cve) flash('Added {}'.format(cve.id)) group.severity = highest_severity(severities) pkgnames_removed = set( filter(lambda pkgname: pkgname not in pkgnames_edited, pkgnames)) pkgnames_added = set( filter(lambda pkgname: pkgname not in pkgnames, pkgnames_edited)) if pkgnames_removed: (db.session.query(CVEGroupPackage).filter( CVEGroupPackage.group_id == group.id).filter( CVEGroupPackage.pkgname.in_(pkgnames_removed)).delete( synchronize_session=False)) for removed in pkgnames_removed: flash('Removed {}'.format(removed)) for pkgname in pkgnames_added: db.get_or_create(CVEGroupPackage, pkgname=pkgname, group=group) flash('Added {}'.format(pkgname)) # update scheduled advisories for advisory in advisories: if Publication.published == advisory.publication: continue issue_type = 'multiple issues' if len( set([issue.issue_type for issue in issues_final])) > 1 else next( iter(issues_final)).issue_type advisory.advisory_type = issue_type db.session.commit() flash('Edited {}'.format(group.name)) return redirect('/{}'.format(group.name))
def __call__(self, form, field): issues = multiline_to_list(field.data) for issue in issues: if not match(cve_id_regex, issue): self.fail(issue)
def __call__(self, form, field): urls = multiline_to_list(field.data) for url in urls: if not self.regex.match(url): self.fail(url)
def add_group(): form = GroupForm() if not form.validate_on_submit(): return render_template('form/group.html', title='Add AVG', form=form, CVEGroup=CVEGroup) issue_ids = multiline_to_list(form.cve.data) issue_ids = set(filter(lambda s: s.startswith('CVE-'), issue_ids)) existing_issues = CVE.query.filter(CVE.id.in_(issue_ids)).all() existing_issue_ids = [issue.id for issue in existing_issues] pkgnames = multiline_to_list(form.pkgnames.data) # check if a package with a CVE clashes with an existing group if not form.force_submit.data: same_group = (db.session.query(CVEGroup, CVE, CVEGroupPackage).join( CVEGroupEntry).join(CVE).join(CVEGroupPackage).filter( CVEGroupPackage.pkgname.in_(pkgnames))) if issue_ids: same_group = same_group.filter(CVE.id.in_(issue_ids)) same_group = same_group.all() if same_group: for group, cve, package in same_group: flash( ERROR_GROUP_WITH_ISSUE_EXISTS.format( group.id, cve.id, package.pkgname), 'warning') return render_template('form/group.html', title='Add AVG', form=form, CVEGroup=CVEGroup, show_force=True) for cve_id in list( filter(lambda issue: issue not in existing_issue_ids, issue_ids)): cve = db.create(CVE, id=cve_id) existing_issues.append(cve) flash('Added {}'.format(cve.id)) fixed = form.fixed.data affected = Affected.fromstring(form.status.data) status = affected_to_status(affected, pkgnames[0], fixed) severity = highest_severity([issue.severity for issue in existing_issues]) advisory_qualified = form.advisory_qualified.data and status is not Status.not_affected group = db.create(CVEGroup, affected=form.affected.data, status=status, fixed=fixed, bug_ticket=form.bug_ticket.data, reference=form.reference.data, notes=form.notes.data, severity=severity, advisory_qualified=advisory_qualified) db.session.commit() for cve in existing_issues: db.create(CVEGroupEntry, group=group, cve=cve) for pkgname in pkgnames: db.get_or_create(CVEGroupPackage, pkgname=pkgname, group=group) flash('Added {}'.format(pkgname)) db.session.commit() flash('Added {}'.format(group.name)) return redirect('/{}'.format(group.name))