Security Posture Engine
Security Posture Engine
Section titled “Security Posture Engine”Xferity includes a built-in security posture engine that continuously monitors the security state of your deployment. It evaluates your certificate lifecycle, cryptographic key status, transport security configuration, authentication settings, and flow-level security configuration — and surfaces findings in a structured, queryable report.
The posture engine is read-only. It never modifies configuration or state. It produces a PostureReport that is consumed by the web UI dashboard, the REST API, and stored as periodic snapshots for trend analysis.
What it evaluates
Section titled “What it evaluates”Xferity evaluates security posture across six domains:
| Domain | What it checks |
|---|---|
crypto | PGP key validity, key capability mismatches, missing keys for partner roles |
lifecycle | Certificate and PGP key expiry warnings (30-day threshold by default) |
transport | TLS verification, host key pinning, AS2 certificate bindings |
auth | Authentication configuration security |
secrets | Secret management configuration |
flow | Flow-level security configuration |
Reading a posture report
Section titled “Reading a posture report”The posture API returns a PostureReport object:
{ "checks": [ { "domain": "transport", "scope": "partner", "severity": "warning", "code": "sftp_host_key_not_pinned", "message": "SFTP partner \"vendor-a\" does not pin the server host key (no fingerprint or known_hosts configured).", "suggestion": "Set host_key_fingerprint (SHA256:...) or known_hosts to pin the expected host key and prevent MITM attacks.", "partner_id": "vendor-a", "last_evaluated_at": "2026-03-16T22:00:00Z" }, { "domain": "lifecycle", "scope": "asset", "severity": "warning", "code": "certificate_expiring_soon", "message": "Certificate \"as2-signing-cert\" expires in 12 day(s).", "suggestion": "Plan to replace this certificate within 12 day(s) and update partner bindings.", "asset_type": "certificate", "asset_id": "cert-abc123", "asset_name": "as2-signing-cert", "last_evaluated_at": "2026-03-16T22:00:00Z" } ], "total_errors": 0, "total_warnings": 2, "total_info": 0, "total_suppressed": 0, "healthy": true, "evaluated_at": "2026-03-16T22:00:00Z"}Report fields
Section titled “Report fields”| Field | Description |
|---|---|
checks | Array of all findings, including suppressed ones |
total_errors | Count of active (non-suppressed) error findings |
total_warnings | Count of active warning findings |
total_info | Count of info findings |
total_suppressed | Count of suppressed findings |
healthy | true when total_errors == 0 (no active errors) |
evaluation_incomplete | true if a check category failed evaluation |
Finding fields
Section titled “Finding fields”Each CheckResult contains:
| Field | Description |
|---|---|
domain | Security domain: crypto, lifecycle, transport, auth, secrets, flow |
scope | Breadth: platform, partner, flow, asset |
severity | error, warning, or info |
code | Machine-readable identifier (see finding reference below) |
message | Human-readable description of the finding |
suggestion | Actionable remediation step |
partner_id | Populated for partner-scoped findings |
flow_name | Populated for flow-scoped findings |
asset_type | e.g. certificate, pgp_key |
asset_id | Database identifier of the asset |
is_suppressed | Whether this finding is suppressed |
suppression_note | Note explaining the suppression |
Accessing the posture report
Section titled “Accessing the posture report”GET /api/security/posture # Full platform postureGET /api/security/posture?partner=vendor-a # Scoped to one partnerGET /api/security/posture?flow=payroll-upload # Scoped to one flowAll API endpoints require authentication (Bearer token or OIDC session).
Web UI
Section titled “Web UI”The security posture dashboard is accessible from the main navigation. It shows:
- Overall health status (
healthy/unhealthy) - Active errors and warnings by domain
- Per-partner and per-asset findings
- Suppressed findings with notes
Finding reference
Section titled “Finding reference”Transport domain (transport)
Section titled “Transport domain (transport)”| Code | Severity | Description |
|---|---|---|
sftp_insecure_host_key_global | warning (error in hardened mode) | Global security.allow_insecure_host_key: true — SSH host key verification is bypassed for all SFTP connections |
sftp_insecure_host_key | warning (error in hardened mode) | SFTP partner has allow_insecure_host_key: true |
sftp_host_key_not_pinned | warning | Host key checking is enabled but no fingerprint or known_hosts is configured |
ftps_tls_skip_verify | warning (error in hardened mode) | FTPS partner has tls.insecure_skip_verify: true |
as2_tls_skip_verify | warning (error in hardened mode) | AS2 partner has https_tls.insecure_skip_verify: true |
as2_async_mdn_unsupported | error | AS2 partner configured with receipt_mode: async, which is not supported |
as2_missing_cert_binding | warning | AS2 partner is missing a required certificate role binding (as2_signing or as2_encryption) |
Crypto domain (crypto)
Section titled “Crypto domain (crypto)”| Code | Severity | Description |
|---|---|---|
pgp_key_expired | error | A PGP key bound to a partner role has expired |
pgp_key_revoked | error | A PGP key is revoked |
pgp_key_inactive | error | A PGP key is marked inactive |
pgp_key_passphrase_missing | error | A private key requires a passphrase but none is configured |
pgp_key_capability_mismatch | error | A key lacks the required capability (encrypt/sign) for the role it is bound to |
missing_encrypt_key | error | No encryption key is bound to a partner role that requires encryption |
missing_decrypt_key | error | No decryption key is bound to a partner role that requires decryption |
Lifecycle domain (lifecycle)
Section titled “Lifecycle domain (lifecycle)”| Code | Severity | Description |
|---|---|---|
pgp_key_expiring_soon | warning | A PGP key expires within 30 days |
pgp_key_expired | error | A PGP key (not bound to any partner) has expired |
certificate_expiring_soon | warning | An X.509 certificate expires within 30 days |
certificate_expired | error | An X.509 certificate has expired |
Hardened mode and posture
Section titled “Hardened mode and posture”When security.hardened_mode: true is set, the posture engine escalates the severity of several transport findings from warning to error. This means:
- Any SFTP partner with
allow_insecure_host_key: truecauseshealthy: false - Any FTPS partner with
tls.insecure_skip_verify: truecauseshealthy: false - Any AS2 partner with
https_tls.insecure_skip_verify: truecauseshealthy: false - The global
security.allow_insecure_host_key: truecauseshealthy: false
This enforces a hard posture requirement in hardened deployments: no insecure transport configurations are permitted.
Posture snapshots
Section titled “Posture snapshots”Xferity stores periodic posture snapshots in the PostgreSQL database. This enables:
- Historical trend analysis: “was the platform healthy last week?”
- Audit evidence: demonstrate continuous posture monitoring
- Regression alerts: detect when posture degresses after a configuration change
Snapshot retention is configurable:
security: posture_snapshot_retention_days: 90 # default; set -1 to disable pruningSuppressing findings
Section titled “Suppressing findings”If a finding represents a known-acceptable configuration (for example, an SFTP server in a controlled network where host key pinning is not practical), you can suppress it with a documented note.
Suppressed findings:
- Remain visible in the
checksarray for full audit visibility - Are excluded from
total_errors,total_warnings, and thehealthyflag - Are flagged with
is_suppressed: trueand thesuppression_noteexplaining the decision
Suppressions are managed through the web UI (Security → Posture → Suppressions) or via the API.
Each suppression record includes:
- Finding code being suppressed
- Partner or asset scope
- The operator’s justification note
- Optional expiry date
Evaluation completeness
Section titled “Evaluation completeness”If any check category fails to evaluate (for example, the database is unavailable when the certificate check runs), the report sets:
{ "evaluation_incomplete": true, "evaluation_errors": ["certificate lifecycle check failed: database unavailable"]}The report is still valid for the categories that did evaluate. Operators and monitoring systems should surface evaluation_incomplete: true as an alert.
Integration example
Section titled “Integration example”Poll the posture API from your monitoring system:
curl -s -H "Authorization: Bearer $XFERITY_TOKEN" \ https://xferity.internal/api/security/posture | jq '.healthy'Alert when healthy == false or evaluation_incomplete == true.