Documentation

RESPECT

How to turn a pentest report into checks replayed automatically, and get warned the moment a fix stops holding.

Concepts

RESPECT organises work around five objects. Understanding them is enough to use the product.

ObjectWhat it is
TenantAn organisation. Isolates everything else: two tenants never see each other's data.
ScopeAn assessment perimeter, usually one audit or one application. This is the unit you schedule and measure.
AssetA concrete target inside that perimeter: a host, an endpoint, a domain.
FindingA vulnerability from your pentest report. Carries a reference, a title, a severity and a state.
CheckThe reproducible test attached to a finding. It decides whether the fix still holds.

A validation run executes every check in a scope and updates each finding's state. Every state change is recorded as a transition.

RESPECT overview listing two scopes with their indicators
The overview gathers your scopes, each with its findings, regressions and posture score.

Finding lifecycle

A finding moves between four states depending on its check result. This is the heart of the product.

StateMeaning
presentThe vulnerability is open. Initial state on import.
remediatedThe check passed: the fix is verified.
regressedA previously fixed finding whose check fails again.
inconclusiveThe check could not run: unreachable target, network error. Temporary, draws no conclusion.
            check PASS                    check FAIL
present ──────────────► remediated ──────────────► regressed
   ▲                                                    │
   └──────────────────── check PASS ───────────────────┘

any state ── check ERROR ──► inconclusive
The transition that matters: remediated → regressed. It means a confirmed fix has stopped working. This is the one signal RESPECT produces that nobody else gives you: a scanner tells you a flaw exists, RESPECT tells you a flaw you believed settled has come back.

inconclusive never counts as a regression. A target under maintenance does not raise an alert.

Transition log showing moves from remediated to regressed and back
The audit trail keeps every state change with its reason and timestamp. Both directions are visible: a fix breaking, then the same one going back to green.

Getting started

The shortest path from a pentest report to your first automatic check is four steps.

  • Create a scope for the audit or application concerned.
  • Import your findings from a CSV, JSON or YAML file.
  • Attach a check to each finding you want watched. You do not have to cover them all: start with the critical ones.
  • Schedule the replay, then let it run.

The built-in check editor runs a check live against its target before you attach it, and shows the result assertion by assertion. Use it: a check never run by hand is a check that will alert for nothing.

Importing findings

Three formats are accepted: CSV, JSON and YAML. Whatever the format, three fields are mandatory.

FieldRequiredDetail
refyesYour internal reference, the one from the pentest report.
titleyesVulnerability name. A row without a title is rejected.
severityyescritical, high, medium, low or info.
descriptionnoFree text, typically the observation and the expected remediation.
asset_kindnoTarget nature, for example host or endpoint.
asset_valuenoThe target itself: hostname, URL, endpoint.
sourcenoWhere the finding came from. Useful to trace it back to an audit.
cwe, owaspnoFrameworks. Common column names from market tools are recognised.

A minimal CSV looks like this:

ref,title,severity,asset_kind,asset_value,cwe,owasp
PT-2026-014,SQL injection on /api/orders,critical,endpoint,POST /api/orders,CWE-89,A03
PT-2026-015,Missing HSTS header,low,host,www.example.com,CWE-319,A05

In JSON, the same thing reads:

{
  "source": "audit-2026-04",
  "findings": [
    {
      "ref": "PT-2026-014",
      "title": "SQL injection on /api/orders",
      "severity": "critical",
      "description": "order_id parameter concatenated into the query.",
      "asset": { "kind": "endpoint", "value": "POST /api/orders" }
    }
  ]
}
Two behaviours worth knowing. An unrecognised severity does not stop the import: the row is accepted as medium and a warning is raised. A CSV missing ref, title or severity, on the other hand, is rejected outright, before any processing.
Findings list with severities, states and last check dates
After import, every finding carries its severity, its state, its last check and its frameworks. Columns are filterable.

Writing a check

A check is described in YAML. It aims at a target, runs a request, then evaluates a list of assertions. The check passes if every assertion passes.

name: "SQL injection fixed on /api/orders"
type: http_probe
target: "https://app.example.com/api/orders?order_id=1'"
method: GET
severity: critical
assertions:
  - field: status_code
    operator: eq
    value: 400
  - field: body
    operator: not_contains
    value: "SQL syntax"
tags: [sqli, owasp-a03]

The reasoning is inverted compared to a scanner: you write what must be true once the flaw is fixed. Here, the application must reject the input and never leak an SQL error. The day either stops being true, the finding moves to regressed.

Check editor with a payload replay YAML and its execution result
The editor brings together the template library, the check YAML, the detection mode and the execution result. Always test live before attaching.

Two detection modes

The editor's DETECTION selector decides what your assertions describe. It is the most structural setting on a check, and the easiest one to get backwards.

ModeYour assertions describe…
Normalthe remediated state. The check passes when they hold. This is the default, and the mode used in the example above.
Signaturethe vulnerable pattern. The check passes when they no longer hold. Handy when the flaw is easier to describe than its fix.
Pick the mode before writing the assertions. The same assertions in the other mode produce the exact opposite result: a fix that holds gets reported as a regression, and an open flaw as remediated.

Available operators

FamilyOperators
Equalityeq, neq, in, not_in
Textcontains, not_contains
Regular expressionmatches, matches_regex, not_matches_regex
Comparisongt, lt, gte, lte
Presenceexists, not_exists
URLeq_url, neq_url - compare URLs while ignoring insignificant differences

Several checks can be chained in one document by separating them with ---.

