hex-audit 0.5.6 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DEMO.md +15 -12
- package/README.md +16 -13
- package/dashboard/.next/BUILD_ID +1 -1
- package/dashboard/.next/app-build-manifest.json +11 -11
- package/dashboard/.next/app-path-routes-manifest.json +1 -1
- package/dashboard/.next/build-manifest.json +4 -4
- package/dashboard/.next/next-server.js.nft.json +1 -1
- package/dashboard/.next/prerender-manifest.js +1 -1
- package/dashboard/.next/prerender-manifest.json +1 -1
- package/dashboard/.next/routes-manifest.json +1 -1
- package/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/_not-found.html +1 -1
- package/dashboard/.next/server/app/_not-found.rsc +4 -4
- package/dashboard/.next/server/app/access/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/calls/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/conformance/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/diagram/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/diagram.html +1 -1
- package/dashboard/.next/server/app/diagram.rsc +4 -4
- package/dashboard/.next/server/app/flows/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/flows.html +1 -1
- package/dashboard/.next/server/app/flows.rsc +4 -4
- package/dashboard/.next/server/app/functions/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/issues/page.js +1 -1
- package/dashboard/.next/server/app/issues/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/notes/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/progress/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/report/page.js +1 -0
- package/dashboard/.next/server/app/report/page_client-reference-manifest.js +1 -0
- package/dashboard/.next/server/app/stats/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app-paths-manifest.json +10 -10
- package/dashboard/.next/server/chunks/530.js +1 -1
- package/dashboard/.next/server/functions-config-manifest.json +1 -1
- package/dashboard/.next/server/middleware-build-manifest.js +1 -1
- package/dashboard/.next/server/pages/404.html +1 -1
- package/dashboard/.next/server/pages/500.html +1 -1
- package/dashboard/.next/server/server-reference-manifest.js +1 -1
- package/dashboard/.next/server/server-reference-manifest.json +1 -1
- package/dashboard/.next/static/chunks/app/issues/{page-d1607f57783782ae.js → page-98a298e1c1045c91.js} +1 -1
- package/dashboard/.next/static/chunks/app/{layout-a95b696089e278c3.js → layout-49f2496c7637d931.js} +1 -1
- package/dashboard/.next/static/chunks/app/report/page-796f2f4a8a5ac8f7.js +1 -0
- package/dashboard/.next/static/chunks/{main-9a811c95265dbd11.js → main-63ff429eab01f5bf.js} +1 -1
- package/dashboard/app/issues/IssuesBoardClient.tsx +1 -1
- package/dashboard/app/{overleaf/OverleafClient.tsx → report/ReportClient.tsx} +15 -7
- package/dashboard/app/report/page.tsx +35 -0
- package/dashboard/components/DashboardLayout.tsx +1 -1
- package/dist/commands/init.js +2 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/core/schema.d.ts +14 -0
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +2 -0
- package/dist/core/schema.js.map +1 -1
- package/dist/skills/generate-report.md +571 -0
- package/dist/skills/init-audit.md +1 -1
- package/dist/skills/sync-issues.md +1 -1
- package/dist/skills/validate-all-findings.md +1 -1
- package/dist/skills/validate-finding.md +1 -1
- package/package.json +1 -1
- package/dashboard/.next/server/app/overleaf/page.js +0 -1
- package/dashboard/.next/server/app/overleaf/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/static/chunks/app/overleaf/page-bcea12a80c97b92f.js +0 -1
- package/dashboard/app/overleaf/page.tsx +0 -32
- package/dist/skills/generate-overleaf.md +0 -334
- /package/dashboard/.next/server/app/{overleaf → report}/page.js.nft.json +0 -0
- /package/dashboard/.next/static/{hV9GBuhq9vm6hXiHOWEfE → mIJovZ5WuDGk7ZlzWBn03}/_buildManifest.js +0 -0
- /package/dashboard/.next/static/{hV9GBuhq9vm6hXiHOWEfE → mIJovZ5WuDGk7ZlzWBn03}/_ssgManifest.js +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
globalThis.__RSC_MANIFEST=(globalThis.__RSC_MANIFEST||{});globalThis.__RSC_MANIFEST["/overleaf/page"]={"moduleLoading":{"prefix":"/_next/","crossOrigin":null},"ssrModuleMapping":{"9":{"*":{"id":"6131","name":"*","chunks":[],"async":false}},"1076":{"*":{"id":"9323","name":"*","chunks":[],"async":false}},"1187":{"*":{"id":"7918","name":"*","chunks":[],"async":false}},"1447":{"*":{"id":"5915","name":"*","chunks":[],"async":false}},"2024":{"*":{"id":"2857","name":"*","chunks":[],"async":false}},"2198":{"*":{"id":"9915","name":"*","chunks":[],"async":false}},"3297":{"*":{"id":"1611","name":"*","chunks":[],"async":false}},"3362":{"*":{"id":"5289","name":"*","chunks":[],"async":false}},"3443":{"*":{"id":"7406","name":"*","chunks":[],"async":false}},"3719":{"*":{"id":"526","name":"*","chunks":[],"async":false}},"4595":{"*":{"id":"1388","name":"*","chunks":[],"async":false}},"5268":{"*":{"id":"3817","name":"*","chunks":[],"async":false}},"5276":{"*":{"id":"820","name":"*","chunks":[],"async":false}},"7063":{"*":{"id":"618","name":"*","chunks":[],"async":false}},"7498":{"*":{"id":"696","name":"*","chunks":[],"async":false}},"7542":{"*":{"id":"9555","name":"*","chunks":[],"async":false}},"7701":{"*":{"id":"8530","name":"*","chunks":[],"async":false}},"7780":{"*":{"id":"8664","name":"*","chunks":[],"async":false}},"9487":{"*":{"id":"6844","name":"*","chunks":[],"async":false}},"9690":{"*":{"id":"2204","name":"*","chunks":[],"async":false}},"9745":{"*":{"id":"4136","name":"*","chunks":[],"async":false}},"9922":{"*":{"id":"8033","name":"*","chunks":[],"async":false}}},"edgeSSRModuleMapping":{},"clientModules":{"/home/dx/Work/hex/node_modules/next/dist/client/components/app-router.js":{"id":5268,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/esm/client/components/app-router.js":{"id":5268,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/client/components/client-page.js":{"id":1076,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/esm/client/components/client-page.js":{"id":1076,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/client/components/error-boundary.js":{"id":9690,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/esm/client/components/error-boundary.js":{"id":9690,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/client/components/layout-router.js":{"id":5276,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/esm/client/components/layout-router.js":{"id":5276,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/client/components/not-found-boundary.js":{"id":1447,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/esm/client/components/not-found-boundary.js":{"id":1447,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/client/components/render-from-template-context.js":{"id":3297,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/esm/client/components/render-from-template-context.js":{"id":3297,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/globals.css":{"id":3812,"name":"*","chunks":["7498","static/chunks/7498-ea83cb9e30ec5491.js","3185","static/chunks/app/layout-a95b696089e278c3.js"],"async":false},"/home/dx/Work/hex/dashboard/components/CommandPalette.tsx":{"id":2198,"name":"*","chunks":["7498","static/chunks/7498-ea83cb9e30ec5491.js","3185","static/chunks/app/layout-a95b696089e278c3.js"],"async":false},"/home/dx/Work/hex/dashboard/components/DashboardLayout.tsx":{"id":1187,"name":"*","chunks":["7498","static/chunks/7498-ea83cb9e30ec5491.js","3185","static/chunks/app/layout-a95b696089e278c3.js"],"async":false},"/home/dx/Work/hex/node_modules/next-themes/dist/index.mjs":{"id":4595,"name":"*","chunks":["7498","static/chunks/7498-ea83cb9e30ec5491.js","3185","static/chunks/app/layout-a95b696089e278c3.js"],"async":false},"/home/dx/Work/hex/node_modules/next/font/google/target.css?{\"path\":\"app/layout.tsx\",\"import\":\"Manrope\",\"arguments\":[{\"subsets\":[\"latin\"],\"variable\":\"--font-sans\",\"display\":\"swap\"}],\"variableName\":\"manrope\"}":{"id":8414,"name":"*","chunks":["7498","static/chunks/7498-ea83cb9e30ec5491.js","3185","static/chunks/app/layout-a95b696089e278c3.js"],"async":false},"/home/dx/Work/hex/node_modules/next/font/google/target.css?{\"path\":\"app/layout.tsx\",\"import\":\"JetBrains_Mono\",\"arguments\":[{\"subsets\":[\"latin\"],\"variable\":\"--font-mono\",\"display\":\"swap\"}],\"variableName\":\"jetbrainsMono\"}":{"id":5256,"name":"*","chunks":["7498","static/chunks/7498-ea83cb9e30ec5491.js","3185","static/chunks/app/layout-a95b696089e278c3.js"],"async":false},"/home/dx/Work/hex/dashboard/app/diagram/page.tsx":{"id":3719,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/flows/page.tsx":{"id":3443,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/access/AccessClient.tsx":{"id":9745,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/calls/CallsClient.tsx":{"id":3362,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/notes/NotesClient.tsx":{"id":2024,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/overleaf/OverleafClient.tsx":{"id":9,"name":"*","chunks":["529","static/chunks/app/overleaf/page-bcea12a80c97b92f.js"],"async":false},"/home/dx/Work/hex/dashboard/app/functions/FunctionsClient.tsx":{"id":7780,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/conformance/ConformanceTable.tsx":{"id":7542,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/stats/StatsClient.tsx":{"id":9922,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/progress/ProgressClient.tsx":{"id":7701,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/issues/IssuesBoardClient.tsx":{"id":7063,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/components/MarkdownRenderer.tsx":{"id":9487,"name":"*","chunks":["7397","static/chunks/7397-f6f4dddc7a20bfc1.js","7498","static/chunks/7498-ea83cb9e30ec5491.js","1931","static/chunks/app/page-24bac51dfe007c66.js"],"async":false},"/home/dx/Work/hex/node_modules/next/dist/client/link.js":{"id":7498,"name":"*","chunks":["7397","static/chunks/7397-f6f4dddc7a20bfc1.js","7498","static/chunks/7498-ea83cb9e30ec5491.js","1931","static/chunks/app/page-24bac51dfe007c66.js"],"async":false},"/home/dx/Work/hex/node_modules/next/dist/esm/client/link.js":{"id":7498,"name":"*","chunks":["7397","static/chunks/7397-f6f4dddc7a20bfc1.js","7498","static/chunks/7498-ea83cb9e30ec5491.js","1931","static/chunks/app/page-24bac51dfe007c66.js"],"async":false}},"entryCSSFiles":{"/home/dx/Work/hex/dashboard/":[],"/home/dx/Work/hex/dashboard/app/layout":["static/css/4a38d8f6f6b7a68f.css"],"/home/dx/Work/hex/dashboard/app/page":[],"/home/dx/Work/hex/dashboard/app/overleaf/page":[]}}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[529],{9531:function(e,t,a){Promise.resolve().then(a.bind(a,9))},9:function(e,t,a){"use strict";a.d(t,{OverleafClient:function(){return i}});var s=a(7821),r=a(8078);let n=[{key:"executive_summary",label:"Executive Summary",file:"executive_summary.txt"},{key:"audited_files",label:"Audited Files",file:"audited_files.txt"},{key:"summary_of_findings",label:"Summary of Issues",file:"summary_of_findings.txt"},{key:"findings",label:"Issues",file:"findings.txt"}];function i(e){var t;let{sections:a}=e,[i,o]=(0,r.useState)("executive_summary"),[l,c]=(0,r.useState)(!1),d=a[i],x=async()=>{if(d)try{await navigator.clipboard.writeText(d),c(!0),setTimeout(()=>c(!1),1500)}catch(e){}};return(0,s.jsxs)("div",{children:[(0,s.jsxs)("header",{className:"mb-6",children:[(0,s.jsx)("h1",{className:"text-title font-semibold text-text-primary",children:"Overleaf"}),(0,s.jsxs)("p",{className:"mt-1 text-body text-text-secondary",children:["LaTeX report sections from ",(0,s.jsx)("span",{className:"font-mono text-caption",children:".hex/overleaf/"}),". Copy each into the matching slot of the Nethermind Overleaf template."]})]}),(0,s.jsx)("div",{className:"mb-4 flex flex-wrap gap-1.5",children:n.map(e=>{let t=e.key===i,r=!!a[e.key];return(0,s.jsx)("button",{type:"button",onClick:()=>o(e.key),className:"rounded-md px-3 py-1.5 text-caption font-medium ".concat(t?"bg-accent text-surface-0":"bg-surface-2 text-text-secondary hover:text-text-primary"," ").concat(r?"":"opacity-50"),children:e.label},e.key)})}),(0,s.jsxs)("div",{className:"rounded-lg border border-border-subtle bg-surface-1",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between border-b border-border-subtle px-4 py-2.5",children:[(0,s.jsx)("span",{className:"font-mono text-caption text-text-tertiary",children:null===(t=n.find(e=>e.key===i))||void 0===t?void 0:t.file}),(0,s.jsx)("button",{type:"button",onClick:x,disabled:!d,className:"rounded-md border border-border-default px-2.5 py-1 text-caption text-text-secondary hover:bg-surface-2 hover:text-text-primary disabled:opacity-50",children:l?"Copied!":"Copy"})]}),d?(0,s.jsx)("pre",{className:"max-h-[70vh] overflow-auto p-4 font-mono text-caption leading-relaxed text-text-secondary whitespace-pre-wrap break-words",children:d}):(0,s.jsxs)("p",{className:"p-4 text-body text-text-tertiary",children:["This section has not been generated yet. Run"," ",(0,s.jsx)("span",{className:"font-mono text-caption",children:"/generate-overleaf"}),"."]})]})]})}}},function(e){e.O(0,[7115,3205,1744],function(){return e(e.s=9531)}),_N_E=e.O()}]);
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { readMarkdownFile } from '@/lib/data';
|
|
2
|
-
import { NotYetGenerated } from '@/components/NotYetGenerated';
|
|
3
|
-
import { OverleafClient, type OverleafSections } from './OverleafClient';
|
|
4
|
-
|
|
5
|
-
// Read .hex/overleaf/ at request time, not at build time.
|
|
6
|
-
export const dynamic = 'force-dynamic';
|
|
7
|
-
|
|
8
|
-
export default function OverleafPage() {
|
|
9
|
-
const sections: OverleafSections = {
|
|
10
|
-
executive_summary: readMarkdownFile('overleaf/executive_summary.txt'),
|
|
11
|
-
audited_files: readMarkdownFile('overleaf/audited_files.txt'),
|
|
12
|
-
summary_of_findings: readMarkdownFile('overleaf/summary_of_findings.txt'),
|
|
13
|
-
findings: readMarkdownFile('overleaf/findings.txt'),
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const anyPresent = Object.values(sections).some(Boolean);
|
|
17
|
-
if (!anyPresent) {
|
|
18
|
-
return (
|
|
19
|
-
<div>
|
|
20
|
-
<header className="mb-6">
|
|
21
|
-
<h1 className="text-title font-semibold text-text-primary">Overleaf</h1>
|
|
22
|
-
<p className="mt-1 text-body text-text-secondary">
|
|
23
|
-
LaTeX report sections, ready to paste into the Nethermind Overleaf template.
|
|
24
|
-
</p>
|
|
25
|
-
</header>
|
|
26
|
-
<NotYetGenerated command="/generate-overleaf" />
|
|
27
|
-
</div>
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return <OverleafClient sections={sections} />;
|
|
32
|
-
}
|
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Generate the four LaTeX section files for the final audit report (Overleaf-ready)"
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Skill: Generate Overleaf
|
|
6
|
-
|
|
7
|
-
**Recommended model:** Sonnet
|
|
8
|
-
|
|
9
|
-
This skill produces the four LaTeX section files an auditor uploads into the Nethermind Overleaf template at the end of an engagement. It runs from the GitHub-synced issues (the report's source of truth), after findings have been pushed via /sync-issues.
|
|
10
|
-
|
|
11
|
-
## What it writes
|
|
12
|
-
|
|
13
|
-
Four `.txt` files in `<output_dir>/overleaf/`:
|
|
14
|
-
|
|
15
|
-
1. `executive_summary.txt` — `\section{Executive Summary}` body with project synopsis, severity histogram, status histogram, summary table of audit metadata.
|
|
16
|
-
2. `audited_files.txt` — `\section{Audited Files}` body with a LaTeX table of in-scope files (LoC, comments, ratio, blank, total).
|
|
17
|
-
3. `summary_of_findings.txt` — `\section{Summary of Issues}` body with hyperlinked finding rows.
|
|
18
|
-
4. `findings.txt` — `\section{Issues}` body with one `\subsection{[Sev] title}\label{issue:N}` per synced finding, including description, code blocks, recommendation, status, client update.
|
|
19
|
-
|
|
20
|
-
Output is plain `.txt` so the auditor pastes content into the matching Overleaf template slots. The skill does NOT compile LaTeX itself.
|
|
21
|
-
|
|
22
|
-
## Phase 0 — Gather report metadata
|
|
23
|
-
|
|
24
|
-
Read `<output_dir>/config.json`. Look under `settings.report.*` for:
|
|
25
|
-
|
|
26
|
-
- `repository_url` — e.g. `https://github.com/mellow-finance/flexible-vaults`. Required for hyperref links in the audited files table and per-finding file links.
|
|
27
|
-
- `initial_commit` — commit hash for the initial report scope.
|
|
28
|
-
- `final_commit` — commit hash after fixes (defaults to `initial_commit` if no remediation cycle).
|
|
29
|
-
- `initial_report_date` — date the initial report was delivered (e.g. `May 22, 2026`).
|
|
30
|
-
- `final_report_date` — date the final report was delivered (defaults to `initial_report_date`).
|
|
31
|
-
- `audit_type` — defaults to `Security Review`.
|
|
32
|
-
- `doc_assessment` — `High` / `Medium` / `Low`.
|
|
33
|
-
- `test_assessment` — `High` / `Medium` / `Low`.
|
|
34
|
-
|
|
35
|
-
For each missing field, use **AskUserQuestion** to prompt the auditor. After collection, persist all values back to `config.json` under `settings.report.*` so re-runs don't re-prompt.
|
|
36
|
-
|
|
37
|
-
If `repository_url` is not set, also offer to derive it from the project's git remote (`git -C <project_dir> remote get-url origin`).
|
|
38
|
-
|
|
39
|
-
## Phase 0.5 — Require synced issues (GitHub is the source of truth)
|
|
40
|
-
|
|
41
|
-
The report is generated **only** from issues that are synced to GitHub (`tracking.status === "synced"`). GitHub is the single source of truth for finding content; the local Potential/Verified columns are a staging area.
|
|
42
|
-
|
|
43
|
-
Before doing anything else:
|
|
44
|
-
- If `settings.github.repo` is not set, **abort**: "The report is generated from GitHub-synced issues. Configure `settings.github.repo` (or pass `--github-repo` to `hex init`) and run `/sync-issues` first."
|
|
45
|
-
- If there are zero `synced` findings, **abort**: "No synced issues found. Verify findings, then run `/sync-issues` to push them to GitHub before generating the report."
|
|
46
|
-
|
|
47
|
-
## Phase 1 — Compute the histograms and counts
|
|
48
|
-
|
|
49
|
-
Read `<output_dir>/findings.json` and `<output_dir>/tracking.json`.
|
|
50
|
-
|
|
51
|
-
**Report findings** are findings whose tracking entry has `status: "synced"`. These are the ones that go in the report. Sort by severity (Critical → High → Medium → Low → Info), then by id within each severity.
|
|
52
|
-
|
|
53
|
-
Severity histogram (count of synced findings per severity):
|
|
54
|
-
```
|
|
55
|
-
{ "Critical": N, "High": N, "Medium": N, "Low": N, "Undetermined": 0, "Info": N, "Best Practices": 0 }
|
|
56
|
-
```
|
|
57
|
-
(`Undetermined` and `Best Practices` are not currently in Hex's severity model — render them as 0 to match the Nethermind template.)
|
|
58
|
-
|
|
59
|
-
Resolution histogram (count of synced findings per `resolution` field):
|
|
60
|
-
```
|
|
61
|
-
{ "Fixed": N, "Acknowledged": N, "Mitigated": N, "Not Fixed": 0, "Unresolved": N }
|
|
62
|
-
```
|
|
63
|
-
Findings without a `resolution` field count as `Unresolved`.
|
|
64
|
-
|
|
65
|
-
## Phase 2 — Build the protocol synopsis paragraph
|
|
66
|
-
|
|
67
|
-
Read `<output_dir>/overview.md`. Produce a roughly half-page (~120-180 words) plain-language summary of what the protocol does and the security-relevant mechanics. This becomes the second paragraph of `executive_summary.txt`. Match the tone of the Nethermind example:
|
|
68
|
-
|
|
69
|
-
- Open with one sentence on the project's purpose and the in-scope contract(s).
|
|
70
|
-
- Use a short `\begin{itemize}[leftmargin=*,itemsep=4pt] ... \end{itemize}` to list 2-3 of the security-relevant axes (e.g., access-control gates, asset-flow surfaces, upgradeability boundaries).
|
|
71
|
-
- Close with one or two sentences on any notable edge cases the auditor wants to flag generally (an entry point that bypasses a typical gate, a non-obvious permission, etc.).
|
|
72
|
-
|
|
73
|
-
Style hints:
|
|
74
|
-
- Refer to contracts as `\texttt{ContractName}`, role constants as `\texttt{ROLE\_NAME}`, function names as `\texttt{name(...)}`.
|
|
75
|
-
- Bold key terms with `\textbf{...}`.
|
|
76
|
-
- No code blocks in this paragraph — those belong in the per-finding sections.
|
|
77
|
-
|
|
78
|
-
## Phase 3 — Write `executive_summary.txt`
|
|
79
|
-
|
|
80
|
-
```latex
|
|
81
|
-
\pagebreak \vspace*{0cm}
|
|
82
|
-
\sectioncolor
|
|
83
|
-
\section{Executive Summary}
|
|
84
|
-
\black
|
|
85
|
-
This document presents the results of the security review conducted by \href{https://www.nethermind.io/smart-contract-audits}{Nethermind Security} for <PROJECT_NAME>'s <SCOPE_DESCRIPTION>.
|
|
86
|
-
|
|
87
|
-
<AI-GENERATED PROTOCOL SYNOPSIS PARAGRAPH FROM PHASE 2>
|
|
88
|
-
|
|
89
|
-
\textbf{The audit comprises <TOTAL_NSLOC>} lines of Solidity code. \textbf{The audit was performed using} (a)~manual analysis of the codebase, and (b)~automated analysis tools.
|
|
90
|
-
|
|
91
|
-
\textbf{Along this document, we report} <ISSUE_COUNT_PHRASE>.
|
|
92
|
-
%
|
|
93
|
-
The issues are summarized in Fig.~1.
|
|
94
|
-
|
|
95
|
-
\textbf{This document is organized as follows.}
|
|
96
|
-
%
|
|
97
|
-
{Section~2} presents the files in the scope.
|
|
98
|
-
%
|
|
99
|
-
{Section~3} presents the summary of issues.
|
|
100
|
-
%
|
|
101
|
-
{Section~4} presents the System Overview.
|
|
102
|
-
%
|
|
103
|
-
{Section~5} discusses the risk rating methodology.
|
|
104
|
-
%
|
|
105
|
-
{Section~6} details the issues.
|
|
106
|
-
%
|
|
107
|
-
{Section~7} discusses the documentation provided by the client for this audit.
|
|
108
|
-
%
|
|
109
|
-
{Section~8} presents the test suite evaluation and automated tools used.
|
|
110
|
-
%
|
|
111
|
-
{Section~9} concludes the document.
|
|
112
|
-
\color{black}
|
|
113
|
-
|
|
114
|
-
\begin{figure}[H]
|
|
115
|
-
\centering
|
|
116
|
-
\subfigure[]
|
|
117
|
-
{
|
|
118
|
-
\includegraphics[trim=0cm 0cm 0cm 0cm, clip=true, width=0.45\textwidth]{img/Severity.pdf}
|
|
119
|
-
\label{fig:severity}
|
|
120
|
-
}
|
|
121
|
-
\subfigure[]
|
|
122
|
-
{
|
|
123
|
-
\includegraphics[trim=0cm 0cm 0cm 0cm, clip=true, width=0.45\textwidth]{img/Status.pdf}
|
|
124
|
-
\label{fig:status}
|
|
125
|
-
}
|
|
126
|
-
\label{fig:trapezio}
|
|
127
|
-
\end{figure}
|
|
128
|
-
\begin{center}
|
|
129
|
-
\begin{footnotesize}
|
|
130
|
-
\textbf{Fig.~1: Distribution of issues:} \textbf{Critical}~(<C>), \textbf{High}~(<H>), \textbf{Medium}~(<M>), \textbf{Low}~(<L>), \textbf{Undetermined}~(0), \textbf{Informational}~(<I>), \textbf{Best Practices}~(0).\\
|
|
131
|
-
\textbf{Distribution of status:} \textbf{Fixed}~(<F>), \textbf{Acknowledged}~(<A>), \textbf{Mitigated}~(<MI>), \textbf{Unresolved}~(<U>)
|
|
132
|
-
\end{footnotesize}
|
|
133
|
-
\end{center}
|
|
134
|
-
|
|
135
|
-
\color{black}
|
|
136
|
-
|
|
137
|
-
\begin{longtable}[c]{ll}
|
|
138
|
-
\caption*{\textbf{Summary of the Audit}} \\ \hline
|
|
139
|
-
\textbf{Audit Type} & <AUDIT_TYPE> \\
|
|
140
|
-
\textbf{Initial Report} & <INITIAL_REPORT_DATE> \\
|
|
141
|
-
\textbf{Final Report} & <FINAL_REPORT_DATE> \\
|
|
142
|
-
\textbf{Initial Commit} & \href{<REPOSITORY_URL>/blob/<INITIAL_COMMIT>/<FIRST_SCOPE_FILE>}{<INITIAL_COMMIT_SHORT>} \\
|
|
143
|
-
\textbf{Final Commit} & \href{<REPOSITORY_URL>/commit/<FINAL_COMMIT>}{<FINAL_COMMIT_SHORT>} \\
|
|
144
|
-
\textbf{Documentation Assessment} & <DOC_ASSESSMENT> \\
|
|
145
|
-
\textbf{Test Suite Assessment} & <TEST_ASSESSMENT> \\ \hline
|
|
146
|
-
\end{longtable>
|
|
147
|
-
\color{black}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
Substitutions:
|
|
151
|
-
- `<PROJECT_NAME>` ← `config.json.project.name`.
|
|
152
|
-
- `<SCOPE_DESCRIPTION>` ← if a single in-scope file, `\texttt{<filename without extension>}` followed by a single-clause description from the overview; if many, `the contracts listed in Section~2`.
|
|
153
|
-
- `<TOTAL_NSLOC>` ← `stats.json.totals.nsloc`.
|
|
154
|
-
- `<ISSUE_COUNT_PHRASE>` ← something like "five points of attention, where one is classified as `\texttt{Low}`, and four are classified as `\texttt{Informational}` severity." Build dynamically from the severity histogram. If 0 synced findings: "no points of attention requiring remediation." If 1: "one point of attention, classified as `\texttt{<severity>}` severity." Pluralize properly.
|
|
155
|
-
- `<C><H><M><L><I>` ← severity histogram counts.
|
|
156
|
-
- `<F><A><MI><U>` ← resolution histogram counts.
|
|
157
|
-
- `<INITIAL_COMMIT_SHORT>` ← first 7 chars of the commit hash.
|
|
158
|
-
- `<FIRST_SCOPE_FILE>` ← relative path of the first file in `config.json.project.scope` (for the initial commit hyperref, which the template anchors to a specific file).
|
|
159
|
-
|
|
160
|
-
## Phase 4 — Write `audited_files.txt`
|
|
161
|
-
|
|
162
|
-
Compute per-file line counts from each scope file. For each in-scope file in `config.json.project.scope`:
|
|
163
|
-
|
|
164
|
-
- Read the file. Count:
|
|
165
|
-
- `code` lines (non-blank, non-comment).
|
|
166
|
-
- `comments` (lines starting with `//` or `#`, or any line inside a `/* ... */` block).
|
|
167
|
-
- `blank` (empty after `.strip()`).
|
|
168
|
-
- `total` = sum of the three.
|
|
169
|
-
- `ratio` = `round(comments * 100 / max(code, 1), 0)` followed by `\%`.
|
|
170
|
-
|
|
171
|
-
Render the table:
|
|
172
|
-
|
|
173
|
-
```latex
|
|
174
|
-
\pagebreak \vspace*{0cm}
|
|
175
|
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
176
|
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
177
|
-
\sectioncolor
|
|
178
|
-
\section{Audited Files}
|
|
179
|
-
\black
|
|
180
|
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
181
|
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
182
|
-
|
|
183
|
-
\begin{table}[H]
|
|
184
|
-
\centering
|
|
185
|
-
\begin{footnotesize}
|
|
186
|
-
\begin{tabular}{|p{.5cm}|p{9cm}|p{1cm}|p{1.5cm}|p{1cm}|p{1cm}|p{1cm}|}
|
|
187
|
-
\hline
|
|
188
|
-
&\textbf{Contract} & \textbf{LoC} & \textbf{Comments} & \textbf{Ratio} & \textbf{Blank} & \textbf{Total} \\ \hline
|
|
189
|
-
<N> & \href{<REPOSITORY_URL>/blob/<INITIAL_COMMIT>/<FILE_PATH>}{ \texttt{<FILENAME>}} & <code> & <comments> & <ratio>\% & <blank> & <total> \\ \hline
|
|
190
|
-
...
|
|
191
|
-
& \textbf{Total} & \textbf{<sum-code>} & \textbf{<sum-comments>} & \textbf{<aggregate-ratio>\%} & \textbf{<sum-blank>} & \textbf{<sum-total>} \\ \hline
|
|
192
|
-
%%
|
|
193
|
-
\end{tabular}
|
|
194
|
-
\end{footnotesize}
|
|
195
|
-
\end{table}
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
- `<FILENAME>` is the basename, LaTeX-escaped (no extension processing — show e.g., `ThreeFModule.sol`).
|
|
199
|
-
- `<FILE_PATH>` is the path relative to the project root (`src/utils/ThreeFModule.sol`).
|
|
200
|
-
- Number rows sequentially `1, 2, 3 ...`.
|
|
201
|
-
- Aggregate ratio = `round(sum-comments * 100 / max(sum-code, 1), 0)`.
|
|
202
|
-
|
|
203
|
-
## Phase 5 — Write `summary_of_findings.txt`
|
|
204
|
-
|
|
205
|
-
For each synced finding in severity-sorted order (Critical → Info), assign a sequential `issue:N` label starting at `issue:0`. This same label is used in `findings.txt` for the `\hyperref`.
|
|
206
|
-
|
|
207
|
-
```latex
|
|
208
|
-
%\pagebreak \vspace*{0cm}
|
|
209
|
-
|
|
210
|
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
211
|
-
%%%%%%%%%%%% H E A D E R 1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
212
|
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
213
|
-
\sectioncolor
|
|
214
|
-
\section{Summary of Issues}
|
|
215
|
-
\black
|
|
216
|
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
217
|
-
\begin{table}[H]
|
|
218
|
-
\centering
|
|
219
|
-
\begin{footnotesize}
|
|
220
|
-
\begin{tabular}{|p{1cm}|p{11cm}|p{2.1cm}|p{2.1cm}|}
|
|
221
|
-
\hline
|
|
222
|
-
& \textbf{Finding} & \textbf{Severity} & \textbf{Update} \\ \hline
|
|
223
|
-
<N>&\hyperref[issue:<I>]{<title-LaTeX-escaped>} &<Severity-display> & <Resolution-display>\\ \hline
|
|
224
|
-
%
|
|
225
|
-
\end{tabular}
|
|
226
|
-
\end{footnotesize}
|
|
227
|
-
\end{table}
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
- `<N>` is the 1-based row counter.
|
|
231
|
-
- `<I>` matches the `\label{issue:N}` index used in `findings.txt`.
|
|
232
|
-
- `<Severity-display>` maps `Info` → `Info`, others use their name as-is.
|
|
233
|
-
- `<Resolution-display>` maps the `resolution` field directly (`Fixed`, `Acknowledged`, `Mitigated`, `Not Fixed`); blank/`Unresolved` shows `Unresolved`.
|
|
234
|
-
|
|
235
|
-
## Phase 6 — Write `findings.txt`
|
|
236
|
-
|
|
237
|
-
For each synced finding in the same order (severity-sorted), render one subsection. Use the index `i` (0-based) matching `summary_of_findings.txt`.
|
|
238
|
-
|
|
239
|
-
```latex
|
|
240
|
-
\pagebreak \vspace*{0cm}
|
|
241
|
-
|
|
242
|
-
\sectioncolor
|
|
243
|
-
\section{Issues}
|
|
244
|
-
\black
|
|
245
|
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
246
|
-
|
|
247
|
-
<per-finding block>
|
|
248
|
-
|
|
249
|
-
<per-finding block>
|
|
250
|
-
|
|
251
|
-
...
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
Each per-finding block:
|
|
255
|
-
|
|
256
|
-
```latex
|
|
257
|
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
258
|
-
%%%%%%%%%%%% H E A D E R 3 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
259
|
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
260
|
-
\subsubsectioncolor
|
|
261
|
-
\subsection{[<Severity-display>] <title-LaTeX-escaped>}\label{issue:<i>}
|
|
262
|
-
\begin{footnotesize} \black
|
|
263
|
-
|
|
264
|
-
\textbf{File(s)}: \href{<REPOSITORY_URL>/blob/<INITIAL_COMMIT>/<FILE_PATH>}{ \texttt{<FILE_PATH>}}
|
|
265
|
-
|
|
266
|
-
\textbf{Description}: <description converted from markdown to LaTeX>
|
|
267
|
-
|
|
268
|
-
<each code block from description rendered as \begin{minted}[linenos,firstnumber=1]{solidity} ... \end{minted}>
|
|
269
|
-
|
|
270
|
-
\textbf{Recommendation(s)}: <recommendation converted from markdown to LaTeX>
|
|
271
|
-
|
|
272
|
-
\textbf{Status}: <Resolution-display or "Unresolved">
|
|
273
|
-
|
|
274
|
-
\textbf{Update from the client}: <update_from_client, LaTeX-escaped>
|
|
275
|
-
|
|
276
|
-
\end{footnotesize}
|
|
277
|
-
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
If the finding has multiple `root_cause.locations[]`, list them as `\href{...}{...}, \href{...}{...}` comma-separated.
|
|
281
|
-
|
|
282
|
-
### Markdown → LaTeX conversion rules
|
|
283
|
-
|
|
284
|
-
Apply to `description`, `recommendation`, and `update_from_client` (in that order, on non-code-block text only — first split out fenced code blocks, then convert the prose):
|
|
285
|
-
|
|
286
|
-
| Markdown | LaTeX |
|
|
287
|
-
|---|---|
|
|
288
|
-
| `` `text` `` | ` \texttt{text}` (leading space intentional, matches Nethermind template) |
|
|
289
|
-
| `**text**` | ` \textbf{text}` |
|
|
290
|
-
| `[label](url)` | ` \href{url}{label}` — if `label` contains `#`, replace with `/#` (anchors break in LaTeX otherwise) |
|
|
291
|
-
| `_` (literal underscore in prose) | `\_` |
|
|
292
|
-
| `^` | `\^{}` |
|
|
293
|
-
| `%` (only when no `](` was present on the line — to avoid mangling URLs) | `\%` |
|
|
294
|
-
| Numbered list `1. text` | `\begin{enumerate}\n \def\labelenumi{\arabic{enumi}.} \tightlist\n\item text;\n...\end{enumerate}` |
|
|
295
|
-
| Bulleted list `- text` | `\begin{itemize}\n\tightlist\n\item text;\n...\end{itemize}` |
|
|
296
|
-
| Fenced code block ` ```solidity ` | `\begin{minted}[linenos,firstnumber=1]{solidity}` ... `\end{minted}` — also support `python`, `typescript`, `javascript`, `cairo` (use `python` lexer), `diff`, `shell`, `rust` |
|
|
297
|
-
|
|
298
|
-
End list items with `;` (replace trailing `.` with `;`). Last item still ends with `;`.
|
|
299
|
-
|
|
300
|
-
The markdown-to-LaTeX logic matches the spirit of the Python script `create-section-findings.py` referenced by the auditor — port that semantically into the skill's instructions rather than calling it.
|
|
301
|
-
|
|
302
|
-
### Severity-display mapping
|
|
303
|
-
- `Critical` → `Critical`
|
|
304
|
-
- `High` → `High`
|
|
305
|
-
- `Medium` → `Medium`
|
|
306
|
-
- `Low` → `Low`
|
|
307
|
-
- `Info` → `Info` (the Nethermind template uses `Info` in the subsection headers and `Informational` in the histogram caption)
|
|
308
|
-
|
|
309
|
-
## Phase 7 — Final report
|
|
310
|
-
|
|
311
|
-
After writing all four files, print:
|
|
312
|
-
|
|
313
|
-
```
|
|
314
|
-
Wrote 4 LaTeX section files to <output_dir>/overleaf/:
|
|
315
|
-
- executive_summary.txt (<N> bytes)
|
|
316
|
-
- audited_files.txt (<N> bytes)
|
|
317
|
-
- summary_of_findings.txt (<N> bytes)
|
|
318
|
-
- findings.txt (<N> bytes)
|
|
319
|
-
|
|
320
|
-
Synced findings included: <count>
|
|
321
|
-
Critical=<C> High=<H> Medium=<M> Low=<L> Info=<I>
|
|
322
|
-
|
|
323
|
-
Status distribution:
|
|
324
|
-
Fixed=<F> Acknowledged=<A> Mitigated=<MI> Unresolved=<U>
|
|
325
|
-
|
|
326
|
-
Upload these into your Overleaf project's Section 1 / 2 / 3 / 6 slots respectively.
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
## What this skill does NOT do
|
|
330
|
-
|
|
331
|
-
- Does not compile LaTeX (no `pdflatex` invocation).
|
|
332
|
-
- Does not modify any file outside `<output_dir>/overleaf/` and (with permission) `config.json` under `settings.report.*`.
|
|
333
|
-
- Does not push to Overleaf, GitHub, or any remote — output is local plain-text.
|
|
334
|
-
- Does not include `rejected`, `duplicate`, `pending_validation`, `unverified`, or `verified`-but-not-yet-synced findings. Only `synced` (on GitHub) makes the cut.
|
|
File without changes
|
/package/dashboard/.next/static/{hV9GBuhq9vm6hXiHOWEfE → mIJovZ5WuDGk7ZlzWBn03}/_buildManifest.js
RENAMED
|
File without changes
|
/package/dashboard/.next/static/{hV9GBuhq9vm6hXiHOWEfE → mIJovZ5WuDGk7ZlzWBn03}/_ssgManifest.js
RENAMED
|
File without changes
|