Skip to content

Commit

Permalink
2023.0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
FredHappyface committed Jun 27, 2023
1 parent 977a203 commit 970e8c3
Show file tree
Hide file tree
Showing 13 changed files with 408 additions and 120 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
All major and minor version changes will be documented in this file. Details of
patch-level version changes can be found in [commit messages](../../commits/master).

## 2023.0.2 - 2023/06/27

- Add `Level.CRIT`
- Misc fixes to make plugins more resilient
- Test plugin utility functions

## 2023.0.1 - 2023/06/27

- Fix `csv` writer
Expand Down
11 changes: 3 additions & 8 deletions documentation/reference/simplesecurity/level.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ Level

Levels for confidence and severity.

UNKNOWN = 0
LOW = 1
MED = 2
HIGH = 3

#### Signature

```python
Expand All @@ -32,7 +27,7 @@ class Level(IntEnum):

### Level().__repr__

[Show source in level.py:27](../../../simplesecurity/level.py#L27)
[Show source in level.py:22](../../../simplesecurity/level.py#L22)

__repr__ method.

Expand All @@ -49,7 +44,7 @@ def __repr__(self) -> str:

### Level().__str__

[Show source in level.py:35](../../../simplesecurity/level.py#L35)
[Show source in level.py:30](../../../simplesecurity/level.py#L30)

__str__ method (tostring).

Expand All @@ -66,7 +61,7 @@ def __str__(self) -> str:

### Level().toSarif

[Show source in level.py:49](../../../simplesecurity/level.py#L49)
[Show source in level.py:45](../../../simplesecurity/level.py#L45)

Convert to sarif representation.

Expand Down
10 changes: 5 additions & 5 deletions documentation/reference/simplesecurity/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Plugins

## bandit

[Show source in plugins.py:90](../../../simplesecurity/plugins.py#L90)
[Show source in plugins.py:92](../../../simplesecurity/plugins.py#L92)

Generate list of findings using bandit. requires bandit on the system path.

Expand Down Expand Up @@ -47,7 +47,7 @@ def bandit(scanDir=".") -> list[Finding]:

## dlint

[Show source in plugins.py:247](../../../simplesecurity/plugins.py#L247)
[Show source in plugins.py:274](../../../simplesecurity/plugins.py#L274)

Generate list of findings using _tool_. requires _tool_ on the system path.

Expand Down Expand Up @@ -78,7 +78,7 @@ def dlint(scanDir=".") -> list[Finding]:

## dodgy

[Show source in plugins.py:211](../../../simplesecurity/plugins.py#L211)
[Show source in plugins.py:237](../../../simplesecurity/plugins.py#L237)

Generate list of findings using _tool_. requires _tool_ on the system path.

Expand Down Expand Up @@ -137,7 +137,7 @@ def extractEvidence(desiredLine: int, file: str) -> list[Line]:

## safety

[Show source in plugins.py:172](../../../simplesecurity/plugins.py#L172)
[Show source in plugins.py:198](../../../simplesecurity/plugins.py#L198)

Generate list of findings using _tool_. requires _tool_ on the system path.

Expand Down Expand Up @@ -168,7 +168,7 @@ def safety(scanDir=".") -> list[Finding]:

## semgrep

[Show source in plugins.py:302](../../../simplesecurity/plugins.py#L302)
[Show source in plugins.py:331](../../../simplesecurity/plugins.py#L331)

Generate list of findings using for semgrep. Requires semgrep on the
system path (wsl in windows).
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "simplesecurity"
version = "2023.0.1"
version = "2023.0.2"
license = "mit"
description = "Combine multiple popular python security tools and generate reports or output into different formats"
authors = ["FredHappyface"]
Expand Down
4 changes: 2 additions & 2 deletions simplesecurity/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def _processPlugin(args) -> list[Callable]:
},
"safety": {
"func": plugins.safety,
"max_severity": 2,
"max_severity": 4,
"max_confidence": 3,
"fast": True,
},
Expand All @@ -91,7 +91,7 @@ def _processPlugin(args) -> list[Callable]:
},
"dlint": {
"func": plugins.dlint,
"max_severity": 3,
"max_severity": 4,
"max_confidence": 2,
"fast": True,
},
Expand Down
13 changes: 5 additions & 8 deletions simplesecurity/level.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,13 @@


class Level(IntEnum):
"""Levels for confidence and severity.
UNKNOWN = 0
LOW = 1
MED = 2
HIGH = 3
"""
"""Levels for confidence and severity."""

UNKNOWN = 0
LOW = 1
MED = 2
HIGH = 3
CRIT = 4

def __repr__(self) -> str:
"""__repr__ method.
Expand All @@ -43,15 +38,17 @@ def __str__(self) -> str:
Level.LOW: "Low",
Level.MED: "Medium",
Level.HIGH: "High",
Level.CRIT: "Critical",
}
return reprMap[self]

def toSarif(self) -> str:
"""Convert to sarif representation."""
reprMap = {
Level.UNKNOWN: "note",
Level.LOW: "warning",
Level.LOW: "note",
Level.MED: "warning",
Level.HIGH: "error",
Level.CRIT: "error",
}
return reprMap[self]
136 changes: 83 additions & 53 deletions simplesecurity/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,17 @@ def extractEvidence(desiredLine: int, file: str) -> list[Line]:
"""
with open(file, encoding="utf-8", errors="ignore") as fileContents:
start = max(desiredLine - 3, 0)
for line in range(start):
next(fileContents)
content = []
for line in range(start + 1, desiredLine + 3):
try:
try:
for line in range(start):
next(fileContents)
for line in range(start + 1, desiredLine + 3):
lineContent = next(fileContents).rstrip().replace("\t", " ")
except StopIteration:
break
content.append({"selected": line == desiredLine, "line": line, "content": lineContent})
content.append(
{"selected": line == desiredLine, "line": line, "content": lineContent}
)
except StopIteration:
pass
return content


Expand Down Expand Up @@ -115,20 +117,22 @@ def bandit(scanDir=".") -> list[Finding]:
)[1]
)["results"]
for result in results:
file = result["filename"].replace("\\", "/")
file = result.get("filename").replace("\\", "/")
resultId = result.get("test_id")
line = result.get("line_number")
findings.append(
{
"id": result["test_id"],
"title": f"{result['test_id']}: {result['test_name']}",
"description": result["issue_text"],
"id": resultId,
"title": f"{resultId}: {result.get('test_name')}",
"description": result.get("issue_text"),
"file": file,
"evidence": extractEvidence(result["line_number"], file),
"severity": levelMap[result["issue_severity"]],
"confidence": levelMap[result["issue_confidence"]],
"line": result["line_number"],
"evidence": extractEvidence(line, file),
"severity": levelMap[result.get("issue_severity")],
"confidence": levelMap[result.get("issue_confidence")],
"line": line,
"_other": {
"more_info": result["more_info"],
"line_range": result["line_range"],
"more_info": result.get("more_info"),
"line_range": result.get("line_range"),
},
}
)
Expand All @@ -138,23 +142,45 @@ def bandit(scanDir=".") -> list[Finding]:
def _doSafetyProcessing(results: dict[str, Any]) -> list[Finding]:
findings = []
for result in results["vulnerabilities"]:
vulnerabilityId = result.get("vulnerability_id")
packageName = result.get("package_name")
advisory = result.get("advisory")

moreInfo = result.get("more_info_url")
affectedVersions = "; ".join(result.get("affected_versions"))

content = f"{packageName}, version(s)={affectedVersions}"
description = (
f"Vulnerability found in package {packageName},"
f"version(s)={affectedVersions}. {advisory}. More info available at {moreInfo}"
)

cvssv3Score = result.get("severity").get("cvssv3", {}).get("base_score", 0)
severity = Level.LOW
if cvssv3Score > 3.9:
severity = Level.MED
if cvssv3Score > 6.9:
severity = Level.HIGH
if cvssv3Score > 8.9:
severity = Level.CRIT

findings.append(
{
"id": result[4],
"title": f"{result[4]}: {result[0]}",
"description": result[3],
"id": vulnerabilityId,
"title": f"{vulnerabilityId}: {packageName}",
"description": description,
"file": "Project Requirements",
"evidence": [
{
"selected": True,
"line": 0,
"content": f"{result[0]} version={result[2]} affects{result[1]}",
"content": content,
}
],
"severity": Level.MED,
"severity": severity,
"confidence": Level.HIGH,
"line": "Unknown",
"_other": {"id": result[4], "affected": result[1]},
"_other": {"id": vulnerabilityId, "affectedVersions": affectedVersions},
}
)
return findings
Expand Down Expand Up @@ -227,17 +253,18 @@ def dodgy(scanDir=".") -> list[Finding]:
rawResults = _doSysExec(f"dodgy {scanDir} -i {' '.join(EXCLUDED)}")[1]
results = loads(rawResults)["warnings"]
for result in results:
file = "./" + result["path"].replace("\\", "/")
file = "./" + result.get("path").replace("\\", "/")
message = result.get("message")
findings.append(
{
"id": result["code"],
"title": result["message"],
"description": result["message"],
"id": result.get("code"),
"title": message,
"description": message,
"file": file,
"evidence": extractEvidence(result["line"], file),
"evidence": extractEvidence(result.get("line"), file),
"severity": Level.MED,
"confidence": Level.MED,
"line": result["line"],
"line": result.get("line"),
"_other": {},
}
)
Expand Down Expand Up @@ -269,29 +296,31 @@ def dlint(scanDir=".") -> list[Finding]:
"info": Level.LOW,
"minor": Level.MED,
"major": Level.MED,
"critical": Level.HIGH,
"blocker": Level.HIGH,
"critical": Level.CRIT,
"blocker": Level.CRIT,
}
for filePath, scanResults in jsonResults.items():
for scanResult in scanResults:
for result in scanResults:
message = f"{result.get('check_name')}: " f"{result.get('description')}"
positions = result.get("location", {}).get("positions", {})
line = positions.get("begin", {}).get("line", 0)
findings.append(
{
"id": scanResult["check_name"],
"title": f"{scanResult['check_name']}: " f"{scanResult['description']}",
"description": f"{scanResult['check_name']}: " f"{scanResult['description']}",
"id": result.get("check_name"),
"title": message,
"description": message,
"file": filePath,
"evidence": extractEvidence(
scanResult["location"]["positions"]["begin"]["line"],
line,
filePath,
),
"severity": levelMap[scanResult["severity"]],
"severity": levelMap[result.get("severity")],
"confidence": Level.MED,
"line": scanResult["location"]["positions"]["begin"]["line"],
"line": line,
"_other": {
"col": scanResult["location"]["positions"]["begin"]["column"],
"start": scanResult["location"]["positions"]["begin"]["line"],
"end": scanResult["location"]["positions"]["end"]["line"],
"fingerprint": scanResult["fingerprint"],
"start": line,
"end": positions.get("end", {}).get("line", 0),
"fingerprint": result.get("fingerprint"),
},
}
)
Expand Down Expand Up @@ -324,23 +353,24 @@ def semgrep(scanDir=".") -> list[Finding]:
)["results"]
levelMap = {"INFO": Level.LOW, "WARNING": Level.MED, "ERROR": Level.HIGH}
for result in results:
filePath = result["Target"].replace("\\", "/")
filePath = result.get("Target").replace("\\", "/")
file = f"{scanDir}/{filePath}"
resultId = result.get("check_id", "")
extras = result.get("extra", {})
line = result.get("start", {}).get("line", 0)
findings.append(
{
"id": result["check_id"],
"title": result["check_id"].split(".")[-1],
"description": result["extra"]["message"].strip(),
"id": resultId,
"title": resultId.split(".")[-1],
"description": extras("message").strip(),
"file": file,
"evidence": extractEvidence(result["start"]["line"], file),
"severity": levelMap[result["extra"]["severity"]],
"evidence": extractEvidence(line, file),
"severity": levelMap[extras("severity")],
"confidence": Level.HIGH,
"line": result["start"]["line"],
"line": line,
"_other": {
"col": result["start"]["col"],
"start": result["start"],
"end": result["end"],
"extra": result["extra"],
"end": result.get("end"),
"extra": extras,
},
}
)
Expand Down
1 change: 0 additions & 1 deletion tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@

2 changes: 1 addition & 1 deletion tests/data/advanced.sarif
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
},
{
"ruleId": "TEST_ID2",
"level": "warning",
"level": "note",
"message": {
"text": "TEST2: This is a test2"
},
Expand Down
Loading

0 comments on commit 970e8c3

Please sign in to comment.