Skip to content

v1.15.1 — PIV/CAC sign-in fix (supersedes unsigned v1.15.0)

Choose a tag to compare

@clem-field clem-field released this 27 Jul 15:32
v1.15.1
98fed79

Patch release fixing PIV/CAC sign-in, which was impossible in v1.15.0, and re-establishing a signed release image.

Upgrade note. v1.15.0's image published successfully but its signing job never ran — the build job failed on a GitHub Actions cache-export error after the image had already been pushed, which skipped sign-verify-attest. v1.15.0 is therefore unsigned and is superseded by this release. Deployments verifying signatures should move to v1.15.1.

Fixed

PIV/CAC sign-in failed for every user (#824)

A user selected their smart-card certificate, entered the card PIN, and was told "No smart card certificate was presented" — while the gateway was forwarding the certificate and attesting verify=SUCCESS. Firefox, Chrome and Edge behaved identically, because the fault was server-side.

Three defects, two of which independently broke sign-in.

The certificate arrived but could not be parsed. HTTP headers cannot carry newlines and a PEM is defined by them, so every gateway works around it differently:

Gateway What arrives
nginx $ssl_client_escaped_cert, ALB X-Amzn-Mtls-Clientcert URL-encoded (%0A)
nginx $ssl_client_cert newlines folded to spaces or tabs
assorted literal backslash-n written into the value
assorted bare base64 DER with no BEGIN/END markers

SPARC handled exactly one of these — it URL-decoded when it saw a percent sign. Every other shape reached OpenSSL as mangled text and was rejected. SPARC now reassembles all four before parsing, so no additional gateway configuration is required. Reassembly remains fail-closed: anything that is not a decodable certificate is still refused.

The failure message was misleading. A missing certificate and an unreadable one produced the same message, so the audit log reported "no certificate presented" while the gateway simultaneously reported successful verification — a contradiction that points diagnosis at the wrong subsystem. The two are now distinct:

Message Meaning
Your smart card could not be verified by the gateway. Verify header missing or not SUCCESS
No smart card certificate was presented. Verify succeeded but the certificate header was empty
Your smart card certificate could not be read. A certificate arrived but could not be decoded

Every PIV failure now records shape-only diagnostics — byte count, whether PEM markers were present, whether the value was URL-encoded, whether reassembly succeeded — so the next occurrence is diagnosable from the audit log without a redeploy. The certificate itself is never recorded, in whole or in part.

The consent banner did not persist. It re-fired on every login-page load, interposing between the certificate-bearing request and /auth/piv. Acceptance is now remembered for the browser session. Session scope is deliberate: AC-8 requires the notice before access is granted, so acceptance is not made permanent — clearing the browser session brings the notice back.

Documentation

  • Authentication and MFA (wiki) — the forwarded-certificate formats SPARC accepts, and a troubleshooting table mapping each smart-card failure message to where to look.

Compliance

  • Authentication component definition 1.1.0 → 1.2.0, and the NIST SP 800-53 Rev 5 mapping, updated for IA-2 / IA-2(12) to cover forwarded-certificate reassembly and the distinct auditing of absent versus undecodable certificates.

Verification

  • Full RSpec suite: 3376 examples, 0 failures, 24 pending (environment-gated).
  • Seven parser tests, one per gateway mangling, plus request-level tests signing in through the real request path with space-folded, URL-encoded and marker-less certificates.
  • Mutation-tested: with certificate reassembly disabled, all seven mangling tests fail while the well-formed control and every negative case still pass.
  • Browser tests for consent persistence pass against this build and fail against v1.15.0.

Full changelog: v1.15.0...v1.15.1