Four screening failures. Four requests you can run.
On October 13, 2026, OFAC published its settlement with Bank of America, N.A.: $11,662,930 for 475 apparent violations. The release describes, in OFAC's own words, how the bank's sanctions screening failed. This page quotes each failure from the release, states the control Noble applies, and gives a request you can run against production to see the response field that proves it.
Source: ofac.treasury.gov/media/937231/download (PDF, 6 pages). Every quotation below is verbatim from that document. Part of Noble's enforcement series.
Bank of America, N.A. (Bank of America), a national banking association headquartered in Charlotte, North Carolina, has agreed to pay $11,662,930 to settle its potential civil liability for 475 apparent violations of OFAC sanctions programs targeting Russia, Belarus, Iran, Burma, Somalia, narcotics, and global terrorism.
Enforcement Release, page 1. Total value of the apparent violations: approximately $14,834,082 (page 2).
KEY to a Noble API key. A free-tier key works; keys are invite-only while Noble is in beta (sales@noblesight.io). Each request is one line. Each response is JSON; the field named beside it is the evidence.
| # | What OFAC found | Noble control | Field |
|---|---|---|---|
| 1 | Watchlist not updated for five weeks in 2023; a one-day lag in 2025 | Per-list watchers; the list version is on every screening | list_versions[] |
| 2 | Exact name and date-of-birth matches classified low- or medium-priority | An exact match scores 100 and is matches[0]; there is no priority tier | matches[0].score |
| 3 | Alerts released automatically by an "alert suppression rule" | No suppression rule exists; every alert is closed by a person with a reason | alert_id |
| 4 | A single, narrowly tailored lookback | as_of screens any name against any past list version | screened_as_of |
The watchlist was not the list
Between May 24 and June 28, 2023, due to human error by a third-party vendor, the sanctions watchlist file Bank of America used to perform sanctions screening was not updated to reflect changes to OFAC’s List of Specially Designated Nationals and Blocked Persons.
On February 7, 2025, Bank of America’s sanctions watchlist file failed to implement an update from Bank of America’s vendor reflecting the previous day’s designations, this time due to a series of technical problems with Bank of America’s systems. As a result, Bank of America processed 26 transactions on February 7 totaling $146,543 on behalf of a ship management company designated pursuant to the Global Terrorism Sanctions Regulations (GTSR), 31 C.F.R. part 594.
Enforcement Release, page 3, "Delays in Watchlist Updates Following OFAC Designations".
What failed
The screening system was running, and it was screening against a file that no longer matched OFAC's list. Nothing in the screening result said so. The five-week gap in 2023 was found a month later, when another bank blocked a payment downstream.
Noble's control
Noble polls each of its nine sources itself and imports every publish as a numbered version. Every screening response names the version of every list it was screened against, so the list state behind a decision is in the decision, not in a vendor's file timestamp.
Every source is polled every five minutes. If one has not been confirmed for 30 minutes, GET /v1/lists reports that list as degraded and GET /status degrades; after 2 hours it reports stale. Neither requires a key.
Run it
curl -s -X POST https://api.noblesight.io/v1/screen -H "X-API-Key: $KEY" -H "Content-Type: application/json" -d '{"name":"Alisher Usmanov"}'
The field that proves it: list_versions
"engine_version": "2.4.0",
"list_versions": [
{ "list": "ofac", "publish_id": 145, "publish_date": "2026-10-21", "record_count": 19471 },
{ "list": "uk", "publish_id": 29, "publish_date": "2026-10-16", "record_count": 6408 },
{ "list": "eu", "publish_id": 16, "publish_date": "2026-10-23", "record_count": 6269 },
{ "list": "france", "publish_id": 113, "publish_date": "2026-10-22", "record_count": 8005 },
{ "list": "un", "publish_id": 184, "publish_date": "2026-10-22", "record_count": 1010 },
...
]
Captured from production on 2026-10-23. Your response carries whatever versions are current when you run it, which is the point. Compare publish_date for ofac against the date on OFAC's recent actions; then check curl -s https://api.noblesight.io/v1/lists for the per-list freshness verdict.
An exact name and date of birth was not the top of the queue
Due to a design flaw in its alert prioritization logic, Bank of America’s sanctions relationship screening system classified alerts associated with individual customers whose name and date of birth both matched exactly those of a blocked person as low- or medium-priority, rather than high-priority. This design flaw remained in place for an extended period of time.
Enforcement Release, page 2, "Not Prioritizing Alerts for Customers Who Were Exact Name- and Date of Birth-Matches to Blocked Persons". Three designated individuals transacted for two and a half years through their own accounts.
What failed
The match was made. A second system then decided how urgent it was, and that system was wrong. The strongest possible signal, an exact name and an exact date of birth, was routed behind weaker ones.
Noble's control
There is no prioritization layer to misconfigure. An exact name scores 100, is matches[0], and raises an alert in the same response. A date of birth that agrees with the listed one is shown agreeing; one that disagrees is recorded as a dismissal_signals entry with its effect on the score, so the analyst sees the comparison rather than a tier.
Alerts scoring 90 or above carry four_eyes_required: true: a different analyst must close them.
Run it
curl -s -X POST https://api.noblesight.io/v1/screen -H "X-API-Key: $KEY" -H "Content-Type: application/json" -d '{"name":"Ramzan Kadyrov","date_of_birth":"1976-10-05"}'
The fields that prove it: matches[0].score, summary.verdict, alert_id
"alert_id": 43256,
"summary": {
"verdict": "confirmed_match",
"top_match": {
"uid": "23343",
"name": "KADYROV, Ramzan Akhmatovich",
"score": 100,
"source": "OFAC SDN",
"date_of_birth": "05 Oct 1976",
...
}
},
"matches": [
{ "uid": "23343", "score": 100, "programs": ["RUSSIA-EO14024", "MAGNIT", "GLOMAG"], "prohibition_type": "blocking", "date_of_birth": "05 Oct 1976", ... }
]
Captured from production on 2026-10-23, engine 2.4.0. The listed date of birth is returned on the match so the agreement is visible, not inferred. Send a date that disagrees and the response says so in dismissal_signals, with the field, the value you sent, and the impact on the score.
A rule released alerts nobody looked at
Despite alerting in Bank of America’s system, the payments were released automatically due to an “alert suppression rule,” a screening function used by Bank of America that automatically “suppressed” alerts in certain circumstances—for example, if an alert was based on the exact same criteria as an alert that a Bank of America analyst manually dispositioned as a false positive in the past.
Enforcement Release, page 2, "Processing of Payments Involving Blocked Banks", cause 3 of 3. Bank of America processed 403 transactions totaling $14,340,100 via 35 blocked banks.
What failed
A past false-positive decision was turned into a standing rule, and the rule kept applying after the facts changed. OFAC's compliance considerations in the same release say that "decisions concerning sanctions screening alert parameters and rules should be risk-based, adequately supervised, and subject to audit and testing in order to prevent errors from compounding."
Noble's control
Noble has no suppression rule. A match at or above the alert threshold opens an alert, every time, including when the same name was dismissed last week. Repeating an identical screening within five minutes returns the same open alert rather than a second copy; it never hides the match.
An alert closes one way: a person calls POST /v1/alerts/{id}/resolve with a reason code from a fixed vocabulary. The closure, the actor, and the reason are appended to an immutable case history and come back in GET /v1/export.
Run it
curl -s -X POST https://api.noblesight.io/v1/screen -H "X-API-Key: $KEY" -H "Content-Type: application/json" -d '{"name":"Kasem Soleimani"}'
The field that proves it: alert_id
"alert_id": 43257,
"summary": { "verdict": "confirmed_match", "top_match": { "uid": "10481", "name": "SOLEIMANI, Qasem", "score": 100, "source": "OFAC SDN" } }
# then, with the id from your response:
# curl -s https://api.noblesight.io/v1/alerts/43257 -H "X-API-Key: $KEY"
"id": 43257,
"status": "new",
"score": 100,
"four_eyes_required": true,
"due_at": "2026-10-24T18:56:39Z",
"alert_reason": "score_threshold"
Captured from production on 2026-10-23. Run the same request again tomorrow and you get a new alert, whatever happened to this one. How an alert is closed, and why it cannot be closed silently, is below.
One narrow lookback, three years late
Despite being aware since March 2022 that its routing directory included blocked banks and that it had processed transactions involving them, and despite telling OFAC in more than one instance that it was investigating payments it had processed involving blocked banks, Bank of America initially performed only a single, narrowly tailored lookback and did not identify the full scope of its payment activity involving blocked banks until after OFAC directed it to provide information about recent lookbacks it had conducted in a January 2025 administrative subpoena.
Enforcement Release, page 2, "Processing of Payments Involving Blocked Banks".
What failed
A lookback asks: on the day we processed this, was the counterparty blocked? Answering that at scale needs the list as it stood on each past date, not the list as it stands today. Without that, a lookback is a guess bounded by whatever the team can reconstruct by hand.
Noble's control
Any screening can carry as_of. The same engine scores the name against every list exactly as it stood at that instant, and the response pins list_versions to the publishes in force on that date. A lookback over a year of payments is a loop over the same request with a different date, as far back as Noble's own history reaches: each list's history begins the day Noble first imported it, in May 2026, GET /v1/lists reports that instant per list as history_from, and an as_of before it is refused rather than answered clean.
Decisions Noble already recorded can be re-verified with POST /v1/export/replay, which re-runs them against the pinned versions and reports whether the verdict still holds.
Run it
curl -s -X POST https://api.noblesight.io/v1/screen -H "X-API-Key: $KEY" -H "Content-Type: application/json" -d '{"name":"Alisher Usmanov","as_of":"2026-10-01"}'
The fields that prove it: screened_as_of, list_versions[].publish_date
"screened_at": "2026-10-23T18:57:57Z",
"screened_as_of": "2026-10-01T23:59:59.999999999Z",
"engine_version": "2.4.0",
"list_versions": [
{ "list": "ofac", "publish_id": 128, "publish_date": "2026-10-01", "record_count": 19483 },
{ "list": "uk", "publish_id": 20, "publish_date": "2026-10-01", "record_count": 6370 },
...
],
"warnings": [
{ "code": "ofac_child_detail_current_state",
"message": "OFAC was screened as of the requested instant: its listed names exactly as they stood, without aliases OFAC published later, and with names in a party's own script that OFAC has removed since. An alias's wording, and the addresses, identifiers and dates of birth in match detail, are as OFAC publishes them today, because OFAC does not publish their history." }
]
Captured from production on 2026-10-23. Note the warning: Noble tells you exactly which parts of an OFAC record it can and cannot reconstruct historically, because OFAC publishes name history but not detail history. A historical screening never creates an alert; it is a record, not a new case.
ownership on every response) addresses the ownership half of that; the human error is yours to govern. Each organization, in OFAC's words, "remains responsible for its own compliance regardless of whether it relies upon third-party providers."
Every closure is a person, a reason, and a record
This is the request that stands where Bank of America's suppression rule stood. It needs an alert you own, so it is not one of the four above; it is what happens after them.
curl -s -X POST https://api.noblesight.io/v1/alerts/$ALERT_ID/resolve -H "X-API-Key: $KEY" -H "X-Actor: analyst@yourbank.example" -H "Content-Type: application/json" -d '{"status":"closed_false_positive","reason":"false_positive_dob_mismatch","note":"Customer DOB 1981-03-02 per passport; listed party born 1976."}'
The reason must be one of a fixed set; a free-text reason or a missing one is refused with 400 invalid_reason_code, which is the response you get if you run the request above without a reason:
false_positive_name_onlyfalse_positive_dob_mismatchfalse_positive_country_mismatchfalse_positive_entity_type_mismatchfalse_positive_othertrue_match(with adisposition: blocked, rejected, permitted_gl, no_action_required)
On an alert scoring 90 or above, the closing actor must differ from the actor who last touched it. X-Actor is validated against the tenant's registered team (/v1/team); an unregistered identity is refused rather than recorded. The case history is append-only and exported with the screening it belongs to. A true match carries a disposition, and GET /v1/alerts/{id}/ofac-report renders the blocking or reject report OFAC requires within 10 business days.
Run the four requests against your own key
Keys are invite-only while Noble is in beta. Ask for an invite code and you will have a key, and the four responses above, in a few minutes.
Noble Sight