Skip to content
Reference

Report template tags

Every tag available in a Report Profile's Document template, and the rules for how the three tag systems combine.

RedScribe reports are authored as one free-form document per Report Profile (the Document tab on a profile’s edit page). You write headings for structure and drop {{ tag }} placeholders wherever you want dynamic content to appear. This page documents every tag currently available, how each behaves, and the rules for how they combine.

There are three independent tag systems. They look the same ({{ name }}) but behave differently. See How the systems differ before relying on edge-case behavior.

This is simple text substitution: the tag is replaced with a plain string value from the current engagement/user. These work anywhere text can appear: directly in the Document body, and inside any custom text block’s content, any finding section, retest notes, observations, and testing-phase entries.

Tag Value
{{ client_name }} Engagement.client_name
{{ reference_number }} Engagement.reference_number
{{ scope }} Engagement.scope (free text)
{{ start_date }} Engagement.start_date, ISO format, or empty if unset
{{ end_date }} Engagement.end_date, ISO format, or empty if unset
{{ report_date }} Today’s date (ISO format), computed at render time
{{ prepared_by }} The user generating the report, or empty if none

If a placeholder tag’s name isn’t recognized, it’s left in the output unchanged (e.g. a typo like {{ cilent_name }} prints literally rather than erroring or vanishing).

Each of these pulls in a specific chunk of real engagement/finding data. They only work as a standalone paragraph in the Document template. Put the tag alone on its own line, directly under the heading you want it to belong to. They cannot be used inside a text block, finding section, or anywhere else, only in the Document body itself.

Tag What it renders Notes
{{ cover_page }} The report’s own cover page, built from the Report Profile’s Appearance settings and the engagement’s own fields (cover title, client, reference number, dates, classification label) Not automatic: a template with no {{ cover_page }} tag gets no cover page at all, the same as any other structural tag
{{ table_of_contents }} A table of contents, using the section numbers computed from your template’s own heading structure Placement matters: sections above this tag in the template won’t be numbered relative to it, since numbering is computed by walking the template top to bottom
{{ document_control }} A table of the engagement’s status history (stage / date / changed by) Same content as {{p document_control }} in a DOCX template
{{ breakdown_of_findings }} Severity/status bar chart (with a table fallback) plus a findings summary table (ID, severity, title, status)
{{ finding_details }} The full write-up for every included finding: metadata table, then each active finding section in its configured order (see Finding sections below, which includes Affected Assets), and (on a remediation report) retest history This is the main body of the report, and it’s almost always required
{{ observations }} Free-form dynamic entries configured per-engagement (title + rich content), each as its own subsection Empty/omitted entirely if none are configured, with no placeholder text shown
{{ testing_phases }} Same pattern as observations, free-form per-engagement phase entries Empty/omitted if none are configured
{{ assessment_team }} One subsection per user actually assigned to the engagement, showing their bio and qualifications Omitted entirely if no one is assigned. Superadmins and anyone else with blanket instance-wide access are excluded unless they’re specifically assigned to this engagement
{{ checklist_coverage }} The engagement’s checklist run(s), grouped by category, showing item status and any linked findings. A Blocked check’s status includes its reason (“Blocked: …”), so testing limitations appear in the report Shows a graceful “No checklist runs have been recorded for this engagement.” message if none exist, and never errors
{{ scan_imports }} A table documenting each scanner import on this engagement (tool, filename, date, imported by, findings produced) Metadata only: the original uploaded scan file itself is never stored, only this record of the import. Shows a graceful “No scanner imports have been recorded for this engagement.” message if none exist

Finding sections inside {{ finding_details }}

Section titled “Finding sections inside {{ finding_details }}”

{{ finding_details }} doesn’t have its own separate tag list. It automatically includes every active ContentSectionDefinition (Finding Structure), in their configured order. A fresh instance starts with zero content sections; the table below is what seed_pentest_report_format creates as a starting point, and it’s fully editable afterward from Finding structure:

Order Slug Label Supports images Visible on client portal
5 risk_assessment Risk Assessment No Yes
10 description Description No Yes
20 impact Impact No Yes
30 steps_to_reproduce Steps to Reproduce Yes Yes
40 proof_of_concept Proof of Concept Yes Yes
50 affected_assets Affected URLs / Assets No Yes
60 recommendation Recommendation No Yes
70 references References No Yes

These are managed from the Finding structure admin screen, not the Document editor. Adding, reordering, or deactivating one changes what {{ finding_details }} includes for every profile, immediately.

