Skip to content
downpipes docs

The security-centre posture score and control checks

This page is a reference for the posture score the security centre shows: how the number is computed, what each control check looks at, and which checks are graded against which are informational. It is written for an auditor reading the score and for an operator deciding what to fix first.

The posture is a pure computation over your account’s own observable state. The engine gathers presence booleans, per-downpipe recency, expiry states, identity counts and a few flags, then runs a fixed function with no input or output of its own; the console renders the result. The vendor reads nothing, and every check carries only redaction-safe metadata: an id, a title, a severity, a status, the automatic outcome, the named control it maps to, what was observed, how the determination is made, and how to fix it. No check can carry a key, a value or a fingerprint.

How often it updates

The report is recomputed live on every read: opening the security centre, pressing its refresh, or generating a posture report or evidence pack always evaluates every check against the state at that moment; nothing is cached. The console also refreshes the open screen about every thirty seconds while it is visible (pausable with the auto-refresh control). The engine runs a scheduled evaluation about every six hours, so a previously-good check that regresses fires its posture-regression notification even when no one has the screen open. There is no state a stale read could show you; the only latency is the gap since the last computation.

How the score works

The score is a weighted pass fraction, rendered as a 0 to 100 integer. Each check has a fixed severity, and each severity carries a weight. The score is the sum of the weights of the checks that count as passing, divided by the total weight of all checks, multiplied by 100 and rounded. A critical check therefore moves the number far more than a low one.

SeverityWeight
Critical5
High3
Medium2
Low1

Every check first computes an automatic outcome: pass, fail, or cannot-verify. Cannot-verify applies to controls the engine cannot observe (media diversity for cloud-only storage, MFA enforced inside your IdP or your Cloudflare Access policy), so the platform records neither a pass nor a fail for them and does not show them as red failures you have no automatic way to clear. A cannot-verify check with no owner grading reads as “needs attestation” (amber), and it does not earn its weight until you grade it.

On top of the automatic outcome sits the Owner’s grading, called an override. The effective status is one of:

StatusMeaningScore effect
passThe platform observed the control satisfiedEarns its weight
failThe platform observed it not satisfied, and no override is recordedDoes not earn
unattestedThe platform cannot verify it and no attestation is recorded yetDoes not earn
attested-passAn Owner attested it IS satisfied, with the reason recordedEarns its weight
compensating-controlAn Owner recorded a compensating control satisfying the intentEarns its weight
not-applicableAn Owner determined it does not applyExcluded from both sides of the score
risk-acceptedAn Owner deliberately accepted the riskEarns its weight, listed as an accepted risk
resolved-alternativeReserved for a platform-observed alternative; the engine does not emit itEarns its weight

Every override requires a reason, records the Owner’s identity and time, queues for a second approver when the four-eyes gate is on, and is written to the audit log as a posture-override-set event naming the check and the kind; the reason itself lives on the record and flows into the posture report and evidence packs, never into the audit chain. An override also needs a recent strong factor, in both the accept and the withdraw direction: a session that signed in within the last five minutes carries it already, and an older one is asked for a fresh passkey assertion first. It does not take a change number, and the distinction matters on this page in particular: an override is a config mutation, so the four-eyes gate covers it and the Require Change Number policy does not, even though this page’s own emergency-change-review check watches that policy. See what each policy covers. An override on a check whose automatic outcome later recovers to pass goes dormant: the check reads pass, the recorded determination stays attached and visible, and you can withdraw it.

A customer grading is stated as a customer grading

An attested pass or a compensating control reads as a pass in the console and the signed reports, always labelled as your determination with your reason, never as a platform verification. A risk acceptance is the opposite discipline: it counts as pass for the score so the number reflects a deliberate decision, but it is always stated as an accepted risk, never dressed up as a pass. Marking a check not applicable removes it from the score entirely, in both the numerator and the denominator, which is the standard compliance treatment for a control that does not apply.

The checks are sorted most severe first, and within a severity the needs-attention checks (failing or awaiting attestation) sort before the graded and passing ones, so the worst open item is always at the top of the security centre.