Good practice

  • Do not follow redirects without a reason. follow_redirects defaults to false on purpose: turn it on and a status_code eq 301 assertion will never see the 301, hidden by the follow.
  • Prefer in over eq for status codes. A 401 and a 403 both mean "not allowed". Testing in [401, 403] avoids a false regression the day the application changes its code.
  • Always pair it with a body assertion. A 200 proves nothing if the page still returns the error trace. Add a body not_contains on the revealing string.
  • For a decommissioned target use expect_unreachable: true rather than letting the check error out. Without it, removing the DNS record produces repeated inconclusive results instead of a clean pass.
  • Keep the timeout between 5 and 15 seconds. Beyond that the check ties up the scheduler without learning anything more.
  • Five to seven assertions per check, no more. Past that, split them: when the check fails you want to know which of the two problems came back.
  • Do not forget authentication. On a protected endpoint, a check with no auth profile returns 401 forever - a pass or a fail that means nothing.
Two classic mix-ups. contains looks for a literal substring, matches_regex interprets a regular expression: contains: "v1.0" does not behave like matches_regex: "v\d+". And while HTTP headers are case-insensitive on the wire, the header.Content-Type field is case-sensitive in configuration: write the canonical form.

When a check fails for no obvious reason

  • Replay it live from the editor and read the result assertion by assertion: the detail says which one failed.
  • An empty observed value means the target did not answer. That is a case for expect_unreachable, not for a looser assertion.
  • A rejected regular expression was refused by the anti-ReDoS guard. A pattern like (a+)+ is turned down: simplify it.
  • A result in error rather than pass or fail comes from transport - timeout, TLS, DNS - not from your assertions.

Check types

The five types below cover the vast majority of remediations in an application pentest report.

TypeWhat it does
http_probeSends an HTTP request, then tests the status code, the body and the headers.
dns_resolveResolves a name and checks that it points somewhere, or precisely that it no longer does.
tls_inspectOpens a TLS session and checks the negotiated protocol. Useful to confirm a weak version really was disabled.
port_scanAttempts a TCP connection and checks whether a port is open or closed.
header_checkChecks the presence, absence or value of a security header.

The engine exposes more specialised ones, notably cert_expiry, ssh_audit, spf_check, dmarc_check, dkim_check, cors_check, jwt_probe, smtp_check, ldap_check, snmp_check and http_chain for multi-request scenarios.

Payload replay

The attack_replay type does not test one request but a whole payload set. You name a payload_set and the field to inject it into, and the engine replays them all.

name: "Reflected XSS fixed on /?name="
type: attack_replay
target: "https://demo.example.com/?name={{payload}}&r=greet"
method: "get"
timeout: 10
payload_set: "xss_reflected_basic"
injection_field: "url"

The result is global: 12 of 12 payloads blocked is a pass, a single one getting through is a fail. This is the right tool when the remediation is a filter - output encoding, a web application firewall, input validation - rather than a one-off fix.

Ready-made templates

The editor ships a library of 91 templates grouped by family: web vulnerabilities, payload replay, out-of-band callbacks for blind flaws, misconfiguration, information disclosure, TLS and crypto, network, security headers, auth and session, FTP, SSH, certificates, email security, CORS, infrastructure, brute force and rate limiting, multi-context IDOR and BOLA, JWT mutations, false-positive guards, posture attestation. A dedicated entry filters them by OWASP Top 10 category.

The vocabulary changes per screen. The editor says NOT VULNERABLE or VULNERABLE because it reasons about the target; the run history counts PASS, FAIL and ERR because it reasons about the check. NOT VULNERABLE and PASS mean the same thing, as do VULNERABLE and FAIL.

Scheduling

Scheduling is set per scope, not per finding: every check in a perimeter is replayed together, which gives a coherent picture at a given date. A scope can be paused and resumed without losing its history.

Pick the frequency from how often the watched application ships, not from finding severity. An application released every week deserves a daily replay: it is deployment that breaks fixes, not the passage of time.

A run can also be triggered by hand with Run now, without touching the schedule. Useful right after a deployment whose effect you want to check immediately rather than waiting for the next pass.

Reports and coverage

Every scope produces a PDF report covering the posture, the findings and their state. That is the deliverable to attach to a security committee pack or send back to an audit client.

The dashboard also shows framework coverage: your findings are mapped to OWASP Top 10 categories, with a score per category and a count of the ones mapped to nothing. Those are worth a look - an unmapped finding is often a finding poorly described at import time.

Alerts

A transition to regressed raises an alert by email and by webhook. The webhook lets you route the information to your team chat, your SIEM or your ticketing tool.

Only regressions alert. A finding that stays open produces no daily noise, and an inconclusive check does not alert either.

Posture score

The score summarises a scope's exposure on a 0 to 100 scale, weighted by severity.

score = 100 × (1 − open_exposure / total_exposure)
SeverityWeight
critical10
high6
medium3
low1
info0.2

All findings remediated gives a score of 100. The weighting means one open critical costs as much as ten low findings: the score cannot be inflated by fixing trivia.

Posture dashboard with OWASP radar and severity breakdown
A scope dashboard: posture score, 30-day trend, OWASP Top 10 coverage and severity breakdown.

Roles

RoleReach
client_adminAdministers their organisation: scopes, findings, checks, users.
check_creatorWrites and edits checks, without touching administration.
analystReads findings, runs and posture. No modification.
mssp_adminService provider managing several client organisations.

A question this page does not cover?

The documentation follows the product, which moves fast. If something is missing or looks wrong, say so: it is the fastest way to get it fixed.

Write to us