Commit 255e3ad
committed
fix+chore: audit triage (dev-review + SOX/SOC2 compliance pass)
Combined triage of two parallel audit reports on the PR-#2 change set since
commit 6a2db50. Both ran against the live codebase, not just the diff.
== ca-rest-plugin-dev (technical review) ==
Blocker B1 — ExtractSerialFromPem hex format parity:
BouncyCastle BigInteger.ToString(16) drops the leading-zero nibble in the
most-significant byte, producing "A123456" where X509Certificate2.SerialNumber
returns "0A123456". That mismatch breaks audit-log correlation against the
serial Keyfactor Command stores at issue time. Switched to
Convert.ToHexString(cert.SerialNumber.ToByteArrayUnsigned()) which preserves
every byte exactly. New ExtractSerialFromPemTests pins five cases including
the leading-zero-byte regression.
Blocker B2 — cached-DCV path missing OrderStatusId terminal guard:
PerformDcvIfNeededAsync's new "return true on Status=1" cached-DCV path
could fire on a cancelled or rejected order whose domainVerification.Status
was carried over from a prior validated round — sending the caller into a
wasted DcvWaitForIssuanceSeconds-long GetCertificate poll. Added the same
OrderStatusId "4"/"5" check that WaitForDcvVerificationAsync uses, ahead of
the AlreadyValidated branch. New Dcv_Skipped_WhenOrderStatusIdIsTerminal
Theory pins both states.
Should-fix S1: _domainValidatorFactory marked `volatile` so cross-thread
SetDomainValidatorFactory writes are immediately visible to Enroll/Sync.
Should-fix S2: README compatibility note rewritten — `SetDomainValidatorFactory`
is the gateway host's integration point, not something operators call.
Should-fix S3: footer "Production codes 838–847" note replaced with a
pointer to the per-product sandbox/production table above; the range
notation was confusing because some codes (e.g. 842) appear in both
columns for different products.
Nit N1: clarifying comment on Times.Exactly(1) expectation in the
single-shot test.
Nit N2: SetDomainValidatorFactory_SecondCall_OverridesFirst converted from
reflection-on-field to a behavioural test driving Enroll and asserting
which factory's validator was actually used.
== compliance-auditor (SOX / SOC1 / SOC2) ==
Critical C1: WaitForDcvVerificationAsync gained a defense-in-depth absolute
deadline so a future caller passing CancellationToken.None can't make
the loop unbounded (SOX CC7.3).
Critical C3 (verify-and-document): added an explicit comment at the OAuth2
token-acquisition site forbidding logging of tokenResp.Content / .ErrorMessage
/ .ErrorException — RestSharp echoes the original request body on failure,
which contains the client_secret (SOX CC6.1).
Material M1: SetDomainValidatorFactory now logs every call (offered type +
whether the cast succeeded) so an auditor can confirm which DNS provider
drove DCV (SOX change-management).
Material M2: ValidateCAConnectionInfo and ValidateProductInfo blank out
ApiKey/OAuthClientSecret/Password on the transient tempConfig after the
validate call so they aren't reachable from the still-rooted tempClient
instance (SOC2 CC6.1 best-effort).
Material M3: Synchronize gained an error-rate threshold — aborts and throws
when error rate exceeds 25% over a sample of ≥50 records, so a CA-side
outage cannot silently 'complete' a sync with zero useful records (SOC1
completeness/accuracy).
Material M4: Revoke log line now includes ManagedThreadId for correlation
against any RequestingUser scope the gateway host enriches (SOX
segregation-of-duties evidence).
Material M5: RenewOrReissueAsync logs the PriorCertSN probe at Information
(SOC2 CC6.1 logical-access event).
Material M6: BuildDefaultAgreementDetails logs a Warning when SignerIp
falls back to 127.0.0.1 — submitting that to a public CA is a
misrepresentation in the legal audit record (SOC1 accuracy-of-processing).
Material M7: ExtractErrorMessage caps the response-body size at 64 KB
before JsonDocument.Parse to prevent memory-exhaustion DoS via a hostile
CA response (SOC2 CC7.2).
Advisory A1: GenerateTxnId switched from Random.Shared.NextDouble to
Org.BouncyCastle.Security.SecureRandom.NextLong — txn is part of the
authKey HMAC input, so cryptographic randomness is appropriate. Matches
the project's BouncyCastle-only crypto policy.
Advisory A2: Initialize now warns when DcvEnabled=true but no factory is
injected — surfaces a silent functional downgrade.
Advisory A3: ExtractSerialFromPem catch-all logs the suppression at Debug
(audit visibility without breaking the never-throw contract).
Advisory A5: Initialize log line gained DcvEnabled, DcvTxtRecordTemplate,
and DomainValidatorFactoryInjected so DCV configuration is visible on
every plugin restart.
Advisory A6: in-flight DCV collision log promoted from Debug to Information
— concurrent attempts are security-relevant events.
== Tests ==
153/153 unit tests pass. Live Ping/Sync still authenticate against the
sandbox (the BouncyCastle SecureRandom-based GenerateTxnId produces a
valid authKey end-to-end).
== Deferred follow-ups (not in this commit) ==
C2 (auditor): generic CERTInext error-message passthrough flagged as a
theoretical leak vector. Current behaviour matches every other CERTInext
API consumer; rewriting all throw sites to drop the underlying message
would noticeably hurt diagnostics. Worth a follow-up issue if the
compliance team wants tighter belt-and-braces.
A4 (auditor): make IsDcvNotYetReady deferral distinguishable from
"no DCV required" in the return code so audit trail shows deferral cause.
Worth doing but requires touching every PerformDcvIfNeededAsync caller.1 parent 8503a8f commit 255e3ad
6 files changed
Lines changed: 404 additions & 35 deletions
File tree
- CERTInext.Tests
- CERTInext
- Client
- docsource
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
371 | 371 | | |
372 | 372 | | |
373 | 373 | | |
374 | | - | |
| 374 | + | |
375 | 375 | | |
376 | 376 | | |
377 | 377 | | |
378 | | - | |
379 | | - | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
380 | 382 | | |
381 | 383 | | |
382 | 384 | | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
383 | 392 | | |
384 | 393 | | |
385 | 394 | | |
386 | | - | |
387 | | - | |
388 | | - | |
389 | | - | |
390 | | - | |
391 | | - | |
392 | | - | |
393 | | - | |
394 | | - | |
395 | | - | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
396 | 453 | | |
397 | 454 | | |
398 | 455 | | |
| |||
426 | 483 | | |
427 | 484 | | |
428 | 485 | | |
429 | | - | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
430 | 490 | | |
431 | 491 | | |
432 | 492 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
0 commit comments