Skip to content

Commit

Permalink
Merge pull request #958 from camptocamp/remove-npm-audit
Browse files Browse the repository at this point in the history
Remove npm audit better replaced by Snyk
  • Loading branch information
sbrunner authored Jan 5, 2023
2 parents 339bc01 + 7f564a2 commit 3b9241d
Show file tree
Hide file tree
Showing 5 changed files with 927 additions and 1,090 deletions.
30 changes: 17 additions & 13 deletions c2cciutils/applications_definition.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,47 @@

from typing import Dict, List, Literal, TypedDict, Union

# Application configuration
# Application configuration.
#
# An application configuration
ApplicationConfiguration = TypedDict(
"ApplicationConfiguration",
{
# URL pattern
# URL pattern.
#
# URL pattern, to be used for files that didn't come from GitHub release, available arguments: {version}
"url-pattern": str,
"type": "TheTypeOfFile",
# The filename to get
# The filename to get.
#
# The filename to get in the GitHub release
"get-file-name": str,
# The created tile name
# The created tile name.
#
# The name of the final tile name we will create
"to-file-name": str,
# The tile name to get in the tar file
# The tile name to get in the tar file.
"tar-file-name": str,
# The commands to run after the tile creation
# The commands to run after the tile creation.
"finish-commands": List[List[str]],
},
total=False,
)


# Applications configuration
#
# All the applications configuration
ApplicationsConfiguration = Dict[str, "ApplicationConfiguration"]
"""
Applications configuration.
All the applications configuration
"""


# The type of file
#
# The type of file
TheTypeOfFile = Union[Literal["tar"]]
# The values for the enum
"""
The type of file.
The type of file
"""
THETYPEOFFILE_TAR: Literal["tar"] = "tar"
"""The values for the 'The type of file' enum"""
170 changes: 0 additions & 170 deletions c2cciutils/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
import subprocess # nosec
import sys
from argparse import Namespace
from typing import Any, Dict, List

import yaml

import c2cciutils
import c2cciutils.configuration
Expand Down Expand Up @@ -209,173 +206,6 @@ def snyk(
return install_success and test_success and diff_proc.returncode == 0


def get_global_npm_cve() -> List[int]:
"""
Get the CVE which were installed globally by GitHub.
"""
with open("/tmp/package.json", "w", encoding="utf-8") as package:
package.write("{}")

subprocess.check_call(["npm", "install", "--package-lock-only"], cwd="/tmp")
audit = json.loads(
# Don't use check=True because audit will return an error on any vulnerabilities found
# and we want to manage that ourself.
subprocess.run( # pylint: disable=subprocess-run-check
["npm", "audit", "--json"], stdout=subprocess.PIPE, cwd="/tmp"
).stdout
)

if "error" in audit:
print(yaml.dump(audit["error"], default_flow_style=False, Dumper=yaml.SafeDumper))
return []

return [
vulnerability["id"]
for vulnerability in audit.get("advisories", audit.get("vulnerabilities")).values()
]


def npm(
config: c2cciutils.configuration.AuditNpmConfig,
full_config: c2cciutils.configuration.Configuration,
args: Namespace,
) -> bool:
"""
Audit all the `package.json` files.
config is like:
cwe_ignore: list of ignored CWE
Arguments:
config: The audit section config
full_config: All the CI config
args: The parsed command arguments
"""
del full_config, args

global_cve = get_global_npm_cve()
global_success = True
for file in subprocess.check_output(["git", "ls-files"]).decode().strip().split("\n"):
success = True
if os.path.basename(file) != "package.json":
continue
print("::group::Audit " + file)
directory = os.path.dirname(file)
sys.stdout.flush()
sys.stderr.flush()
subprocess_kwargs: Dict[str, Any] = {} if directory == "" else {"cwd": directory}
subprocess.check_call(["npm", "install", "--package-lock-only"], **subprocess_kwargs)

cve_file = os.path.join(directory, "npm-cve-ignore")
all_ignores = []
unused_ignores = []
if os.path.exists(cve_file):
with open(cve_file, encoding="utf-8") as cve_file_open:
all_ignores = [int(e) for e in cve_file_open.read().strip().split(",")]
unused_ignores = list(all_ignores)

cwe_ignores = config.get("cwe_ignore", [])
package_ignore = config.get("package_ignore", [])

audit = json.loads(
# Don't use check_output because audit will return an error on any vulnerabilities found
# and we want to manage that ourself.
subprocess.run( # pylint: disable=subprocess-run-check
["npm", "audit", "--audit-level=moderate", "--json"],
stdout=subprocess.PIPE,
**subprocess_kwargs,
).stdout
)
vulnerabilities = {}
if "error" in audit:
print(yaml.dump(audit["error"], default_flow_style=False, Dumper=yaml.SafeDumper))
print("::endgroup::")
print("::error::With error")
return False

for vulnerability in audit.get("advisories", audit.get("vulnerabilities")).values():
cwe = vulnerability.get("cwe")
if isinstance(cwe, str):
if cwe in cwe_ignores:
continue
else:
ignored = True
for cwe_elem in cwe:
if cwe_elem not in cwe_ignores:
ignored = False
break
if ignored:
continue

completely_ignored = True
for find in vulnerability.get("findings", []):
valid_splitted_path = []
for path in find.get("paths", []):
path_splitted = path.split(">")
ignored = False
for package in package_ignore:
if package in path_splitted:
ignored = True
if not ignored:
valid_splitted_path.append(path_splitted)
completely_ignored = False
find["paths"] = valid_splitted_path
if completely_ignored:
continue
if vulnerability["id"] in global_cve:
continue
if "recommendation" not in vulnerability or vulnerability.get("recommendation") == "None":
continue
if vulnerability["id"] not in all_ignores:
vulnerabilities[vulnerability["id"]] = vulnerability
elif vulnerability["id"] in unused_ignores:
unused_ignores.remove(vulnerability["id"])

if vulnerabilities:
first = True
for vulnerability in vulnerabilities.values():
cwe = vulnerability.get("cwe")
if isinstance(cwe, list):
cwe = ", ".join(cwe)
if not first:
print("=======================================================")
print()
print(f"Title: [{vulnerability.get('id')}] {vulnerability.get('title')}")
print("Severity: " + vulnerability.get("severity"))
print("CWE: " + cwe)
print("Vulnerable versions: " + vulnerability.get("vulnerable_versions"))
print("Patched versions: " + vulnerability.get("patched_versions"))
print("Recommendation: " + vulnerability.get("recommendation"))
for find in vulnerability.get("findings", []):
paths = find["paths"]
if paths:
print("Version: " + find["version"])
for path in paths:
print("Path: " + " > ".join(path))
print("More info: " + vulnerability.get("url"))
print()

c2cciutils.error(
"npm", "We have some vulnerabilities see logs", file=os.path.join(directory, "package.json")
)
success = False

if len(unused_ignores) > 0:
c2cciutils.error(
"npm",
"The following cve ignores are not present in the audit: "
f"{', '.join([str(e) for e in unused_ignores])}",
file=cve_file,
)
success = False

print("::endgroup::")
if not success:
print("::error::With error")
global_success = global_success and success
return global_success


def outdated_versions(
config: None,
full_config: c2cciutils.configuration.Configuration,
Expand Down
Loading

0 comments on commit 3b9241d

Please sign in to comment.