The Posture score card at the top of the console's Security centre, headed 67 out of 100 and toned needs work. Four tiles sit beneath it: Score, reading 67 out of 100 with the note that it is a weighted pass fraction over the applicable checks, critical weighted highest, with an N/A excluded entirely; Needs attention, reading 7 for review, of which 5 are failing and 2 await your attestation, ranked below; Marked by you, reading 0 with no overrides or attestations recorded; and Passing, reading 13 checks the platform verified on its own.

The twenty-seven checks

There are twenty-seven named checks, one per stable id, and each maps to a named control standard. The set is fixed in the code, so the list does not vary by account; what varies is each check’s status. Several are conditional: recovery-codes-low appears only for a signed-in identity with a recovery-code set, dest-cred-encryption only when there is a stored destination credential (or a wrap key) to grade, emergency-change-review only when the Require Change Number policy is on, attended-verification-cadence only on an offline-key-only estate that has stated an interval, and the two update checks only once an engine update has settled through the signed channel. Every check also states, in plain language on its card, how its determination is made. The table gives the id, what it looks at, its severity and the control it maps to.

CheckWhat it observesSeverityMaps to
restore-test-recencyWhether every downpipe has a recent successful restore testCriticalCIS 11.5, NIST CSF PR.DS-11
seal-verificationWhether the latest run’s archive read back and verified at sealCriticalRecoverability
destination-configuredWhether an archive destination exists, so backups have somewhere to landCriticalRedundancy
access-enforcedWhether any shared-token admin path is still live, so an admin action could be unattributableHighProduct no-custody
admin-strong-authWhether admin sign-in is verifiably phishing-resistant MFA (all admins on passkeys), or needs your attestation (MFA at your IdP or in Cloudflare Access is not observable)HighEssential Eight MFA, NIST SP 800-63B
dispose-bootstrap-tokenWhether the one-time break-glass bootstrap token has been disposed once it is safe toHighSecurity
restore-test-enabledWhether scheduled restore tests are switched on for each downpipeHighCIS 11.5
redundant-copiesWhether each source fans out to two or more destinationsHigh3-2-1
break-glass-presentWhether a break-glass recipient is configured for offline recoveryHighDR continuity
credential-expiryWhether any tracked credential or key is expiring or expiredHighNIST SP 800-57
recovery-codes-lowWhether your own recovery-code set is running lowMediumSecurity
two-ownersWhether at least two Owners exist, for continuityMediumAvailability
failure-alertsWhether a notification rule alerts on backup failureMediumOperational
media-diversityWhether the operator has attested their destinations meet a media-diversity policyMedium3-2-1
operational-private-weakeningWhether an in-account read-back key is present, a deliberate weakening of strict no-custodyMediumNo-custody
immutabilityThe real store-enforced WORM status from the live capability probeMediumISO A.8.13
dest-cred-encryptionWhether console-set destination credentials are envelope-encrypted at rest, rather than on the platform-encryption-only plaintext floorMediumISO A.8.24
emergency-change-reviewWhen change numbers are required: whether any recorded emergency change awaits its retrospective reviewMediumITIL Change Management, ISO 27001 A.8.32
audit-export-availableThat a tamper-evident audit log is retained and exportableLowISO A.8.15
beacon-offThat the vendor beacon is off, so the engine does not phone homeLowNo-custody
encryption-pq-hybridThat archives are sealed and signed with a post-quantum hybrid schemeLowISO A.8.13
environment-self-backupWhether downpipes backs up its own control plane, so the configuration survives losing the engineHighISO A.8.13
attended-verification-cadenceOn an offline-key-only estate that has stated an interval: whether every downpipe with a completed run has a full attended verification inside itMediumISO A.8.13, NIST SP 800-34
update-version-driftWhether the engine is running a version the signed update channel still recommendsMediumSLSA v1, NIST SSDF PS.3
update-apply-provenanceWhether the most recent applied engine update left durable content-hash evidenceLowSLSA v1, NIST SSDF PS.3
recipient-set-expectedWhether the recipient set the engine seals archives to still matches the set recorded in the last signed control-plane exportHighNo-custody
off-account-audit-mirrorWhether an outbound audit-log push destination is configured, draining, and its most recent delivery succeeded, so a copy of the audit trail sits with a holder outside this Cloudflare accountMediumISO 27001 A.8.15

