Safe Penetration Testing Labs · beginner · ~12 min
Take a `finding` struct and render it as a Markdown report section.
snprintf into a bounded buffer with ## title / **Severity:** ... / ### Evidence / ... / ### Recommendation / .... Reject buffers that would overflow.
The hardest part of any security engagement is the writeup. A clean Markdown template — title, severity, affected asset, evidence, recommendation — is what turns notes into a deliverable.
This exercise teaches the formatter side: given a struct, produce the Markdown a human can read.
typedef struct {
const char *title; // "Missing HSTS header"
const char *severity; // "Low", "Medium", "High"
const char *asset; // "https://example.com/"
const char *evidence; // "Response missing 'Strict-Transport-Security'"
const char *recommendation;// "Add HSTS with max-age >= 31536000"
} finding_t;
Implement int render_finding(const finding_t *f, char *out, size_t cap)
that writes the Markdown into out (capped at cap-1 bytes + NUL).
Return the number of bytes written, or -1 if the buffer would overflow.
## Missing HSTS header
**Severity:** Medium
**Asset:** https://example.com/
### Evidence
Response missing 'Strict-Transport-Security'
### Recommendation
Add HSTS with max-age >= 31536000
sprintf without checking the length. Use snprintf and the
return-value-vs-cap check.Strings in, Markdown out. Use snprintf with a bounded buffer; check both branches of its return value.