Skip to content

Commit

Permalink
Add markdown report support
Browse files Browse the repository at this point in the history
  • Loading branch information
forefy committed Feb 9, 2024
1 parent 4e76b56 commit 6575e01
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 8 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,4 @@ dist/
**/cache
.vscode
*[0-9][0-9].py
*eburger-output.json
*.sarif
*eburger-output*
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Template Based Smart Contracts Static Analyzer

<p align="center">
<img src="https://github.com/forefy/eburger/raw/main/static/eburger.png" alt="eBurger" title="eBurger" width="400"/>
<img src="https://github.com/forefy/eburger/raw/main/static/eburger.png" alt="eBurger" title="eBurger" width="450"/>
</p>

<p align="center">
Expand Down Expand Up @@ -70,14 +70,21 @@ cat eburger-output.json
<br>

SARIF output
```
```bash
eburger -f MyProject/ -o sarif
```

<br>

Focused scan of a single file and it's dependencies:
Markdown output
```bash
eburger -f MyProject/ -o markdown
```

<br>

Focused scan of a single file and it's dependencies:
```bash
eburger -f ../ProjectToScan/src/SomeContract.sol
```

Expand Down Expand Up @@ -132,6 +139,7 @@ Forgot one or made a mistake? open a pull request or an issue :)
- Fast learning curve for creating templates, ability to customize templates to the current ongoing audit project
- Foundry and Hardhat support ❣️
- SARIF support & VSCode GUI integration
- Markdown report
- Community and free support via [Discord](https://discord.gg/WaVMpBtxdB)


Expand Down
4 changes: 4 additions & 0 deletions eburger/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
calculate_nsloc,
draw_nsloc_table,
save_as_json,
save_as_markdown,
save_as_sarif,
)
from eburger.yaml_parser import process_files_concurrently
Expand Down Expand Up @@ -246,6 +247,9 @@ def main():
if args.output == "sarif":
results_path = settings.project_root / f"eburger-output.sarif"
save_as_sarif(results_path, insights)
elif args.output in ["markdown", "md"]:
results_path = settings.project_root / f"eburger-output.md"
save_as_markdown(results_path, analysis_output)
else:
save_as_json(results_path, analysis_output)

Expand Down
5 changes: 4 additions & 1 deletion eburger/utils/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,11 @@ def log(type: str, message: str):
print(f"[{color.Success} 🍔 Success {color.Default}] {message}")
case "error":
print(f"[{color.Error} Error {color.Default}] {message}")
post_error_message = " We are so sorry 😭🍔 please consider"
if not args.debug:
post_error_message += " running with --debug or"
print(
" We are so sorry 😭🍔 try running with --debug or create an issue on https://github.com/forefy/eburger/issues/new?assignees=forefy&template=bug_report.md&title=Tool%20error%20report"
f"{post_error_message} creating an issue on https://github.com/forefy/eburger/issues/new?assignees=forefy&template=bug_report.md&title=Tool%20error%20report"
)
sys.exit(0)
case "warning":
Expand Down
91 changes: 89 additions & 2 deletions eburger/utils/outputs.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Silence tool prints
from datetime import datetime
import json
import os
from pathlib import Path
import sys
from prettytable import PrettyTable
from prettytable import PrettyTable, MARKDOWN
from pygount import ProjectSummary, SourceAnalysis

from eburger import settings
Expand All @@ -16,6 +17,92 @@ def save_as_json(file_path: Path, json_data: dict):
json.dump(json_data, outfile, indent=4)


def save_as_markdown(output_file_path: Path, json_data: dict):
md_report_root_dir = Path(output_file_path).resolve().parent

markdown_content = "# eBurger Static Analysis Report\n\n"
markdown_content += f"This report was generated by the [eBurger](https://github.com/forefy/eburger) static analyzer on {datetime.now().strftime('%d.%m.%Y at %H:%M')}.\n\nThe results are not intended to substitute for comprehensive audits or professional assessments, and should be used only as a tool to help identify possible security vulnerabilities or insights and not for any other purpose.\n\n"

markdown_content += "## Insights Summary\n\n"
markdown_content += "| Issue | Severity | Occurrences |\n"
markdown_content += "|-------|----------|-------------|\n"

details_md = ""

for issue in json_data["insights"]:
name = f"[{issue['severity']}] {issue['name']}"
severity = issue["severity"]
occurrences = len(issue["results"])
anchor_name = (
name.replace(" ", "-")
.replace(",", "")
.replace(".", "")
.replace("[", "")
.replace("]", "")
.lower()
)

# Add issue to the table with a hyperlink to its detailed description
markdown_content += (
f"| [{name}](#{anchor_name}) | {severity} | {occurrences} |\n"
)

# Generate detailed description for each issue
details_md += f"\n### {name}\n{issue['description']}\n\n"
details_md += "#### Vulnerable Locations\n"
for result in issue["results"]:
try:
# Convert the file path to be absolute and normalize it
full_path = Path(result["file"]).resolve()
# Calculate the relative path safely
relative_path = full_path.relative_to(md_report_root_dir)

line_info, column_info = (
result["lines"]
.replace("Line ", "")
.replace("Columns ", "")
.split(" ")
)
start_line = line_info
start_column, end_column = column_info.split("-")
location_format = (
f"{relative_path}:{start_line}:{start_column}-{end_column}"
)
details_md += f"- {location_format}\n"

# Include the vulnerable code snippet
if "code" in result:
code_snippet = result["code"].replace(
"\n", "\n\t"
) # Indent for better readability
details_md += f"\t```\n\t{code_snippet}\n\t```\n"
except ValueError as e:
log("error", f"Error processing path {result['file']}: {e}")

details_md += "\n"

if "action-items" in issue:
details_md += (
"#### Action Items\n"
+ "\n".join(f"- {item}" for item in issue["action-items"])
+ "\n\n"
)
if "references" in issue:
details_md += (
"#### References\n"
+ "\n".join(f"- [{ref}]({ref})" for ref in issue["references"])
+ "\n\n"
)
details_md += "---\n"

markdown_content += "\n" + details_md

markdown_content += '<p align=center>Generated by <a href=https://github.com/forefy/eburger title="eBurger">eBurger</a> </p>\n'

with open(output_file_path, "w") as md_file:
md_file.write(markdown_content)


def convert_severity_to_sarif_level(severity: str) -> str:
match severity:
case "High":
Expand Down Expand Up @@ -157,7 +244,7 @@ def save_as_sarif(output_file_path: Path, insights: dict):
json.dump(sarif_json, outfile, indent=4)


def calculate_nsloc() -> (list, list):
def calculate_nsloc() -> tuple[list, list]:
project_summary = ProjectSummary()
project_sources = []
solidity_file_or_folder = Path(args.solidity_file_or_folder)
Expand Down

0 comments on commit 6575e01

Please sign in to comment.