Hello community, here is the log from the commit of package python-pymisp for openSUSE:Factory checked in at 2018-05-29 10:37:57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pymisp (Old) and /work/SRC/openSUSE:Factory/.python-pymisp.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pymisp" Tue May 29 10:37:57 2018 rev:9 rq:611050 version:2.4.90.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pymisp/python-pymisp.changes 2018-05-11 14:27:52.436966469 +0200 +++ /work/SRC/openSUSE:Factory/.python-pymisp.new/python-pymisp.changes 2018-05-29 10:38:01.839749980 +0200 @@ -1,0 +2,13 @@ +Thu May 10 09:49:15 UTC 2018 - [email protected] + +- update to version 2.4.90.1: + * New + - Properly implement the Email object creator. + * Changes + - Normalize the RestResponse calls. + * Fix + - Properly get and decode the body of the email. + - Provide the extension of the EML file to attach. + - Properly handle attachments. + +------------------------------------------------------------------- Old: ---- pymisp-2.4.90.tar.gz New: ---- pymisp-2.4.90.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pymisp.spec ++++++ --- /var/tmp/diff_new_pack.mioOcH/_old 2018-05-29 10:38:02.419728567 +0200 +++ /var/tmp/diff_new_pack.mioOcH/_new 2018-05-29 10:38:02.423728420 +0200 @@ -20,7 +20,7 @@ %{!?license: %global license %doc} %bcond_without test Name: python-pymisp -Version: 2.4.90 +Version: 2.4.90.1 Release: 0 Summary: Python API for MISP License: BSD-2-Clause ++++++ pymisp-2.4.90.tar.gz -> pymisp-2.4.90.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/CHANGELOG.txt new/pymisp-2.4.90.1/CHANGELOG.txt --- old/pymisp-2.4.90/CHANGELOG.txt 2018-04-25 11:29:29.000000000 +0200 +++ new/pymisp-2.4.90.1/CHANGELOG.txt 2018-05-09 13:39:40.000000000 +0200 @@ -2,6 +2,29 @@ ========= +v2.4.90.1 (2018-05-09) +---------------------- + +New +~~~ +- Properly implement the Email object creator. [Raphaël Vinot] + +Changes +~~~~~~~ +- Version bump. [Raphaël Vinot] +- Bump misp-objects. [Raphaël Vinot] +- Bump misp-objects. [Raphaël Vinot] +- Normalize the RestResponse calls. [Raphaël Vinot] + +Fix +~~~ +- Properly get and decode the body of the email. [Raphaël Vinot] +- Provide the extension of the EML file to attach. [Raphaël Vinot] +- Properly handle attachments. [Raphaël Vinot] +- Test cases & attributes automatically getting an UUID. [Raphaël Vinot] +- Typo in the *feed methods. [Raphaël Vinot] + + v2.4.90 (2018-04-25) -------------------- @@ -22,6 +45,7 @@ Changes ~~~~~~~ +- Bump changelog. [Raphaël Vinot] - Bump version. [Raphaël Vinot] - Bump misp-objects. [Raphaël Vinot] - Add more examples. [Raphaël Vinot] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/PKG-INFO new/pymisp-2.4.90.1/PKG-INFO --- old/pymisp-2.4.90/PKG-INFO 2018-04-25 11:32:03.000000000 +0200 +++ new/pymisp-2.4.90.1/PKG-INFO 2018-05-09 13:43:02.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pymisp -Version: 2.4.90 +Version: 2.4.90.1 Summary: Python API for MISP. Home-page: https://github.com/MISP/PyMISP Author: Raphaël Vinot @@ -20,8 +20,8 @@ Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Security Classifier: Topic :: Internet +Provides-Extra: virustotal +Provides-Extra: warninglists Provides-Extra: openioc Provides-Extra: neo -Provides-Extra: warninglists Provides-Extra: fileobjects -Provides-Extra: virustotal diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/examples/add_feed.py new/pymisp-2.4.90.1/examples/add_feed.py --- old/pymisp-2.4.90/examples/add_feed.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pymisp-2.4.90.1/examples/add_feed.py 2018-05-09 13:34:36.000000000 +0200 @@ -0,0 +1,19 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from pymisp import PyMISP +from keys import misp_url, misp_key, misp_verifycert +import argparse + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Add a feed') + parser.add_argument("-f", "--format", required=True, choices=['misp', 'csv', 'freetext'], help="Feed source format") + parser.add_argument("-u", "--url", required=True, help="URL, or local path") + parser.add_argument("-n", "--name", required=True, help="Name of the feed") + parser.add_argument("-i", "--input", required=True, choices=['local', 'network'], help="URL, or local path") + parser.add_argument("-p", "--provider", required=True, help="Provider name") + args = parser.parse_args() + + pm = PyMISP(misp_url, misp_key, misp_verifycert, debug=True) + response = pm.add_feed(args.format, args.url, args.name, args.input, args.provider) + print(response) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/pymisp/__init__.py new/pymisp-2.4.90.1/pymisp/__init__.py --- old/pymisp-2.4.90/pymisp/__init__.py 2018-04-25 11:29:29.000000000 +0200 +++ new/pymisp-2.4.90.1/pymisp/__init__.py 2018-05-09 13:41:45.000000000 +0200 @@ -1,4 +1,4 @@ -__version__ = '2.4.90' +__version__ = '2.4.90.1' import logging import functools import warnings diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/pymisp/api.py new/pymisp-2.4.90.1/pymisp/api.py --- old/pymisp-2.4.90/pymisp/api.py 2018-04-25 11:29:29.000000000 +0200 +++ new/pymisp-2.4.90.1/pymisp/api.py 2018-05-09 13:34:36.000000000 +0200 @@ -1415,52 +1415,40 @@ # ############## Users ################## def get_users_list(self): - url = urljoin(self.root_url, 'admin/users') - response = self.__prepare_request('GET', url) - return self._check_response(response)['response'] + return self._rest_list('admin/users') def get_user(self, user_id): - url = urljoin(self.root_url, 'admin/users/view/{}'.format(user_id)) - response = self.__prepare_request('GET', url) - return self._check_response(response) + return self._rest_view('admin/users', user_id) def add_user(self, email, org_id, role_id, **kwargs): - url = urljoin(self.root_url, 'admin/users/add/') new_user = MISPUser() new_user.from_dict(email=email, org_id=org_id, role_id=role_id, **kwargs) - response = self.__prepare_request('POST', url, new_user.to_json()) - return self._check_response(response) + return self._rest_add('admin/users', new_user) def add_user_json(self, json_file): with open(json_file, 'r') as f: jdata = json.load(f) - url = urljoin(self.root_url, 'admin/users/add/') - response = self.__prepare_request('POST', url, json.dumps(jdata)) - return self._check_response(response) + new_user = MISPUser() + new_user.from_dict(**jdata) + return self._rest_add('admin/users', new_user) def get_user_fields_list(self): - url = urljoin(self.root_url, 'admin/users/add/') - response = self.__prepare_request('GET', url) - return self._check_response(response) + return self._rest_get_parameters('admin/users') def edit_user(self, user_id, **kwargs): edit_user = MISPUser() edit_user.from_dict(**kwargs) - url = urljoin(self.root_url, 'admin/users/edit/{}'.format(user_id)) - response = self.__prepare_request('POST', url, edit_user.to_json()) - return self._check_response(response) + return self._rest_edit('admin/users', edit_user, user_id) def edit_user_json(self, json_file, user_id): with open(json_file, 'r') as f: jdata = json.load(f) - url = urljoin(self.root_url, 'admin/users/edit/{}'.format(user_id)) - response = self.__prepare_request('POST', url, json.dumps(jdata)) - return self._check_response(response) + new_user = MISPUser() + new_user.from_dict(**jdata) + return self._rest_edit('admin/users', new_user, user_id) def delete_user(self, user_id): - url = urljoin(self.root_url, 'admin/users/delete/{}'.format(user_id)) - response = self.__prepare_request('POST', url) - return self._check_response(response) + return self._rest_delete('admin/users', user_id) # ############## Organisations ################## @@ -1468,14 +1456,10 @@ scope = scope.lower() if scope not in ["local", "external", "all"]: raise ValueError("Authorized fields are 'local','external' or 'all'") - url = urljoin(self.root_url, 'organisations/index/scope:{}'.format(scope)) - response = self.__prepare_request('GET', url) - return self._check_response(response)['response'] + return self._rest_list('organisations/index/scope:{}'.format(scope)) def get_organisation(self, organisation_id): - url = urljoin(self.root_url, 'organisations/view/{}'.format(organisation_id)) - response = self.__prepare_request('GET', url) - return self._check_response(response) + return self._rest_view('organisations', organisation_id) def add_organisation(self, name, **kwargs): new_org = MISPOrganisation() @@ -1484,40 +1468,32 @@ if new_org.get('local') is False: if 'uuid' not in new_org: raise PyMISPError('A remote org MUST have a valid uuid') - url = urljoin(self.root_url, 'admin/organisations/add/') - response = self.__prepare_request('POST', url, new_org.to_json()) - return self._check_response(response) + return self._rest_add('admin/organisations', new_org) def add_organisation_json(self, json_file): with open(json_file, 'r') as f: jdata = json.load(f) - url = urljoin(self.root_url, 'admin/organisations/add/') - response = self.__prepare_request('POST', url, json.dumps(jdata)) - return self._check_response(response) + new_org = MISPOrganisation() + new_org.from_dict(**jdata) + return self._rest_add('admin/organisations', new_org) def get_organisation_fields_list(self): - url = urljoin(self.root_url, 'admin/organisations/add/') - response = self.__prepare_request('GET', url) - return self._check_response(response) + return self._rest_get_parameters('admin/organisations') def edit_organisation(self, org_id, **kwargs): edit_org = MISPOrganisation() edit_org.from_dict(**kwargs) - url = urljoin(self.root_url, 'admin/organisations/edit/{}'.format(org_id)) - response = self.__prepare_request('POST', url, edit_org.to_json()) - return self._check_response(response) + return self._rest_edit('admin/organisations', edit_org, org_id) def edit_organisation_json(self, json_file, org_id): with open(json_file, 'r') as f: jdata = json.load(f) - url = urljoin(self.root_url, 'admin/organisations/edit/{}'.format(org_id)) - response = self.__prepare_request('POST', url, json.dumps(jdata)) - return self._check_response(response) + edit_org = MISPOrganisation() + edit_org.from_dict(**jdata) + return self._rest_edit('admin/organisations', edit_org, org_id) def delete_organisation(self, org_id): - url = urljoin(self.root_url, 'admin/organisations/delete/{}'.format(org_id)) - response = self.__prepare_request('POST', url) - return self._check_response(response) + return self._rest_delete('admin/organisations', org_id) # ############## Servers ################## @@ -1738,49 +1714,71 @@ response = self.__prepare_request('POST', url, output_type='json') return response.text + # ####################################### + # ######## RestResponse generic ######### + # ####################################### + + def _rest_list(self, urlpath): + url = urljoin(self.root_url, urlpath) + response = self.__prepare_request('GET', url) + return self._check_response(response) + + def _rest_get_parameters(self, urlpath): + url = urljoin(self.root_url, '{}/add'.format(urlpath)) + response = self.__prepare_request('GET', url) + return self._check_response(response) + + def _rest_view(self, urlpath, rest_id): + url = urljoin(self.root_url, '{}/view/{}'.format(urlpath, rest_id)) + response = self.__prepare_request('GET', url) + return self._check_response(response) + + def _rest_add(self, urlpath, obj): + url = urljoin(self.root_url, '{}/add'.format(urlpath)) + response = self.__prepare_request('POST', url, obj.to_json()) + return self._check_response(response) + + def _rest_edit(self, urlpath, obj, rest_id): + url = urljoin(self.root_url, '{}/edit/{}'.format(urlpath, rest_id)) + response = self.__prepare_request('POST', url, obj.to_json()) + return self._check_response(response) + + def _rest_delete(self, urlpath, rest_id): + url = urljoin(self.root_url, '{}/delete/{}'.format(urlpath, rest_id)) + response = self.__prepare_request('GET', url) + return self._check_response(response) + # ########################### # ######## Feed ######### # ########################### def get_feeds_list(self): """Get the content of all the feeds""" - url = urljoin(self.root_url, 'feeds') - response = self.__prepare_request('GET', url) - return self._check_response(response) + return self._rest_list('feeds') - def get_feed(self, feed_ids): + def get_feed(self, feed_id): """Get the content of a single feed""" - url = urljoin(self.root_url, 'feeds/view/{}'.format(feed_ids)) - response = self.__prepare_request('GET', url) - return self._check_response(response) + return self._rest_view('feeds', feed_id) def add_feed(self, source_format, url, name, input_source, provider, **kwargs): """Delete a feed""" - url = urljoin(self.root_url, 'feeds/add') new_feed = MISPFeed() new_feed.from_dict(source_format=source_format, url=url, name=name, input_source=input_source, provider=provider) - response = self.__prepare_request('POST', url, new_feed.to_json()) - return self._check_response(response) + return self._rest_add('feeds', new_feed) def get_feed_fields_list(self): - url = urljoin(self.root_url, 'feeds/add/') - response = self.__prepare_request('GET', url) - return self._check_response(response) + return self._rest_get_parameters('feeds') def edit_feed(self, feed_id, **kwargs): """Delete a feed""" - url = urljoin(self.root_url, 'feeds/edit/{}'.format(feed_id)) edit_feed = MISPFeed() edit_feed.from_dict(**kwargs) - response = self.__prepare_request('POST', url, edit_feed.to_json()) - return self._check_response(response) + return self._rest_edit('feeds', edit_feed) def delete_feed(self, feed_id): """Delete a feed""" - url = urljoin(self.root_url, 'feeds/delete/{}'.format(feed_id)) - response = self.__prepare_request('GET', url) - return self._check_response(response) + return self._rest_delete('feeds', feed_id) def fetch_feed(self, feed_id): """Fetch one single feed""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/pymisp/data/misp-objects/objects/email/definition.json new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/email/definition.json --- old/pymisp-2.4.90/pymisp/data/misp-objects/objects/email/definition.json 2018-04-25 11:30:42.000000000 +0200 +++ new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/email/definition.json 2018-05-09 13:34:43.000000000 +0200 @@ -3,7 +3,7 @@ "uuid": "a0c666e0-fc65-4be8-b48f-3423d788b552", "meta-category": "network", "description": "Email object describing an email with meta-information", - "version": 8, + "version": 11, "attributes": { "reply-to": { "description": "Email address the reply will be sent to", @@ -16,6 +16,7 @@ "message-id": { "description": "Message ID", "misp-attribute": "email-message-id", + "disable_correlation": true, "ui-priority": 0, "categories": [ "Payload delivery" @@ -24,6 +25,7 @@ "to": { "description": "Destination email address", "misp-attribute": "email-dst", + "disable_correlation": true, "ui-priority": 1, "categories": [ "Payload delivery" @@ -33,6 +35,7 @@ "cc": { "description": "Carbon copy", "misp-attribute": "email-dst", + "disable_correlation": true, "ui-priority": 1, "categories": [ "Payload delivery" @@ -59,6 +62,7 @@ "screenshot": { "description": "Screenshot of email", "misp-attribute": "attachment", + "disable_correlation": true, "ui-priority": 1, "categories": [ "External analysis" @@ -76,6 +80,7 @@ "x-mailer": { "description": "X-Mailer generally tells the program that was used to draft and send the original email", "misp-attribute": "email-x-mailer", + "disable_correlation": true, "ui-priority": 0, "categories": [ "Payload delivery" @@ -84,6 +89,7 @@ "header": { "description": "Full headers", "misp-attribute": "email-header", + "disable_correlation": true, "ui-priority": 0, "categories": [ "Payload delivery" @@ -102,6 +108,7 @@ "mime-boundary": { "description": "MIME Boundary", "misp-attribute": "email-mime-boundary", + "disable_correlation": true, "ui-priority": 0, "categories": [ "Payload delivery" @@ -110,6 +117,7 @@ "thread-index": { "description": "Identifies a particular conversation thread", "misp-attribute": "email-thread-index", + "disable_correlation": true, "ui-priority": 0, "categories": [ "Payload delivery" @@ -125,7 +133,7 @@ }, "return-path": { "description": "Message return path", - "misp-attribute": "text", + "misp-attribute": "email-src", "ui-priority": 1, "categories": [ "Payload delivery" @@ -142,10 +150,23 @@ "email-body": { "description": "Body of the email", "misp-attribute": "email-body", + "disable_correlation": true, "ui-priority": 1, "categories": [ "Payload delivery" ] + }, + "user-agent": { + "description": "User Agent of the sender", + "misp-attribute": "text", + "ui-priority": 0, + "disable_correlation": true + }, + "eml": { + "description": "Full EML", + "misp-attribute": "attachment", + "disable_correlation": true, + "ui-priority": 1 } }, "requiredOneOf": [ @@ -163,6 +184,8 @@ "thread-index", "header", "x-mailer", - "return-path" + "return-path", + "email-body", + "eml" ] } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/pymisp/data/misp-objects/objects/network-connection/definition.json new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/network-connection/definition.json --- old/pymisp-2.4.90/pymisp/data/misp-objects/objects/network-connection/definition.json 1970-01-01 01:00:00.000000000 +0100 +++ new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/network-connection/definition.json 2018-05-09 13:34:54.000000000 +0200 @@ -0,0 +1,96 @@ +{ + "name": "network-connection", + "uuid": "af16764b-f8e5-4603-9de1-de34d272f80b", + "meta-category": "network", + "description": "A local or remote network connection.", + "version": 1, + "attributes": { + "ip-src": { + "description": "Source IP address of the nework connection.", + "ui-priority": 1, + "categories": [ + "Network activity", + "External analysis" + ], + "misp-attribute": "ip-src" + }, + "ip-dst": { + "description": "Destination IP address of the nework connection.", + "ui-priority": 1, + "categories": [ + "Network activity", + "External analysis" + ], + "misp-attribute": "ip-dst" + }, + "src-port": { + "description": "Source port of the nework connection.", + "ui-priority": 1, + "categories": [ + "Network activity", + "External analysis" + ], + "misp-attribute": "port" + }, + "dst-port": { + "description": "Destination port of the nework connection.", + "ui-priority": 1, + "categories": [ + "Network activity", + "External analysis" + ], + "misp-attribute": "port" + }, + "hostname-src": { + "description": "Source hostname of the network connection.", + "ui-priority": 1, + "misp-attribute": "hostname" + }, + "hostname-dst": { + "description": "Destination hostname of the network connection.", + "ui-priority": 1, + "misp-attribute": "hostname" + }, + "layer3-protocol": { + "description": "Layer 3 protocol of the network connection.", + "ui-priority": 0, + "sane_default": [ + "IP", + "ICMP", + "ARP" + ], + "misp-attribute": "text" + }, + "layer4-protocol": { + "description": "Layer 4 protocol of the network connection.", + "ui-priority": 0, + "sane_default": [ + "TCP", + "UDP" + ], + "misp-attribute": "text" + }, + "layer7-protocol": { + "description": "Layer 7 protocol of the network connection.", + "ui-priority": 0, + "sane_default": [ + "HTTP", + "HTTPS", + "FTP" + ], + "misp-attribute": "text" + }, + "first-packet-seen": { + "misp-attribute": "datetime", + "ui-priority": 1, + "description": "Datetime of the first packet seen." + } + }, + "requiredOneOf": [ + "first-packet-seen", + "ip-src", + "ip-dst", + "src-port", + "dst-port" + ] +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/pymisp/data/misp-objects/objects/network-socket/definition.json new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/network-socket/definition.json --- old/pymisp-2.4.90/pymisp/data/misp-objects/objects/network-socket/definition.json 1970-01-01 01:00:00.000000000 +0100 +++ new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/network-socket/definition.json 2018-05-09 13:34:54.000000000 +0200 @@ -0,0 +1,194 @@ +{ + "name": "network-socket", + "uuid": "48bbfd72-ef8e-4649-b14d-41b4b5a0eba2", + "meta-category": "network", + "description": "Network socket object describes a local or remote network connections based on the socket data structure.", + "version": 1, + "attributes": { + "ip-src": { + "description": "Source (local) IP address of the network socket connection.", + "ui-priority": 1, + "categories": [ + "Network activity", + "External analysis" + ], + "misp-attribute": "ip-src" + }, + "hostname-src": { + "description": "Source (local) hostname of the network socket connection.", + "ui-priority": 1, + "misp-attribute": "hostname" + }, + "ip-dst": { + "description": "Destination IP address of the network socket connection.", + "ui-priority": 1, + "categories": [ + "Network activity", + "External analysis" + ], + "misp-attribute": "ip-dst" + }, + "hostname-dst": { + "description": "Destination hostname of the network socket connection.", + "ui-priority": 1, + "misp-attribute": "hostname" + }, + "src-port": { + "description": "Source (local) port of the network socket connection.", + "ui-priority": 1, + "categories": [ + "Network activity", + "External analysis" + ], + "misp-attribute": "port" + }, + "dst-port": { + "description": "Destination port of the network socket connection.", + "ui-priority": 1, + "categories": [ + "Network activity", + "External analysis" + ], + "misp-attribute": "port" + }, + "protocol": { + "misp-attribute": "text", + "ui-priority": 0, + "values_list": [ + "TCP", + "UDP", + "ICMP", + "IP" + ], + "description": "Protocol used by the network socket." + }, + "address-family": { + "description": "Address family who specifies the address family type (AF_*) of the socket connection.", + "ui-priority": 1, + "sane_default": [ + "AF_UNSPEC", + "AF_LOCAL", + "AF_UNIX", + "AF_FILE", + "AF_INET", + "AF_AX25", + "AF_IPX", + "AF_APPLETALK", + "AF_NETROM", + "AF_BRIDGE", + "AF_ATMPVC", + "AF_X25", + "AF_INET6", + "AF_ROSE", + "AF_DECnet", + "AF_NETBEUI", + "AF_SECURITY", + "AF_KEY", + "AF_NETLINK", + "AF_ROUTE", + "AF_PACKET", + "AF_ASH", + "AF_ECONET", + "AF_ATMSVC", + "AF_RDS", + "AF_SNA", + "AF_IRDA", + "AF_PPPOX", + "AF_WANPIPE", + "AF_LLC", + "AF_IB", + "AF_MPLS", + "AF_CAN", + "AF_TIPC", + "AF_BLUETOOTH", + "AF_IUCV", + "AF_RXRPC", + "AF_ISDN", + "AF_PHONET", + "AF_IEEE802154", + "AF_CAIF", + "AF_ALG", + "AF_NFC", + "AF_VSOCK", + "AF_KCM", + "AF_MAX" + ], + "misp-attribute": "text" + }, + "domain-family": { + "description": "Domain family who specifies the communication domain (PF_*) of the socket connection.", + "ui-priority": 1, + "sane_default": [ + "PF_UNSPEC", + "PF_LOCAL", + "PF_UNIX", + "PF_FILE", + "PF_INET", + "PF_AX25", + "PF_IPX", + "PF_APPLETALK", + "PF_NETROM", + "PF_BRIDGE", + "PF_ATMPVC", + "PF_X25", + "PF_INET6", + "PF_ROSE", + "PF_DECnet", + "PF_NETBEUI", + "PF_SECURITY", + "PF_KEY", + "PF_NETLINK", + "PF_ROUTE", + "PF_PACKET", + "PF_ASH", + "PF_ECONET", + "PF_ATMSVC", + "PF_RDS", + "PF_SNA", + "PF_IRDA", + "PF_PPPOX", + "PF_WANPIPE", + "PF_LLC", + "PF_IB", + "PF_MPLS", + "PF_CAN", + "PF_TIPC", + "PF_BLUETOOTH", + "PF_IUCV", + "PF_RXRPC", + "PF_ISDN", + "PF_PHONET", + "PF_IEEE802154", + "PF_CAIF", + "PF_ALG", + "PF_NFC", + "PF_VSOCK", + "PF_KCM", + "PF_MAX" + ], + "misp-attribute": "text" + }, + "state": { + "description": "State of the socket connection.", + "multiple": true, + "sane_default": [ + "blocking", + "listening" + ], + "misp-attribute": "text", + "ui-priority": 1 + }, + "option": { + "description": "Option on the socket connection.", + "multiple": true, + "misp-attribute": "text", + "ui-priority": 1 + } + }, + "requiredOneOf": [ + "ip-src", + "ip-dst", + "src-port", + "dst-port" + ] +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/pymisp/data/misp-objects/objects/process/definition.json new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/process/definition.json --- old/pymisp-2.4.90/pymisp/data/misp-objects/objects/process/definition.json 1970-01-01 01:00:00.000000000 +0100 +++ new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/process/definition.json 2018-05-09 13:34:54.000000000 +0200 @@ -0,0 +1,52 @@ +{ + "name": "process", + "uuid": "02aeef94-ac23-455c-addb-731757ceafb5", + "meta-category": "misc", + "description": "Object describing a system process.", + "version": 1, + "attributes": { + "creation-time": { + "description": "Local date/time at which the process was created.", + "ui-priority": 0, + "misp-attribute": "datetime", + "disable_correlation": true + }, + "start-time": { + "description": "Local date/time at which the process was started.", + "ui-priority": 0, + "misp-attribute": "datetime", + "disable_correlation": true + }, + "name": { + "description": "Name of the process", + "ui-priority": 1, + "misp-attribute": "text" + }, + "pid": { + "description": "Process ID of the process.", + "ui-priority": 1, + "misp-attribute": "text" + }, + "parent_pid": { + "description": "Process ID of the parent process.", + "ui-priority": 1, + "misp-attribute": "text" + }, + "child-pid": { + "description": "Process ID of the child(ren) process.", + "ui-priority": 1, + "misp-attribute": "text", + "multiple": true + }, + "port": { + "description": "Port(s) owned by the process.", + "ui-priority": 1, + "misp-attribute": "src-port", + "multiple": true + } + }, + "requiredOneOf": [ + "name", + "pid" + ] +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/pymisp/data/misp-objects/objects/ss7-attack/definition.json new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/ss7-attack/definition.json --- old/pymisp-2.4.90/pymisp/data/misp-objects/objects/ss7-attack/definition.json 2018-04-25 11:30:42.000000000 +0200 +++ new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/ss7-attack/definition.json 2018-05-09 13:34:54.000000000 +0200 @@ -34,6 +34,7 @@ }, "SccpCgGT": { "description": "Signaling Connection Control Part (SCCP) CgGT - Phone number.", + "multiple": true, "ui-priority": 0, "misp-attribute": "text" }, @@ -44,6 +45,7 @@ }, "SccpCgPC": { "description": "Signaling Connection Control Part (SCCP) CgPC - Phone number.", + "multiple": true, "ui-priority": 0, "misp-attribute": "text" }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/pymisp/data/misp-objects/objects/timestamp/definition.json new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/timestamp/definition.json --- old/pymisp-2.4.90/pymisp/data/misp-objects/objects/timestamp/definition.json 1970-01-01 01:00:00.000000000 +0100 +++ new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/timestamp/definition.json 2018-05-09 13:34:43.000000000 +0200 @@ -0,0 +1,45 @@ +{ + "requiredOneOf": [ + "first-seen", + "last-seen" + ], + "attributes": { + "text": { + "description": "Description of the time object.", + "ui-priority": 0, + "misp-attribute": "text", + "disable_correlation": true + }, + "precision": { + "description": "Timestamp precision represents the precision given to first_seen and/or last_seen in this object.", + "ui-priority": 0, + "misp-attribute": "text", + "sane_default": [ + "year", + "month", + "day", + "hour", + "minute", + "full" + ], + "disable_correlation": true + }, + "first-seen": { + "description": "First time that the linked object or attribute has been seen.", + "ui-priority": 0, + "misp-attribute": "datetime", + "disable_correlation": true + }, + "last-seen": { + "description": "First time that the linked object or attribute has been seen.", + "ui-priority": 0, + "misp-attribute": "datetime", + "disable_correlation": true + } + }, + "version": 1, + "description": "A generic timestamp object to represent time including first time and last time seen. Relationship will then define the kind of time relationship.", + "meta-category": "misc", + "uuid": "c8c91e23-4221-4533-8bf7-64e12b05f265", + "name": "timestamp" +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/pymisp/data/misp-objects/objects/whois/definition.json new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/whois/definition.json --- old/pymisp-2.4.90/pymisp/data/misp-objects/objects/whois/definition.json 2018-04-25 11:30:42.000000000 +0200 +++ new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/whois/definition.json 2018-05-09 13:34:43.000000000 +0200 @@ -74,6 +74,7 @@ "External analysis" ], "ui-priority": 0, + "multiple": true, "misp-attribute": "domain" }, "comment": { @@ -84,10 +85,11 @@ "ip-address": { "description": "IP address of the whois entry", "ui-priority": 0, + "multiple": true, "misp-attribute": "ip-src" } }, - "version": 9, + "version": 10, "description": "Whois records information for a domain name or an IP address.", "meta-category": "network", "uuid": "429faea1-34ff-47af-8a00-7c62d3be5a6a", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/pymisp/data/misp-objects/objects/yara/definition.json new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/yara/definition.json --- old/pymisp-2.4.90/pymisp/data/misp-objects/objects/yara/definition.json 2018-04-25 11:30:42.000000000 +0200 +++ new/pymisp-2.4.90.1/pymisp/data/misp-objects/objects/yara/definition.json 2018-05-09 13:34:43.000000000 +0200 @@ -20,9 +20,20 @@ "description": "Version of the YARA rule depending where the yara rule is known to work as expected.", "ui-priority": 0, "misp-attribute": "text" + }, + "context": { + "description": "Context where the YARA rule can be applied", + "sane_default": [ + "all", + "disk", + "memory", + "network" + ], + "misp-attribute": "text", + "ui-priority": 0 } }, - "version": 2, + "version": 3, "description": "An object describing a YARA rule along with its version.", "meta-category": "misc", "uuid": "b5acf82e-ecca-4868-82fe-9dbdf4d808c3", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/pymisp/mispevent.py new/pymisp-2.4.90.1/pymisp/mispevent.py --- old/pymisp-2.4.90/pymisp/mispevent.py 2018-04-25 11:29:29.000000000 +0200 +++ new/pymisp-2.4.90.1/pymisp/mispevent.py 2018-05-09 13:34:36.000000000 +0200 @@ -101,6 +101,7 @@ self.__category_type_mapping = describe_types['category_type_mappings'] self.__sane_default = describe_types['sane_defaults'] self.__strict = strict + self.uuid = str(uuid.uuid4()) self.ShadowAttribute = [] @property @@ -133,7 +134,7 @@ def add_proposal(self, shadow_attribute=None, **kwargs): """Alias for add_shadow_attribute""" - self.add_shadow_attribute(shadow_attribute, **kwargs) + return self.add_shadow_attribute(shadow_attribute, **kwargs) def add_shadow_attribute(self, shadow_attribute=None, **kwargs): """Add a tag to the attribute (by name or a MISPTag object)""" @@ -149,6 +150,7 @@ raise PyMISPError("The shadow_attribute is in an invalid format (can be either string, MISPShadowAttribute, or an expanded dict): {}".format(shadow_attribute)) self.shadow_attributes.append(misp_shadow_attribute) self.edited = True + return misp_shadow_attribute def from_dict(self, **kwargs): if kwargs.get('type') and kwargs.get('category'): @@ -533,7 +535,7 @@ def add_proposal(self, shadow_attribute=None, **kwargs): """Alias for add_shadow_attribute""" - self.add_shadow_attribute(shadow_attribute, **kwargs) + return self.add_shadow_attribute(shadow_attribute, **kwargs) def add_shadow_attribute(self, shadow_attribute=None, **kwargs): """Add a tag to the attribute (by name or a MISPTag object)""" @@ -549,6 +551,7 @@ raise PyMISPError("The shadow_attribute is in an invalid format (can be either string, MISPShadowAttribute, or an expanded dict): {}".format(shadow_attribute)) self.shadow_attributes.append(misp_shadow_attribute) self.edited = True + return misp_shadow_attribute def get_attribute_tag(self, attribute_identifier): '''Return the tags associated to an attribute or an object attribute. @@ -605,14 +608,18 @@ def add_attribute(self, type, value, **kwargs): """Add an attribute. type and value are required but you can pass all other parameters supported by MISPAttribute""" + attr_list = [] if isinstance(value, list): - for a in value: - self.add_attribute(type=type, value=a, **kwargs) + attr_list = [self.add_attribute(type=type, value=a, **kwargs) for a in value] else: attribute = MISPAttribute() attribute.from_dict(type=type, value=value, **kwargs) self.attributes.append(attribute) self.edited = True + if attr_list: + return attr_list + else: + return attribute def get_object_by_id(self, object_id): """Get an object by ID (the ID is the one set by the server when creating the new object)""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/pymisp/tools/emailobject.py new/pymisp-2.4.90.1/pymisp/tools/emailobject.py --- old/pymisp-2.4.90/pymisp/tools/emailobject.py 2018-04-25 11:29:29.000000000 +0200 +++ new/pymisp-2.4.90.1/pymisp/tools/emailobject.py 2018-05-09 13:34:36.000000000 +0200 @@ -5,28 +5,43 @@ from .abstractgenerator import AbstractMISPObjectGenerator from io import BytesIO import logging -from email import message_from_bytes +from email import message_from_bytes, policy logger = logging.getLogger('pymisp') class EMailObject(AbstractMISPObjectGenerator): - def __init__(self, filepath=None, pseudofile=None, standalone=True, **kwargs): + def __init__(self, filepath=None, pseudofile=None, attach_original_email=True, standalone=True, **kwargs): if filepath: with open(filepath, 'rb') as f: - pseudofile = BytesIO(f.read()) + self.__pseudofile = BytesIO(f.read()) elif pseudofile and isinstance(pseudofile, BytesIO): - pseudofile = pseudofile + self.__pseudofile = pseudofile else: raise InvalidMISPObject('File buffer (BytesIO) or a path is required.') # PY3 way: # super().__init__('file') super(EMailObject, self).__init__('email', standalone=standalone, **kwargs) - self.__email = message_from_bytes(pseudofile.getvalue()) + self.__email = message_from_bytes(self.__pseudofile.getvalue(), policy=policy.default) + if attach_original_email: + self.add_attribute('eml', value='Full email.eml', data=self.__pseudofile) self.generate_attributes() + @property + def email(self): + return self.__email + + @property + def attachments(self): + to_return = [] + for attachment in self.__email.iter_attachments(): + to_return.append((attachment.get_filename(), BytesIO(attachment.get_content()))) + return to_return + def generate_attributes(self): + if self.__email.get_body(preferencelist=('html', 'plain')): + self.add_attribute('email-body', value=self.__email.get_body(preferencelist=('html', 'plain')).get_payload(decode=True).decode()) if 'Reply-To' in self.__email: self.add_attribute('reply-to', value=self.__email['Reply-To']) if 'Message-ID' in self.__email: @@ -44,4 +59,5 @@ self.add_attribute('from', value=e_from.strip()) if 'Return-Path' in self.__email: self.add_attribute('return-path', value=self.__email['Return-Path']) - # TODO: self.add_attribute('attachment', value=) + if 'User-Agent' in self.__email: + self.add_attribute('user-agent', value=self.__email['User-Agent']) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/pymisp.egg-info/PKG-INFO new/pymisp-2.4.90.1/pymisp.egg-info/PKG-INFO --- old/pymisp-2.4.90/pymisp.egg-info/PKG-INFO 2018-04-25 11:32:03.000000000 +0200 +++ new/pymisp-2.4.90.1/pymisp.egg-info/PKG-INFO 2018-05-09 13:43:02.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pymisp -Version: 2.4.90 +Version: 2.4.90.1 Summary: Python API for MISP. Home-page: https://github.com/MISP/PyMISP Author: Raphaël Vinot @@ -20,8 +20,8 @@ Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Security Classifier: Topic :: Internet +Provides-Extra: virustotal +Provides-Extra: warninglists Provides-Extra: openioc Provides-Extra: neo -Provides-Extra: warninglists Provides-Extra: fileobjects -Provides-Extra: virustotal diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/pymisp.egg-info/SOURCES.txt new/pymisp-2.4.90.1/pymisp.egg-info/SOURCES.txt --- old/pymisp-2.4.90/pymisp.egg-info/SOURCES.txt 2018-04-25 11:32:03.000000000 +0200 +++ new/pymisp-2.4.90.1/pymisp.egg-info/SOURCES.txt 2018-05-09 13:43:02.000000000 +0200 @@ -15,6 +15,7 @@ examples/__init__.py examples/add_email_object.py examples/add_fail2ban_object.py +examples/add_feed.py examples/add_file_object.py examples/add_generic_object.py examples/add_named_attribute.py @@ -155,12 +156,15 @@ pymisp/data/misp-objects/objects/microblog/definition.json pymisp/data/misp-objects/objects/mutex/definition.json pymisp/data/misp-objects/objects/netflow/definition.json +pymisp/data/misp-objects/objects/network-connection/definition.json +pymisp/data/misp-objects/objects/network-socket/definition.json pymisp/data/misp-objects/objects/passive-dns/definition.json pymisp/data/misp-objects/objects/paste/definition.json pymisp/data/misp-objects/objects/pe/definition.json pymisp/data/misp-objects/objects/pe-section/definition.json pymisp/data/misp-objects/objects/person/definition.json pymisp/data/misp-objects/objects/phone/definition.json +pymisp/data/misp-objects/objects/process/definition.json pymisp/data/misp-objects/objects/r2graphity/definition.json pymisp/data/misp-objects/objects/regexp/definition.json pymisp/data/misp-objects/objects/registry-key/definition.json @@ -172,6 +176,7 @@ pymisp/data/misp-objects/objects/stix2-pattern/definition.json pymisp/data/misp-objects/objects/suricata/definition.json pymisp/data/misp-objects/objects/target-system/definition.json +pymisp/data/misp-objects/objects/timestamp/definition.json pymisp/data/misp-objects/objects/tor-node/definition.json pymisp/data/misp-objects/objects/transaction/definition.json pymisp/data/misp-objects/objects/url/definition.json diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/tests/mispevent_testfiles/def_param.json new/pymisp-2.4.90.1/tests/mispevent_testfiles/def_param.json --- old/pymisp-2.4.90/tests/mispevent_testfiles/def_param.json 2018-04-25 11:29:29.000000000 +0200 +++ new/pymisp-2.4.90.1/tests/mispevent_testfiles/def_param.json 2018-05-09 13:34:36.000000000 +0200 @@ -42,7 +42,7 @@ "name": "whois", "sharing_group_id": 0, "template_uuid": "429faea1-34ff-47af-8a00-7c62d3be5a6a", - "template_version": 9, + "template_version": 10, "uuid": "a" } ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/tests/test_mispevent.py new/pymisp-2.4.90.1/tests/test_mispevent.py --- old/pymisp-2.4.90/tests/test_mispevent.py 2018-01-28 20:54:54.000000000 +0100 +++ new/pymisp-2.4.90.1/tests/test_mispevent.py 2018-05-09 13:34:36.000000000 +0200 @@ -54,8 +54,9 @@ def test_attribute(self): self.init_event() - self.mispevent.add_attribute('filename', 'bar.exe') - self.mispevent.add_attribute_tag('osint', 'bar.exe') + a = self.mispevent.add_attribute('filename', 'bar.exe') + del a.uuid + a = self.mispevent.add_attribute_tag('osint', 'bar.exe') attr_tags = self.mispevent.get_attribute_tag('bar.exe') self.assertEqual(self.mispevent.attributes[0].tags[0].name, 'osint') self.assertEqual(attr_tags[0].name, 'osint') @@ -71,12 +72,14 @@ def test_object_tag(self): self.mispevent.add_object(name='file', strict=True) - self.mispevent.objects[0].add_attribute('filename', value='bar', Tag=[{'name': 'blah'}]) + a = self.mispevent.objects[0].add_attribute('filename', value='bar', Tag=[{'name': 'blah'}]) + del a.uuid self.assertEqual(self.mispevent.objects[0].attributes[0].tags[0].name, 'blah') self.assertTrue(self.mispevent.objects[0].has_attributes_by_relation(['filename'])) self.assertEqual(len(self.mispevent.objects[0].get_attributes_by_relation('filename')), 1) self.mispevent.add_object(name='url', strict=True) - self.mispevent.objects[1].add_attribute('url', value='https://www.circl.lu') + a = self.mispevent.objects[1].add_attribute('url', value='https://www.circl.lu') + del a.uuid self.mispevent.objects[0].uuid = 'a' self.mispevent.objects[1].uuid = 'b' self.mispevent.objects[0].add_reference('b', 'baz', comment='foo') @@ -99,7 +102,8 @@ with open('tests/mispevent_testfiles/simple.json', 'rb') as f: pseudofile = BytesIO(f.read()) self.init_event() - self.mispevent.add_attribute('malware-sample', 'bar.exe', data=pseudofile) + a = self.mispevent.add_attribute('malware-sample', 'bar.exe', data=pseudofile) + del a.uuid attribute = self.mispevent.attributes[0] self.assertEqual(attribute.malware_binary, pseudofile) with open('tests/mispevent_testfiles/malware.json', 'r') as f: @@ -135,18 +139,23 @@ def test_shadow_attributes(self): self.init_event() - self.mispevent.add_proposal(type='filename', value='baz.jpg') - self.mispevent.add_attribute('filename', 'bar.exe') - self.mispevent.attributes[0].add_proposal(type='filename', value='bar.pdf') + p = self.mispevent.add_proposal(type='filename', value='baz.jpg') + del p.uuid + a = self.mispevent.add_attribute('filename', 'bar.exe') + del a.uuid + p = self.mispevent.attributes[0].add_proposal(type='filename', value='bar.pdf') + del p.uuid with open('tests/mispevent_testfiles/proposals.json', 'r') as f: ref_json = json.load(f) self.assertEqual(self.mispevent.to_json(), json.dumps(ref_json, sort_keys=True, indent=2)) def test_default_attributes(self): self.mispevent.add_object(name='file', strict=True) - self.mispevent.objects[0].add_attribute('filename', value='bar', Tag=[{'name': 'blah'}]) + a = self.mispevent.objects[0].add_attribute('filename', value='bar', Tag=[{'name': 'blah'}]) + del a.uuid self.mispevent.add_object(name='file', strict=False, default_attributes_parameters=self.mispevent.objects[0].attributes[0]) - self.mispevent.objects[1].add_attribute('filename', value='baz') + a = self.mispevent.objects[1].add_attribute('filename', value='baz') + del a.uuid self.mispevent.objects[0].uuid = 'a' self.mispevent.objects[1].uuid = 'b' with open('tests/mispevent_testfiles/event_obj_def_param.json', 'r') as f: @@ -156,10 +165,14 @@ def test_obj_default_values(self): self.init_event() self.mispevent.add_object(name='whois', strict=True) - self.mispevent.objects[0].add_attribute('registrar', value='registar.example.com') - self.mispevent.objects[0].add_attribute('domain', value='domain.example.com') - self.mispevent.objects[0].add_attribute('nameserver', value='ns1.example.com') - self.mispevent.objects[0].add_attribute('nameserver', value='ns2.example.com', disable_correlation=False, to_ids=True, category='External analysis') + a = self.mispevent.objects[0].add_attribute('registrar', value='registar.example.com') + del a.uuid + a = self.mispevent.objects[0].add_attribute('domain', value='domain.example.com') + del a.uuid + a = self.mispevent.objects[0].add_attribute('nameserver', value='ns1.example.com') + del a.uuid + a = self.mispevent.objects[0].add_attribute('nameserver', value='ns2.example.com', disable_correlation=False, to_ids=True, category='External analysis') + del a.uuid self.mispevent.objects[0].uuid = 'a' with open('tests/mispevent_testfiles/def_param.json', 'r') as f: ref_json = json.load(f) @@ -247,14 +260,17 @@ # Python2 bullshit self.assertEqual(e.exception.message, 'set([u\'member3\']) are required.') - self.mispevent.objects[0].add_attribute('member3', value='foo') + a = self.mispevent.objects[0].add_attribute('member3', value='foo') + del a.uuid with self.assertRaises(InvalidMISPObject) as e: # Fail on requiredOneOf self.mispevent.to_json() self.assertEqual(e.exception.message, 'At least one of the following attributes is required: member1, member2') - self.mispevent.objects[0].add_attribute('member1', value='bar') - self.mispevent.objects[0].add_attribute('member1', value='baz') + a = self.mispevent.objects[0].add_attribute('member1', value='bar') + del a.uuid + a = self.mispevent.objects[0].add_attribute('member1', value='baz') + del a.uuid with self.assertRaises(InvalidMISPObject) as e: # member1 is not a multiple self.mispevent.to_json() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pymisp-2.4.90/tests/test_offline.py new/pymisp-2.4.90.1/tests/test_offline.py --- old/pymisp-2.4.90/tests/test_offline.py 2018-04-25 11:29:29.000000000 +0200 +++ new/pymisp-2.4.90.1/tests/test_offline.py 2018-05-09 13:34:36.000000000 +0200 @@ -279,16 +279,22 @@ if seos: for s in seos: + for a in s.attributes: + del a.uuid to_return['objects'].append(s) if s.ObjectReference: to_return['references'] += s.ObjectReference if peo: + for a in peo.attributes: + del a.uuid to_return['objects'].append(peo) if peo.ObjectReference: to_return['references'] += peo.ObjectReference if fo: + for a in fo.attributes: + del a.uuid to_return['objects'].append(fo) if fo.ObjectReference: to_return['references'] += fo.ObjectReference
