Commit 1d8c0dc
committed
Addresses findings from the compliance-auditor pass on commits 054b2c3
and aab1847.
== Material ==
M1. LogApiFailure now scrubs known credential fields from response
bodies before logging. The CERTInext request meta block includes a
SHA-256 `authKey` digest that is itself a replayable credential under
SOX (anyone with a valid (ts, txn, authKey) triple can replay until the
timestamp window expires); the helper had no guard against the digest
appearing in an echoed response body. New static `RedactCredentials`
applies a regex pass over JSON (`"authKey": "..."`, `"client_secret"`,
`"apiKey"`, `"accessKey"`, `"password"`), form-urlencoded
(`client_secret=...`, `authKey=...`), and `Authorization:` header
lines, replacing values with `***REDACTED***`.
Also added an explicit XML-doc warning forbidding use of LogApiFailure
on the OAuth token-exchange path — that path's request body contains
the plaintext `client_secret` and has its own dedicated
log-suppression comment at the existing throw site.
M2. PlaceOrder now emits a cumulative LogInformation on the success
branch when at least one rate-limit retry fired:
"PlaceOrder succeeded after rate-limit retries. OrderNumber=...,
RateLimitRetryCount=N, TotalBackoffSeconds=S.S". An operator scraping
gateway logs for rate-limit pressure (SOC2 CC7.2 anomaly detection) now
gets one line per call rather than having to thread per-attempt warnings
by OrderNumber.
M3. IsRateLimitSurface gained an explicit XML-doc contract section:
callers MUST only invoke inside the !result.Meta.IsSuccess branch, and
the known cost of burning up to 5 enrollment attempts on a genuinely-
inactive account is documented (the rate-limit and the inactive-account
conditions return the same string with no distinguishing errorCode).
== Advisory ==
A1. Field-reflection test in CERTInextCAPluginPublicSurfaceTests adds
BindingFlags.DeclaredOnly for symmetry with the nested-type and
method-signature checks below it. No behavioural change — GetFields
already returns declared-only for instance fields — but explicit-is-
better-than-implicit in a reflection guard test.
A3. ComputeRateLimitBackoffSeconds XML-doc now documents the
thundering-herd assumption: the SecureRandom-backed jitter is
process-wide; concurrent callers in the same process get independent
samples; cross-pod fleets each have their own SecureRandom instance so
jitter is also independent across pods.
A4. LogApiFailure gained an optional `LogLevel level = Warning`
parameter. ValidateCredentials passes `LogLevel.Error` so SOX-required
SIEM rules on authentication failures fire (a meta-failure on
ValidateCredentials is by definition an auth event). Other callers keep
the Warning default — meta-failure-on-HTTP-200 is the CA saying "no" to
a business request.
== Tests ==
New RedactCredentialsTests pins the scrubber across JSON, form-urlencoded,
Authorization-header, mixed-case, and null/empty inputs. Tests now run
182/182 (171 prior + 8 redact + 3 nullable / casing checks). Live
ping/sync against the sandbox still authenticates.
== Deferred (none) ==
No findings deferred from this audit pass. The remaining open item from
the prior compliance audit is the A4 finding on IsDcvNotYetReady
distinguishability, unchanged.
1 parent aab1847 commit 1d8c0dc
3 files changed
Lines changed: 232 additions & 14 deletions
File tree
- CERTInext.Tests
- CERTInext/Client
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
73 | 73 | | |
74 | 74 | | |
75 | 75 | | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
76 | 79 | | |
77 | | - | |
| 80 | + | |
78 | 81 | | |
79 | 82 | | |
80 | 83 | | |
| |||
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
160 | 160 | | |
161 | 161 | | |
162 | 162 | | |
163 | | - | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
164 | 169 | | |
165 | 170 | | |
166 | 171 | | |
| |||
187 | 192 | | |
188 | 193 | | |
189 | 194 | | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
190 | 200 | | |
191 | 201 | | |
192 | 202 | | |
| |||
233 | 243 | | |
234 | 244 | | |
235 | 245 | | |
| 246 | + | |
236 | 247 | | |
237 | 248 | | |
238 | 249 | | |
| |||
253 | 264 | | |
254 | 265 | | |
255 | 266 | | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
256 | 277 | | |
257 | 278 | | |
258 | 279 | | |
| |||
1471 | 1492 | | |
1472 | 1493 | | |
1473 | 1494 | | |
| 1495 | + | |
| 1496 | + | |
| 1497 | + | |
| 1498 | + | |
| 1499 | + | |
| 1500 | + | |
| 1501 | + | |
| 1502 | + | |
| 1503 | + | |
| 1504 | + | |
| 1505 | + | |
| 1506 | + | |
| 1507 | + | |
| 1508 | + | |
| 1509 | + | |
| 1510 | + | |
| 1511 | + | |
| 1512 | + | |
1474 | 1513 | | |
1475 | 1514 | | |
1476 | 1515 | | |
| |||
1481 | 1520 | | |
1482 | 1521 | | |
1483 | 1522 | | |
1484 | | - | |
| 1523 | + | |
| 1524 | + | |
| 1525 | + | |
| 1526 | + | |
| 1527 | + | |
| 1528 | + | |
| 1529 | + | |
| 1530 | + | |
| 1531 | + | |
| 1532 | + | |
| 1533 | + | |
| 1534 | + | |
| 1535 | + | |
1485 | 1536 | | |
1486 | 1537 | | |
1487 | 1538 | | |
| |||
1514 | 1565 | | |
1515 | 1566 | | |
1516 | 1567 | | |
1517 | | - | |
1518 | | - | |
1519 | | - | |
1520 | | - | |
1521 | | - | |
| 1568 | + | |
| 1569 | + | |
| 1570 | + | |
| 1571 | + | |
| 1572 | + | |
| 1573 | + | |
| 1574 | + | |
| 1575 | + | |
| 1576 | + | |
| 1577 | + | |
| 1578 | + | |
| 1579 | + | |
| 1580 | + | |
| 1581 | + | |
| 1582 | + | |
| 1583 | + | |
| 1584 | + | |
| 1585 | + | |
| 1586 | + | |
| 1587 | + | |
| 1588 | + | |
| 1589 | + | |
| 1590 | + | |
| 1591 | + | |
| 1592 | + | |
| 1593 | + | |
| 1594 | + | |
| 1595 | + | |
| 1596 | + | |
| 1597 | + | |
| 1598 | + | |
| 1599 | + | |
| 1600 | + | |
| 1601 | + | |
| 1602 | + | |
| 1603 | + | |
| 1604 | + | |
| 1605 | + | |
| 1606 | + | |
| 1607 | + | |
| 1608 | + | |
| 1609 | + | |
| 1610 | + | |
| 1611 | + | |
| 1612 | + | |
| 1613 | + | |
| 1614 | + | |
1522 | 1615 | | |
1523 | 1616 | | |
1524 | 1617 | | |
1525 | 1618 | | |
1526 | 1619 | | |
1527 | 1620 | | |
| 1621 | + | |
| 1622 | + | |
| 1623 | + | |
| 1624 | + | |
| 1625 | + | |
| 1626 | + | |
| 1627 | + | |
| 1628 | + | |
| 1629 | + | |
| 1630 | + | |
| 1631 | + | |
| 1632 | + | |
| 1633 | + | |
| 1634 | + | |
1528 | 1635 | | |
1529 | 1636 | | |
1530 | 1637 | | |
1531 | 1638 | | |
1532 | 1639 | | |
1533 | | - | |
| 1640 | + | |
| 1641 | + | |
1534 | 1642 | | |
1535 | | - | |
1536 | | - | |
1537 | | - | |
1538 | | - | |
| 1643 | + | |
| 1644 | + | |
| 1645 | + | |
1539 | 1646 | | |
1540 | 1647 | | |
1541 | 1648 | | |
1542 | 1649 | | |
1543 | 1650 | | |
1544 | 1651 | | |
1545 | | - | |
| 1652 | + | |
1546 | 1653 | | |
1547 | 1654 | | |
1548 | 1655 | | |
| |||
0 commit comments