That is twenty-seven checks: three critical, nine high, eleven medium and four low.

The critical recoverability checks

Three checks are critical, and together they are the load-bearing recoverability signals. A failure in any of them weighs heaviest on the score, by design, because each one is the difference between a backup that exists and a backup you can actually recover.

restore-test-recency is the headline. It fails critical when any downpipe that has completed at least one run has had no successful restore test within 180 days. “Successful” means the last test outcome was a pass within the window; a downpipe with archives that has never been tested, or whose last test failed, counts as failing. A downpipe that has never completed a run is named in the detail but not failed, because there is no archive to test yet; a brand-new downpipe must not open as a critical failure it cannot clear until its first run. There is a warning band between 90 and 180 days: a downpipe with a successful test older than 90 but not yet 180 days does not fail the critical check, but the detail line flags it as high so it does not silently age into a failure. The check names the worst offender by its downpipe name, which is your own redaction-safe configuration.

seal-verification is the at-seal companion to recency. After a run, the engine can read the just-written archive back from the destination and verify it. This check fails critical when a downpipe’s most recent verify-at-seal verdict was suspect, meaning the archive that landed could not be verified. The run still completed and the archive was not deleted, because the behaviour is fail-open and it alerts rather than destroying data, but a suspect verdict means you should confirm recoverability with a drill or a restore before trusting that copy. A downpipe that has never run with the feature on does not fail, because there is no suspect verdict to surface. From engine 0.3.6 the check also fails when the VERIFY_AT_SEAL override switches verify-at-seal off.

destination-configured fails critical when no archive destination is configured at all, because backups then have nowhere to land. It proves only that a second copy exists off-source, so it is described as the second-copy check and never as 3-2-1; that distinction is set out below.

The identity checks

access-enforced is a high-severity check, and it is account-level: it fails while a shared-token admin path is effectively live, that is, an ADMIN_TOKEN is configured and has been neither env-disabled nor retired in-app. When that path is dead, every remaining sign-in route (Cloudflare Access, passkeys, native OIDC or SAML SSO, recovery codes) resolves to a verified, attributable identity, and the check passes. It deliberately does not read how the current viewer signed in: a per-caller signal would make the same account score differently depending on who looked, and would unfairly fail a tenant whose admins sign in with passkeys or native SSO rather than Cloudflare Access. The determination is identical for every reader and for the scheduled evaluation.

A live shared-token path is a finding, not a setting to leave in place

A bare shared-token fallback means anyone holding the string can act, and nothing the engine records can attribute that action to a named person. The posture check treats this as a high-severity finding for that reason. Retiring the token (in-app, or by env-disabling or deleting the secret) is the intended end state; the related dispose-bootstrap-token check separately prompts you to do so once a durable way back in is in place. If you deliberately keep the token as a sealed break-glass behind Cloudflare Access, record that as an override on the check, with your reasoning.

admin-strong-auth asks whether admin sign-in is phishing-resistant MFA. It auto-passes only in the state it can observe end to end: every Owner and access-admin identity has an enrolled passkey, no IdP connection is enabled, and no shared-token path is live. In every other state it reads “needs attestation” rather than failing, because MFA may well be enforced somewhere the engine cannot see: your IdP’s conditional-access policy, or your Cloudflare Access policy. If that is your setup, attest it (an attested-pass override naming the policy), and the check reads as a pass attributed to your attestation in the console and every report.

Informational checks that always pass

Two checks are informational and always pass. They state a posture rather than grade an outcome, so they must not be read as graded results that happen to be green.

audit-export-available states that a tamper-evident, signed audit log is retained and can be exported. It is a low-severity informational pass that records the posture; there is no failing condition for it.

encryption-pq-hybrid states that archives are sealed with post-quantum hybrid encryption and signed with a post-quantum hybrid signature, and that this makes them tamper-evident. It too is a low-severity informational pass with no failing condition. The encryption is post-quantum hybrid, and the property is tamper-evident: an alteration is detectable, not impossible.