Every deployment also always has an Affected Assets entry in this same ordered list (slug affects), wherever it’s currently positioned. See Affected Assets is a built-in, protected section. Unlike the sections above, it isn’t rich text and isn’t backed by FindingSection content: it renders the finding’s own Affects field as a plain list, and it can be repositioned/renamed but never deleted.

3. Custom text-block tags (author-defined prose)

Section titled “3. Custom text-block tags (author-defined prose)”

These are admin-authored rich-text blocks (ReportTextBlockDefinition), the way you add your own prose sections (executive summary, disclaimers, methodology, etc.) without touching code. Like structural tags, they only work as a standalone paragraph in the Document template.

A text block always belongs to exactly one Report Profile. There’s no shared/global text block that every profile automatically resolves. Its metadata (slug, label) lives on the ReportTextBlockDefinition row; its actual rich-text content lives in that profile’s own block_defaults[slug] (or a per-report override, set from the report’s Configure page). If a tag doesn’t match a structural tag or a text block on the current profile, it falls back to placeholder substitution (see How the systems differ); if that also finds nothing, the tag is left as literal text.

New text blocks are created from a profile’s own Text blocks tab. Whatever slug you give one becomes its tag name automatically. The “Default Penetration Test Report” profile (seeded by seed_pentest_report_format) ships with a worked example set:

Tag Label
{{ executive_summary }} Executive Summary
{{ risk_narrative }} Overall Risk Posture
{{ root_cause_analysis }} Root Cause Analysis
{{ effective_security_practices }} Effective Security Practices
{{ additional_recommendations }} Additional Recommendations
{{ rules_of_engagement }} Rules of Engagement
{{ out_of_scope }} Out-of-Scope Items
{{ emergency_contacts }} Emergency Contacts
{{ testing_methodology }} Testing Methodology
{{ cvss_scoring_methodology }} CVSS Scoring Methodology
{{ risk_rating_matrix }} Risk Rating Matrix
{{ tools_used }} Tools Used
{{ tester_credentials }} Tester Credentials
{{ glossary }} Glossary of Terms
{{ conclusion }} Conclusion
{{ confidentiality_disclaimer }} Confidentiality & Disclaimer

These slugs aren’t reserved or built-in. They’re just what that one profile happens to use. A different profile is free to use different slugs entirely.

A side-by-side summary of the three systems described above, for when you just need a quick comparison rather than the full explanation of each:

Placeholder tags Structural tags Custom text-block tags
Where usable Anywhere (Document body, text blocks, finding sections, observations, etc.) Only as a standalone paragraph in the Document template Only as a standalone paragraph in the Document template
Resolves to A plain string A pre-built section (table/chart/list) Rich text (headings, lists, links, etc.)
Unknown tag Printed literally, unchanged Falls through to a custom-tag lookup, then a placeholder lookup, then printed literally Falls through to a placeholder lookup, then printed literally
Recursive/nested? No, single substitution pass, not re-scanned No, resolved once per Document parse, never re-invoked on nested content No, same as structural tags

A minimal but complete Document template:

{{ cover_page }}
{{ table_of_contents }}
# Document Control
{{ document_control }}
# Executive Summary
{{ executive_summary }}
# Scope, Rules of Engagement & Contacts
## Rules of Engagement
{{ rules_of_engagement }}
## Out-of-Scope Items
{{ out_of_scope }}
## Emergency Contacts
{{ emergency_contacts }}
# Testing Methodology
{{ testing_methodology }}
## Testing Coverage (Checklist)
{{ checklist_coverage }}
# Assessment Team
{{ assessment_team }}
# Breakdown of Findings
{{ breakdown_of_findings }}
# Detailed Findings
{{ finding_details }}
# Appendix: Scanner Imports
{{ scan_imports }}
# Confidentiality & Disclaimer
{{ confidentiality_disclaimer }}

For a fuller worked example (executive summary, root cause analysis, effective security practices, additional recommendations, a conclusion, and every appendix), see the profile built by seed_pentest_report_format.

Within {{ executive_summary }}’s own authored content, you could write:

This assessment was performed for {{ client_name }} between {{ start_date }} and
{{ end_date }}, under reference {{ reference_number }}.

and client_name/start_date/end_date/reference_number will substitute correctly, per engagement, every time it is rendered.

  • DOCX template guide: the parallel tag system for an uploaded .docx Word template, which differs in syntax ({{p tag }} for rich content) and adds a finding loop.
  • Reports & exports: the end-to-end generation workflow this page’s tags plug into.