From 291da9ffe83fcbb78267f2cb739d2ccb80ba7540 Mon Sep 17 00:00:00 2001 From: Valentinas Bakaitis Date: Tue, 10 Sep 2024 13:29:25 +1200 Subject: [PATCH 1/6] Fixes issue #90 - produces separate sarif issues for each result instance --- mobsfscan/formatters/sarif.py | 86 ++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 32 deletions(-) diff --git a/mobsfscan/formatters/sarif.py b/mobsfscan/formatters/sarif.py index 59b2cd4..0be7495 100644 --- a/mobsfscan/formatters/sarif.py +++ b/mobsfscan/formatters/sarif.py @@ -76,14 +76,15 @@ def add_results(path, scan_results, run): rule_indices = {} for rule_id, issue_dict in res.items(): - result = create_result(path, rule_id, issue_dict, rules, rule_indices) - run.results.append(result) + results = create_rule_results(path, rule_id, issue_dict, rules, rule_indices) + run.results += results if len(rules) > 0: run.tool.driver.rules = list(rules.values()) -def create_result(path, rule_id, issue_dict, rules, rule_indices): +def create_rule_results(path, rule_id, issue_dict, rules, rule_indices): + rule_results = [] if rule_id in rules: rule = rules[rule_id] rule_index = rule_indices[rule_id] @@ -105,21 +106,41 @@ def create_result(path, rule_id, issue_dict, rules, rule_indices): rules[rule_id] = rule rule_indices[rule_id] = rule_index - locations = [] - for item in issue_dict.get('files', []): - physical_location = om.PhysicalLocation( - artifact_location=om.ArtifactLocation( - uri=to_uri(item['file_path'])), - ) - physical_location.region = om.Region( - start_line=item['match_lines'][0], - end_line=item['match_lines'][1], - start_column=item['match_position'][0], - end_column=item['match_position'][1], - snippet=om.ArtifactContent(text=item['match_string']), - ) - locations.append(om.Location(physical_location=physical_location)) - if not locations: + files = issue_dict.get('files', []) + + # if there are locations - we iterate over them and create + # a separete result for each location + if files: + for item in files: + locations = [] + physical_location = om.PhysicalLocation( + artifact_location=om.ArtifactLocation( + uri=to_uri(item['file_path'])), + ) + physical_location.region = om.Region( + start_line=item['match_lines'][0], + end_line=item['match_lines'][1], + start_column=item['match_position'][0], + end_column=item['match_position'][1], + snippet=om.ArtifactContent(text=item['match_string']), + ) + locations.append(om.Location(physical_location=physical_location)) + rule_results.append(om.Result( + rule_id=rule.id, + rule_index=rule_index, + message=om.Message(text=issue_dict['metadata']['description']), + level=level_from_severity(issue_dict['metadata']['severity']), + locations=locations, + properties={ + 'owasp-mobile': issue_dict['metadata']['owasp-mobile'], + 'masvs': issue_dict['metadata']['masvs'], + 'cwe': issue_dict['metadata']['cwe'], + 'reference': issue_dict['metadata']['reference'], + }, + )) + # if there are no locations - only create a single resuklt + else: + locations = [] artifact = om.PhysicalLocation( artifact_location=om.ArtifactLocation( uri=path[0]), @@ -132,20 +153,21 @@ def create_result(path, rule_id, issue_dict, rules, rule_indices): snippet=om.ArtifactContent(text='Missing Best Practice'), ) locations.append(om.Location(physical_location=artifact)) - - return om.Result( - rule_id=rule.id, - rule_index=rule_index, - message=om.Message(text=issue_dict['metadata']['description']), - level=level_from_severity(issue_dict['metadata']['severity']), - locations=locations, - properties={ - 'owasp-mobile': issue_dict['metadata']['owasp-mobile'], - 'masvs': issue_dict['metadata']['masvs'], - 'cwe': issue_dict['metadata']['cwe'], - 'reference': issue_dict['metadata']['reference'], - }, - ) + rule_results.append(om.Result( + rule_id=rule.id, + rule_index=rule_index, + message=om.Message(text=issue_dict['metadata']['description']), + level=level_from_severity(issue_dict['metadata']['severity']), + locations=locations, + properties={ + 'owasp-mobile': issue_dict['metadata']['owasp-mobile'], + 'masvs': issue_dict['metadata']['masvs'], + 'cwe': issue_dict['metadata']['cwe'], + 'reference': issue_dict['metadata']['reference'], + }, + )) + + return rule_results def sarif_output(outfile, scan_results, mobsfscan_version, path): From 3d3fca46da11a05f71d57425f38d18e360c263d3 Mon Sep 17 00:00:00 2001 From: Valentinas Bakaitis Date: Wed, 11 Sep 2024 12:03:24 +1200 Subject: [PATCH 2/6] deduplicate findings before returning them --- mobsfscan/mobsfscan.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/mobsfscan/mobsfscan.py b/mobsfscan/mobsfscan.py index e4f677d..c924fbb 100644 --- a/mobsfscan/mobsfscan.py +++ b/mobsfscan/mobsfscan.py @@ -127,6 +127,20 @@ def format_output(self, results) -> dict: self.post_ignore_rules() self.post_ignore_rules_by_severity() self.post_ignore_files() + self.deduplicate_files() + + def deduplicate_files(self): + for _, details in self.result['results'].items(): + files = details.get('files') + # some results don't have any files, so we need to check before we continue + if files: + # "file" here refers to the dictionary containig the file_path, match_lines, etc. + # for each file we create a tuple with it's contents + # then using those tuples as keys and "file" as values we create a dictionary + # This means that for each unique "file" we will get only one entry as we can't have duplicate keys + # Once this is done - convert the dictionary back to list by grabbing it's values and passing it to list() + unique_files = list({tuple(sorted(f.items())): f for f in files}.values()) + details['files'] = unique_files def format_semgrep(self, sgrep_output): """Format semgrep output.""" From 3b891372a5a23c15b2fc4d4d37cdcfd8f95188f1 Mon Sep 17 00:00:00 2001 From: Ajin Abraham Date: Mon, 4 Nov 2024 18:38:01 -0800 Subject: [PATCH 3/6] Update SARIF converter, fix #90, #91 --- action.md | 2 +- mobsfscan/__init__.py | 2 +- mobsfscan/formatters/sarif.py | 219 ++++++++++++---------------------- 3 files changed, 79 insertions(+), 144 deletions(-) diff --git a/action.md b/action.md index 13a6d15..54ae887 100644 --- a/action.md +++ b/action.md @@ -2,7 +2,7 @@ Update Pipfile ```bash -PIPENV_IGNORE_VIRTUALENVS=1 pipenv lock +PIPENV_IGNORE_VIRTUALENVS=1 pipenv lock PIPENV_IGNORE_VIRTUALENVS=1 pipenv sync PIPENV_IGNORE_VIRTUALENVS=1 pipenv run pip freeze > requirements.txt ``` \ No newline at end of file diff --git a/mobsfscan/__init__.py b/mobsfscan/__init__.py index 9c187d0..3e32d53 100644 --- a/mobsfscan/__init__.py +++ b/mobsfscan/__init__.py @@ -6,7 +6,7 @@ __title__ = 'mobsfscan' __authors__ = 'Ajin Abraham' __copyright__ = f'Copyright {datetime.now().year} Ajin Abraham, OpenSecurity' -__version__ = '0.4.0' +__version__ = '0.4.1' __version_info__ = tuple(int(i) for i in __version__.split('.')) __all__ = [ '__title__', diff --git a/mobsfscan/formatters/sarif.py b/mobsfscan/formatters/sarif.py index 0be7495..4906f91 100644 --- a/mobsfscan/formatters/sarif.py +++ b/mobsfscan/formatters/sarif.py @@ -1,203 +1,138 @@ # -*- coding: utf_8 -*- -"""Sarif output format. +"""SARIF output formatter for MobSF scan results. -Based on https://github.com/microsoft/bandit-sarif-formatter/ -blob/master/bandit_sarif_formatter/formatter.py +Based on https://github.com/microsoft/bandit-sarif-formatter/blob/master/bandit_sarif_formatter/formatter.py +MIT License, Copyright (c) Microsoft Corporation. -Copyright (c) Microsoft. All Rights Reserved. -MIT License - -Copyright (c) Microsoft Corporation. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE """ from datetime import datetime from pathlib import PurePath import urllib.parse as urlparse - import sarif_om as om - from jschema_to_python.to_json import to_json - TS_FORMAT = '%Y-%m-%dT%H:%M:%SZ' - def level_from_severity(severity): - if severity == 'ERROR': - return 'error' - elif severity == 'WARNING': - return 'warning' - elif severity == 'INFO': - return 'note' - else: - return 'none' - + return { + 'ERROR': 'error', + 'WARNING': 'warning', + 'INFO': 'note' + }.get(severity, 'none') def to_uri(file_path): pure_path = PurePath(file_path) - if pure_path.is_absolute(): - return pure_path.as_uri() - else: - posix_path = pure_path.as_posix() # Replace backslashes with slashes. - return urlparse.quote(posix_path) # %-encode special characters. - - -def get_rule_name(rule_id): - normalized = [] - noms = rule_id.split('_') - for nom in noms: - normalized.append(nom.capitalize()) - return ''.join(normalized) + return pure_path.as_uri() if pure_path.is_absolute() else urlparse.quote(pure_path.as_posix()) +def format_rule_name(rule_id): + return ''.join(word.capitalize() for word in rule_id.split('_')) def add_results(path, scan_results, run): if run.results is None: run.results = [] - res = {} - res.update(scan_results.get('results', [])) + res = scan_results.get('results', {}) rules = {} rule_indices = {} for rule_id, issue_dict in res.items(): - results = create_rule_results(path, rule_id, issue_dict, rules, rule_indices) - run.results += results + rule_results = create_rule_results(path, rule_id, issue_dict, rules, rule_indices) + run.results.extend(rule_results) - if len(rules) > 0: + if rules: run.tool.driver.rules = list(rules.values()) - def create_rule_results(path, rule_id, issue_dict, rules, rule_indices): rule_results = [] - if rule_id in rules: - rule = rules[rule_id] - rule_index = rule_indices[rule_id] - else: - doc = issue_dict['metadata'].get('reference') - if not doc: - doc = ('https://mobile-security.gitbook.io/' - 'mobile-security-testing-guide/') + rule, rule_index = rules.get(rule_id), rule_indices.get(rule_id) + + if not rule: + doc = issue_dict['metadata'].get('reference') or 'https://mobile-security.gitbook.io/mobile-security-testing-guide/' cwe_id = issue_dict['metadata']['cwe'].split(':')[0].lower() rule = om.ReportingDescriptor( id=rule_id, - name=get_rule_name(rule_id), + name=format_rule_name(rule_id), help_uri=doc, - properties={ - 'tags': ['security', f'external/cwe/{cwe_id}'], - }, + properties={'tags': ['security', f'external/cwe/{cwe_id}']} ) rule_index = len(rules) rules[rule_id] = rule rule_indices[rule_id] = rule_index - files = issue_dict.get('files', []) - - # if there are locations - we iterate over them and create - # a separete result for each location - if files: - for item in files: - locations = [] - physical_location = om.PhysicalLocation( - artifact_location=om.ArtifactLocation( - uri=to_uri(item['file_path'])), + for item in issue_dict.get('files', []): + location = create_location(item) + rule_results.append(create_result(rule, rule_index, issue_dict, [location])) + + if not issue_dict.get('files'): + default_location = om.Location( + physical_location=om.PhysicalLocation( + artifact_location=om.ArtifactLocation(uri=path[0]), + region=om.Region( + start_line=1, + end_line=1, + start_column=1, + end_column=1, + snippet=om.ArtifactContent(text='Missing Best Practice') + ) ) - physical_location.region = om.Region( + ) + rule_results.append(create_result(rule, rule_index, issue_dict, [default_location])) + + return rule_results + +def create_location(item): + return om.Location( + physical_location=om.PhysicalLocation( + artifact_location=om.ArtifactLocation(uri=to_uri(item['file_path'])), + region=om.Region( start_line=item['match_lines'][0], end_line=item['match_lines'][1], start_column=item['match_position'][0], end_column=item['match_position'][1], - snippet=om.ArtifactContent(text=item['match_string']), + snippet=om.ArtifactContent(text=item['match_string']) ) - locations.append(om.Location(physical_location=physical_location)) - rule_results.append(om.Result( - rule_id=rule.id, - rule_index=rule_index, - message=om.Message(text=issue_dict['metadata']['description']), - level=level_from_severity(issue_dict['metadata']['severity']), - locations=locations, - properties={ - 'owasp-mobile': issue_dict['metadata']['owasp-mobile'], - 'masvs': issue_dict['metadata']['masvs'], - 'cwe': issue_dict['metadata']['cwe'], - 'reference': issue_dict['metadata']['reference'], - }, - )) - # if there are no locations - only create a single resuklt - else: - locations = [] - artifact = om.PhysicalLocation( - artifact_location=om.ArtifactLocation( - uri=path[0]), ) - artifact.region = om.Region( - start_line=1, - end_line=1, - start_column=1, - end_column=1, - snippet=om.ArtifactContent(text='Missing Best Practice'), - ) - locations.append(om.Location(physical_location=artifact)) - rule_results.append(om.Result( - rule_id=rule.id, - rule_index=rule_index, - message=om.Message(text=issue_dict['metadata']['description']), - level=level_from_severity(issue_dict['metadata']['severity']), - locations=locations, - properties={ - 'owasp-mobile': issue_dict['metadata']['owasp-mobile'], - 'masvs': issue_dict['metadata']['masvs'], - 'cwe': issue_dict['metadata']['cwe'], - 'reference': issue_dict['metadata']['reference'], - }, - )) - - return rule_results + ) +def create_result(rule, rule_index, issue_dict, locations): + return om.Result( + rule_id=rule.id, + rule_index=rule_index, + message=om.Message(text=issue_dict['metadata']['description']), + level=level_from_severity(issue_dict['metadata']['severity']), + locations=locations, + properties={ + 'owasp-mobile': issue_dict['metadata']['owasp-mobile'], + 'masvs': issue_dict['metadata']['masvs'], + 'cwe': issue_dict['metadata']['cwe'], + 'reference': issue_dict['metadata']['reference'], + } + ) def sarif_output(outfile, scan_results, mobsfscan_version, path): log = om.SarifLog( - schema_uri=('https://raw.githubusercontent.com/oasis-tcs/' - 'sarif-spec/master/Schemata/sarif-schema-2.1.0.json'), + schema_uri='https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json', version='2.1.0', - runs=[ - om.Run( - tool=om.Tool(driver=om.ToolComponent( - name='mobsfscan', - information_uri='https://github.com/MobSF/mobsfscan', - semantic_version=mobsfscan_version, - version=mobsfscan_version), - ), - invocations=[ - om.Invocation( - end_time_utc=datetime.utcnow().strftime(TS_FORMAT), - execution_successful=True, - ), - ], - ), - ], + runs=[om.Run( + tool=om.Tool(driver=om.ToolComponent( + name='mobsfscan', + information_uri='https://github.com/MobSF/mobsfscan', + semantic_version=mobsfscan_version, + version=mobsfscan_version + )), + invocations=[om.Invocation( + end_time_utc=datetime.utcnow().strftime(TS_FORMAT), + execution_successful=True + )] + )] ) run = log.runs[0] add_results(path, scan_results, run) json_out = to_json(log) + if outfile: with open(outfile, 'w') as of: of.write(json_out) else: print(json_out) + return json_out From 0b6de300a883fd8514b427251217c457714eedbd Mon Sep 17 00:00:00 2001 From: Ajin Abraham Date: Mon, 4 Nov 2024 18:51:04 -0800 Subject: [PATCH 4/6] lint fix --- mobsfscan/formatters/sarif.py | 62 ++++++++++++++++++++--------------- mobsfscan/mobsfscan.py | 20 +++++++---- tox.ini | 3 ++ 3 files changed, 53 insertions(+), 32 deletions(-) diff --git a/mobsfscan/formatters/sarif.py b/mobsfscan/formatters/sarif.py index 4906f91..3328e2f 100644 --- a/mobsfscan/formatters/sarif.py +++ b/mobsfscan/formatters/sarif.py @@ -1,32 +1,43 @@ # -*- coding: utf_8 -*- """SARIF output formatter for MobSF scan results. -Based on https://github.com/microsoft/bandit-sarif-formatter/blob/master/bandit_sarif_formatter/formatter.py +Based on https://github.com/microsoft/ +bandit-sarif-formatter/blob/master/ +bandit_sarif_formatter/formatter.py MIT License, Copyright (c) Microsoft Corporation. """ from datetime import datetime from pathlib import PurePath import urllib.parse as urlparse + import sarif_om as om + from jschema_to_python.to_json import to_json TS_FORMAT = '%Y-%m-%dT%H:%M:%SZ' + def level_from_severity(severity): return { 'ERROR': 'error', 'WARNING': 'warning', - 'INFO': 'note' + 'INFO': 'note', }.get(severity, 'none') + def to_uri(file_path): pure_path = PurePath(file_path) - return pure_path.as_uri() if pure_path.is_absolute() else urlparse.quote(pure_path.as_posix()) + if pure_path.is_absolute(): + return pure_path.as_uri() + else: + return urlparse.quote(pure_path.as_posix()) + def format_rule_name(rule_id): return ''.join(word.capitalize() for word in rule_id.split('_')) + def add_results(path, scan_results, run): if run.results is None: run.results = [] @@ -35,25 +46,27 @@ def add_results(path, scan_results, run): rule_indices = {} for rule_id, issue_dict in res.items(): - rule_results = create_rule_results(path, rule_id, issue_dict, rules, rule_indices) + rule_results = create_rule_results( + path, rule_id, issue_dict, rules, rule_indices) run.results.extend(rule_results) if rules: run.tool.driver.rules = list(rules.values()) + def create_rule_results(path, rule_id, issue_dict, rules, rule_indices): rule_results = [] rule, rule_index = rules.get(rule_id), rule_indices.get(rule_id) - + ref_url = ('https://mobile-security.gitbook.io/' + 'mobile-security-testing-guide/') if not rule: - doc = issue_dict['metadata'].get('reference') or 'https://mobile-security.gitbook.io/mobile-security-testing-guide/' + doc = issue_dict['metadata'].get('reference') or ref_url cwe_id = issue_dict['metadata']['cwe'].split(':')[0].lower() rule = om.ReportingDescriptor( id=rule_id, name=format_rule_name(rule_id), help_uri=doc, - properties={'tags': ['security', f'external/cwe/{cwe_id}']} - ) + properties={'tags': ['security', f'external/cwe/{cwe_id}']}) rule_index = len(rules) rules[rule_id] = rule rule_indices[rule_id] = rule_index @@ -71,14 +84,13 @@ def create_rule_results(path, rule_id, issue_dict, rules, rule_indices): end_line=1, start_column=1, end_column=1, - snippet=om.ArtifactContent(text='Missing Best Practice') - ) - ) - ) - rule_results.append(create_result(rule, rule_index, issue_dict, [default_location])) + snippet=om.ArtifactContent(text='Missing Best Practice')))) + rule_results.append(create_result( + rule, rule_index, issue_dict, [default_location])) return rule_results + def create_location(item): return om.Location( physical_location=om.PhysicalLocation( @@ -88,10 +100,8 @@ def create_location(item): end_line=item['match_lines'][1], start_column=item['match_position'][0], end_column=item['match_position'][1], - snippet=om.ArtifactContent(text=item['match_string']) - ) - ) - ) + snippet=om.ArtifactContent(text=item['match_string'])))) + def create_result(rule, rule_index, issue_dict, locations): return om.Result( @@ -105,26 +115,26 @@ def create_result(rule, rule_index, issue_dict, locations): 'masvs': issue_dict['metadata']['masvs'], 'cwe': issue_dict['metadata']['cwe'], 'reference': issue_dict['metadata']['reference'], - } - ) + }) + def sarif_output(outfile, scan_results, mobsfscan_version, path): log = om.SarifLog( - schema_uri='https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json', + schema_uri=('https://raw.githubusercontent.com/' + 'oasis-tcs/sarif-spec/master/Schemata/' + 'sarif-schema-2.1.0.json'), version='2.1.0', runs=[om.Run( tool=om.Tool(driver=om.ToolComponent( name='mobsfscan', information_uri='https://github.com/MobSF/mobsfscan', semantic_version=mobsfscan_version, - version=mobsfscan_version + version=mobsfscan_version, )), invocations=[om.Invocation( - end_time_utc=datetime.utcnow().strftime(TS_FORMAT), - execution_successful=True - )] - )] - ) + end_time_utc=datetime.now(datetime.timezone.utc).strftime(TS_FORMAT), + execution_successful=True, + )])]) run = log.runs[0] add_results(path, scan_results, run) json_out = to_json(log) diff --git a/mobsfscan/mobsfscan.py b/mobsfscan/mobsfscan.py index c924fbb..d6c39b2 100644 --- a/mobsfscan/mobsfscan.py +++ b/mobsfscan/mobsfscan.py @@ -130,16 +130,24 @@ def format_output(self, results) -> dict: self.deduplicate_files() def deduplicate_files(self): + """Deduplicate files.""" for _, details in self.result['results'].items(): files = details.get('files') - # some results don't have any files, so we need to check before we continue + # some results don't have any files, + # so we need to check before we continue if files: - # "file" here refers to the dictionary containig the file_path, match_lines, etc. + # "file" here refers to the dictionary containig + # the file_path, match_lines, etc. # for each file we create a tuple with it's contents - # then using those tuples as keys and "file" as values we create a dictionary - # This means that for each unique "file" we will get only one entry as we can't have duplicate keys - # Once this is done - convert the dictionary back to list by grabbing it's values and passing it to list() - unique_files = list({tuple(sorted(f.items())): f for f in files}.values()) + # then using those tuples as keys and + # "file" as values we create a dictionary + # This means that for each unique "file" + # we will get only one entry as we + # can't have duplicate keys + # Once this is done - convert the dictionary + # back to list by grabbing it's values and passing it to list() + unique_files = list( + {tuple(sorted(f.items())): f for f in files}.values()) details['files'] = unique_files def format_semgrep(self, sgrep_output): diff --git a/tox.ini b/tox.ini index 374fec1..cf92098 100644 --- a/tox.ini +++ b/tox.ini @@ -16,6 +16,7 @@ setenv = skip_install = true deps = pydocstyle + autopep8 flake8 flake8-broken-line flake8-bugbear @@ -32,6 +33,7 @@ deps = pep8-naming radon commands = + autopep8 --recursive --in-place setup.py mobsfscan tests flake8 setup.py mobsfscan tests [testenv:bandit] @@ -99,3 +101,4 @@ ignore = R701, # Too complex radon_max_cc = 10 +max-line-length = 88 \ No newline at end of file From d8c90daf4b810c24daf8081065ea184332d769f8 Mon Sep 17 00:00:00 2001 From: Ajin Abraham Date: Mon, 4 Nov 2024 18:56:14 -0800 Subject: [PATCH 5/6] revert to utcnow --- mobsfscan/formatters/sarif.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobsfscan/formatters/sarif.py b/mobsfscan/formatters/sarif.py index 3328e2f..7ea534b 100644 --- a/mobsfscan/formatters/sarif.py +++ b/mobsfscan/formatters/sarif.py @@ -132,7 +132,7 @@ def sarif_output(outfile, scan_results, mobsfscan_version, path): version=mobsfscan_version, )), invocations=[om.Invocation( - end_time_utc=datetime.now(datetime.timezone.utc).strftime(TS_FORMAT), + end_time_utc=datetime.utcnow().strftime(TS_FORMAT), execution_successful=True, )])]) run = log.runs[0] From bf50202ba0023cfc6b4115841aec2cf38568e420 Mon Sep 17 00:00:00 2001 From: Ajin Abraham Date: Mon, 4 Nov 2024 19:04:38 -0800 Subject: [PATCH 6/6] QA --- mobsfscan/formatters/sarif.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mobsfscan/formatters/sarif.py b/mobsfscan/formatters/sarif.py index 7ea534b..4d237f8 100644 --- a/mobsfscan/formatters/sarif.py +++ b/mobsfscan/formatters/sarif.py @@ -7,7 +7,7 @@ MIT License, Copyright (c) Microsoft Corporation. """ -from datetime import datetime +from datetime import datetime, timezone from pathlib import PurePath import urllib.parse as urlparse @@ -132,7 +132,7 @@ def sarif_output(outfile, scan_results, mobsfscan_version, path): version=mobsfscan_version, )), invocations=[om.Invocation( - end_time_utc=datetime.utcnow().strftime(TS_FORMAT), + end_time_utc=datetime.now(timezone.utc).strftime(TS_FORMAT), execution_successful=True, )])]) run = log.runs[0]