These differ from the immutability check, which is medium severity and graded against a live probe. It grades to three states, only one of which fails, but two axes decide which of the three you are in: whether the bucket enforces Object-Lock, and whether anything actually applies a retention window to the archives written there. That is why a bucket with Object-Lock on can still be an informational pass, not the strong claim, and why an invalid policy fails even there. All of it, with the per-reading table, is on immutability and attestation.

The 3-2-1 distinctions

The three relevant checks measure different things and are deliberately labelled differently.

destination-configured proves only the second copy: a live source plus one archive off-source. One destination is not 3-2-1, and the check is never labelled as such, because claiming 3-2-1 from a single destination would overstate the posture.

redundant-copies is the verifiable leg of 3-2-1. It checks that each protected source fans out to at least two distinct destinations, so a backed-up source exists in two places, which with the live source is three copies. The platform can verify this from each downpipe’s configured destination count, so it is graded as a real outcome.

media-diversity is the operator-attested leg. downpipes is cloud-only object storage, so it cannot verify the “two different media” criterion for you: two buckets, or a bucket plus an external S3, are the same media class as far as the platform can tell. Once a source fans out the check reads “needs attestation” (never a red failure), and an Owner attests it with an attested-pass override: a statement that their destinations meet their own media-diversity policy, recorded with the reason. It is a deliberate operator statement, never a platform claim that the media are diverse.

The Destinations screen’s own note: no leg off-account with immutability

One combination sits outside the three checks above and is not one of the twenty-seven scored controls: every configured destination is inside this Cloudflare account. Cloudflare R2 offers no Object Lock, versioning, legal hold or MFA-delete, and an in-account bucket shares this account’s own credential and blast radius with the sources it protects, so an account compromise can reach every copy. Redundant copies and an attested media-diversity leg do not close that gap on their own, because none of it requires a copy the account compromise cannot also reach.

The Destinations screen carries a calm, non-dismissible warning-tone note for this state, computed client-side from the destinations you have configured rather than from a posture report: it fires whenever no destination is both off-account (not R2) and Object-Lock enforced on the live probe with a retention window, and clears once one is. It is a finding, not a failure: an estate holding only R2 is still working and still backed up, and the note names the one gap rather than turning an otherwise-healthy state red. R2 remains a valid destination and a good secondary leg; the preferred primary leg is an off-account, Object-Lock-capable store (S3 with Object Lock, Google Cloud Storage with per-object retention, or Azure Blob with version-level immutability). Out-of-region latency and egress cost are a separate note the console shows where it applies; they are not read as a risk finding.

A retention window comes from an immutability mode on the destination, or from the bucket’s own default retention rule. Object Lock on a bucket retains nothing by itself. The note clears when at least one off-account destination has Object Lock enforced and a mode or a bucket rule. From console 0.2.7 with engine 0.3.6, a bucket with Object Lock on and no mode or rule does not clear the note. Its Immutability cell reads “Object-Lock on, nothing retained”.

The cell reads “Object-Lock, rule not checked” when the engine has no record of the rule. This occurs for a destination saved before engine 0.3.6, and for a destination reconciled from a control-plane export of such a record. On engine 0.3.6 or later, save the destination again with Replace. The engine then records if the bucket has a rule. If the bucket has no rule, the note stays after Replace.

An Azure Blob container is different. Its default retention policies are on the Azure management plane, and a storage-account key or a SAS cannot read them. The cell reads “Object-Lock, rule not readable”, and Replace does not change it. To clear the note with an Azure destination, set an immutability mode on it.

Where this fits

The posture report can be generated as a signed artefact; that path, and how to verify it yourself, is on signed reports. Several checks point at the immutability probe, the canary and the audit log, which have their own pages at immutability and attestation, the integrity canary and the audit log. To act on a finding you cannot or will not fix immediately, or to grade a control the platform cannot verify, an Owner uses the override flow (attested pass, compensating control, not applicable, or accepted risk), described on overrides and regression alerts.

Last updated .