Skip to content

security: enforce strict input validation and payload bounds in tokens.Service (Fixes #1608) - #1659

Closed
SurbhiAgarwal1 wants to merge 16 commits into
LFDT-Panurus:mainfrom
SurbhiAgarwal1:security/tokens-validation
Closed

security: enforce strict input validation and payload bounds in tokens.Service (Fixes #1608)#1659
SurbhiAgarwal1 wants to merge 16 commits into
LFDT-Panurus:mainfrom
SurbhiAgarwal1:security/tokens-validation

Conversation

@SurbhiAgarwal1

Copy link
Copy Markdown
Contributor

Description

This PR implements strict input validation and payload bounds within the tokens.Service.Append method to protect the system against resource exhaustion and potential Denial of Service (DoS) attacks from malformed or oversized finality data.

Changes

  • ValidationConfig: Introduced a configurable validation layer with safe default limits:
    • MaxTokenPayloadSize: 1MB (covers TokenOnLedger and TokenOnLedgerMetadata)
    • MaxTokenOutputsPerTx: 1000 outputs
    • MaxBulkDeleteSize: 10,000 IDs
    • MaxWalletIDSize: 1024 bytes
    • MaxOwnerRawSize: 2048 bytes
    • MaxIssuerRawSize: 2048 bytes
  • AppendRequest: Refactored the internal data flow to use a request-based structure for validated processing.
  • Strict Validation Logic: Implemented validateAppendRequest which performs in-memory checks before any database transactions or storage operations are initiated.
  • Enhanced Testing: Added a comprehensive test suite in token/services/tokens/validation_test.go covering edge cases, limit violations, and structural validation.

Verification Results

  • Unit Tests: All tests in token/services/tokens passed successfully.
  • Linting: Code is clean according to golangci-lint (v2) standards, including nlreturn and testifylint compliance.

Fixes: #1608

@HayimShaul

Copy link
Copy Markdown
Contributor

@SurbhiAgarwal1 , Thank you for the PR.
I think the PR implements validation in the wrong place. While the validation logic itself is good, it only protects the local token database after transactions are already committed to the ledger.

The primary validation must occur in the Validator before transactions are committed. The current implementation can be kept as a secondary defense layer, but the main mitigation is missing.

Can you please revise?

Comment thread plan.md Outdated
Comment on lines +1 to +2
# Implementation Plan - Strict Input Validation in tokens.Service.Append

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this file should be a part of the commit

@@ -1 +1 @@
{"identifier":"zkatdlognogh.v1","raw":"Cgx6a2F0ZGxvZ25vZ2gQARoCCAEicgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkZuYmFsMFJEeCt3dkRzREhiUExvQmdJeG5USktLcFRJZlhzNkZNMk9uVWNUaDVNbkZma2xaSkJGMlMvQlBOUk42NmcrZ1BLMkx0NkZQS1dVUGgzczlRPT0ifSJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiQ1dMTE41NUtRYTRVd2lwR0hySUxZZFAvT2hNZEJ1OFpPNTkxRnJlZmhGNEN6N3FrWkFWUlBUbEs3N09PZlVydHd5MURsRm92L1RJY3BwN011a2k5a1E9PSJ9InIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJDbm9IblNnWDlzRjN3MjJ2UW5XdzlGNnBpb3Z1Qi9YenlaQ3VPd09yYWFFUnBoVDZCeTdyMnpKUzUyaFY5SDI0bXhrbjJPT3FFZjJ6aWt4NmF4anpzUT09In0q7HUKcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkVLTkVhNXRjZlRxTEloS1FqY0JkK1NaSzVoWVJuS1lpdTN1ZHF1SFJ4MzRqWnBsNUJ4THZkbDhtcEVaRGVqVFpZUnB0ellZbnRoWmlFb3VwNUtEUUd3PT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiQ0dLaExDazhPd3NwN0l3OFYzOHNBQjdKWmU0eXA1TEx1NEFCV1hkeE5KUUlvQUVRQ25rYy82QTFyQklKNWdJbE93YUFQRVliaWZoVnQwRU1zazZGSWc9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJFZ1dWazMwaGt0WVFtU2dVcmNiNG1kSkNYemRBamljYnRWQXlYaVJRd3hjanpmVk03T3UzQ2xJTndOZ3FPOHN5Vlc2M0JycUNhWHdpRUtIbWxhWVZuUT09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkpXWTJpTUtnRjRzbm16NzU2enlCV1dESWRzamg2emcvVU9VaHZwUU5MQ2txaTZxOVUwVkNldlptT2NnVFZ0RXlrL3FPUHl5MmJNaW9ESjk5aENDRVBnPT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiSVQ4ajdjMlpPVHlnK0MwcDlJNWNRSG5hd3BXRTBGcXh0bnBtblcrOWdvc3BsbU9mRFNBNVpMVHlERUlxMG1DbGx0SlhVcHRMRUxueHBwanRlcFNzdGc9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJKa0V1UW1NT1NVTmlQcEQ2Sm1odU44bzFzNnMwZ3lKck44NmorMDRwa2hNQVpHN1NxL1U0eEd4c21OamhPOVpZRllZZzk4d3krakVSYWozd3JQcVF2Zz09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkpNenBLQmNpdEg1ZDljeHgvOG51L0JvaXdyb282V0dvVHVab2E1ODNYMDByZjJTQ1V1OFNuQjNTa2RyZ0hqSGpPK0M2dHVoYmRKQlVHS3daY0dRK3NBPT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiTG1BT0NhbEoyMTNPZlJYeWNjNHBzdEVYZVZUY2U0c0lnblE2WThwUTFvY09FNDdhb1ExZ1BBd0t2N2xhMDdHMXNFRFRYeVBzSjcvcEtCcmd1Z01oN3c9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJJQjhXbmRWUXNLZ0UwSldSQndqMWtodlZBaFhXdXNzMS9iZ1luUFU2NmdjZVR6c2RVcDU0d3VYQlZkU2ErM1RZbllCdzUvSlpWb1AySktoQUg2eFhGdz09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6Ikl1bGJ2Z1hza0x6R3hFR2N6Y2JRMzhZSGxKTzF1T0pka0xZOUN1aTBQZHNpTms5KytIRDg1NENLSG9YYUl3d0tiRDNXa1NTRDNrY09YVXhlU3JuVzd3PT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiRkI4bUp6b0Rwb3UxOFJ2NE9xY2FtcVZZKzdNd3RudnNXQUF2cjhGbkdTNG9uNENETmNheWhYeDY4UDNJTXV4ZUhjMWxKQjBMTlZJd08xdTZNZVZFR3c9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJBSERzVEZ0dlgvTFVqUHR3Rkw1VzhWS3plNHhmcW1TWjNUTTh1UVFOcXhFa2dxWVdNU1JMTWttSFYvaE91MktsVE80OUpFZHV5SGRENWgxWG8zd0xpQT09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6Ik1GampLTWVtaElEZ2xFVVY5WHppdDBsY1hWNEdSZmFnNktYQk1yS0xVN1VzM0k4a2VxM3Y5K1VndnhhMmMyejFyWnE5MXIrRkdrVlc2Z1hIemVTRjhRPT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiQUZFQ2ozcjAreHFTTmRGb3I0UTNpVEZmWFlTQis3N2tpb25mVFJUT20ya1Mzb004OVJQaFRQTWFqeURPaWZ1dGRjY0dFVjlIbVNjTmxMMWUrcitWa1E9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJKWlR2VksyMkxNSDJYOU1CMEM1ak50VU5sdzBUaTI0a21oTVQ3cXNaWDNVRDZVZTVsKzBLc2tBcGl1cm1PWXBOMjQzU3ZsMjZHUDk2dnJqVWtFeDV1dz09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6Ikd4eTVtM0pBR0E3K3VkcDhFNzdqTzViZjgrS0w1dWNmQmRwWXZhNmhITk1lRVAzM2VCc21XNE9TYlpWazFDU25MWlBCVWMzR3FiVFpkRVJGZzNhQXFnPT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiSUhYMkZqeVhiOTNkNGphVlU0ZkorVWlreUhLZkl5WDZsL0NmTzJtNHZVc0JWQU1MRVhldFgrVUh1TVBmZ2hhbVpyY1lybHZFaTNSNytXaVhqVDFCd2c9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJHbGNWT3RJanN2cHpLV2QvamgzbkpoQ0tiOWRCeUQ2Vy9Ja0tkV3BQSUZRVk1uNldDc2x4L2p6Tlc0K3RyOUtCOWtTUkJKS0pnVGc2eFBJeXFzNE9Xdz09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6Ikx0YUF3Mkd0WHE4enZ3OVFWZmRRZ2F2eWJnSHRWSndINGVSNFNSZFJnOGdudCtQNmtBVUpNMlB4RnV0Q2hINkpCOXZCYVZlZDF5QzZ1QkU1SGszVVpBPT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiSVFQSDRKWHBVNG9wSk1FNmdQMjR5UDRIbWREL1hYL2hrVitnQzYzTkZPRURCMjZ3ejRyUWxsM1FBb2s5ZEREWkM0NUtpZXEvYmIvb3FpbkNvMzlaYkE9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJINDZkbHhUYjNWNlVPUUV4eUtscFhkOG50VXFibDhkZXpUU1VCdEUxaUc4aVZqTXA1ZDZnbTdrS09SSWJOcEpGRkc2c2JNMlNLTjQrOHF2N1ZUOG5yQT09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkdzWmdkbGRFaDEyT1BNOFB1QjdpYUNuR29iajROMVdES1AyNmFzOWFmVUFMMjBqeC9ZdG9kOHN5YkhKSUVZcnB5VXFZQzRCREtWbFdOd1d2N0Jmc3h3PT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiQlh2U3RQbXdUZ1c2bW9xa0s5bDFjTTdBaCtlNXJ6RldQU1JMaU93UGxITUwrR2ZxK0F5ZjdvWU1SRU1xWVM3ZGIrQWIvUzRSSXVzaTFGWDVRVW0zVkE9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJESVE0Q0VveFFyLzF6dk9MSjc5TjBheTFwdFRGZTZET2NQU1ZRdVp0NzlndVR4RGhFSGFGR0hIWDFWckVTV1BsK1NNVWdyRHI0UTRGbms0dVpxMVlrdz09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkJpSDhaSm9sd1liN3JwQTNKWWpSYUxmYlNtTFFOY1IvNUk5UGtrUThoNDBxdENiSmRUYmVSZnVWUmZNcmY0MkQ2MEw2N3FzNCt1YWZqWUYvRHZ3ZGRRPT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiSEZPM3U1bWM2NEc0bkRZNjhFVzlibFpTQnNrcTBCb2RuSHc1bUpiYnkxa243TkZPMk5WTmFkZXBvc2w5a25GWHN4L2xiN1Mxd3FwSzBuQ1pQS2wvc2c9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJEUzNKNlFLd3VmWEh2dTFIaXRzUGZ5ZkQ3UjVTUjgwMUpabEVyL09OdWpvZE0wN1VYWmZtckczRi95RVJRdmxRcXgrTXpkci9hT2pWM2F2Ry9ITGsyUT09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IktMbDF6cGxwYWhuWlNTM2VNT0FYV1YvdG5IRmtZcW5BUlBuY0N4NVFnSG92OW9QR2d5UXgvTVQ1a0M1QmFKWkN4S1FmTFdqZmlzU0VEeFA1OVBrOXRnPT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiSkVPWlpIZU9YcHJETldKdmlKeXh6WEsxczVqdE1HRjJJcEZWVWhkWnAxSVVzWkVFTWpUb1pHUEdIeFpvU2ZyaWFYNU1Wd2dydGxQbFVleStoRWxKdUE9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJBN2J1QllqMjRDWjcvaXhvb0FpZTBPbSt2Q0NKUTVFaUlQYm5XVWpzRFNvVndrNUZMM1ZaQ3UxM05SRVlzdFI2THp6MHZwc0M1QjZVT3lXeHVIb1VEZz09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkdnTWxLeVA3aTA0WmowclV0YndQcFJOSjY3aWxjTktZVHpySzZiZHBMUEF3REc0cDFxbkxJM1FDVUtWWXRydG5DUFNjODQySURWTFNlMjQ4UC9CS2dBPT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiSEJqME9KMUZqVW5lRzZMQU1qWEU1OUFoRmtYUnpCQTFwRktFOGdMUkIyb294N0hpQTJyYU9HRGdQbWprMEFuQnlrK1ZheFRCMTAwaVlpSTBZWjlOMlE9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJHakZhQUxpR0p3Nk1IUjhZckZ3c0NRRVlQSG1vdTJlQzhUMHFScW53WXJrZXJTV3RzOUVhSFZZejlacCtDZTNTYkx4MU5KLzUxekFtc3RiS0EyZ2hTUT09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkRNa2pPcnpyTFE5ZEMrbFg5clBiVzNSVXU2UU84VXNld2JjVHRxV1N1WkVsUGUzaHBIOVNwTlc4VStoL3I5dElJVE16Z3BSc2VYS0RlR1Z5bDRMVHRRPT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiSzNvNytCb3BjQ0M2QXpRbFhlS1I3Q1hIN2Z4QTlzSTE1NlFmVmQ1RVFlRWdDamF3bVZrUm1vbkJ5Ym9YY09kNjRWOE1KYzFMdjY2MUIxSU55N25NRlE9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJKeEZDMDQ2WVJRb3F1dGovQ1RndXloVjZyTitENFlzSmNpbGpFa0RNMzVBWldJUEsxeUtMM3BjQ2F0REhja1VDckFLWmRvNkRGLy8vUWxZdWhDMjdQdz09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6Ikl5SzF4NW15VEdpemRYRjRFVWt6YXZZK1ZydTFiUGpvckg1TGl2eER3djBYb2RZM25QMHNuUjZ0bS95SHV1RFptT0psQ1N6VHBEa1dGam0vV1AvRzNnPT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiSjhCL2Z3SmVGdDR0ZkxFeVFpRnd6K2NPVlNpclU1cTJzWG9EU2w0bXdXRVJHOFJyQkF1MjZzZll0ZE5Nelo2M0llYlRsTWYxaExxMGk1NlJPRmo2TWc9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJJazg4VnJFK3ErRG9TQnIrS2c2Qi9mVW1vdWlSYUhlaHN4ZWN1eVkwWE1ZUTRkSzM3WHFSYTlCUE1xSUZjSHk4bWsyV3NyMWNvaWtVOUh5SWZXZmpHdz09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkdVVFpzSzZqSUM2SkhFcWt4dC9LK3AxMnIrcUExSlpYUU1LZ3pXa0pBUWt3T0dDRmdQYW9FY3VKVmt4bFErTFhoNms5UzNidHNkbDJHYlY3LzZONlRnPT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiQVVvbEtIZ252Z1ZBVjBwRzA1NUF5TkVlemVFRXE5eE9RdThKRi9TQVZlRVJkV0xiRWRyVXlGNk40MXZhRkRVRUFNaktRSmp3QjcyeEVuNGUvdEZXZEE9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJESWJMckdaNEtxNkVERVhsZERZVjV0WXZWUExYTHhML2lGTVJMU1g5QVlNcldSWHhDRkJIUWJjbHUwSXp0RU1TVXIram82TEVNb2FzRWNVZ1RlRlk5dz09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IktlTFQzWXZRUmFTMEhuUUFTTHVXeVZpR1V3WXA3YUl2aTRDbVYvRDBISjRzYmo3ZE1PTUVJYXhIWDlhdGM4MjVGMTl3V0RlTFBibmlNYUNPLzZlNU13PT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiQmNlalZmVEdMT29nOGxGWHh4VFNUUk9zZElPNmFlRnBJVW5tYlZ3WllzNHRLSk9sRi9yd1Y0amFYOFRYMko2UE1rSHgvWDhpWVpZeStYcUpDTzJXeXc9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJJL2hKaUNycStzTmJmMG9rUkZFTFo2R2thbVpDT1AyZnhmejNFOHk0U25jdVNWNjAzRkJFblFkWFAvUEZTN2pHUjFOQ2VoMnZ0ejRWcDZkRXl0UlVWUT09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IktWRVIzazl2RTZnZW1rUVIweG1pdys5N0diakdjV0tIZUR2MmJpOGFtRFVXdCtMeDBWL3g5TklrOCsvTUpIVUJCUDhRR2VUQVBFUGNYNnN5WWp0M1pnPT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiRzI2UGordEdHVmd1Q0hoQzhtU2dkc3lqaDkwTUxNT3ZXUi9VYkQ3cHMyY0h5RWZTVG1VclZPNC9PRy8vWE5Bdk43YkxET0pxemY0c2p4MEVSTzdmS2c9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJIcGRrb1FMLy9YMzNTS0plOVovUmU3WHhYdlRsSEpxR0RHTFJ4Mk12WUgwRmZXcmtDQlVXWndWSUJkSzAxbFp0dU0zQ3Z1MzljeWxqN0RkM3JVNTd2UT09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkF3RXZSNjJYMVBxTlN4M200cGhOVDBsMktnYU1IakN0bVFQYUZQeXhpMkVoQTBUS1pyY21VNGV3SXpONk5KVUcyd3hRWW51NFBTcFdUdzYvTkl0WmNBPT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiSElCRUNONXkydXQ3VHdxUFVxU25oOTF3Z3JOaEcwRVlycy8zRmFzT0kzb2VDUU4ydHBFMnl6MjBJeHd0MHB3RDhxUktra2hoN1pCeXJIbUNBei9XTmc9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJLM1o4cTU2U2owRU5sRWJJOE9kYVpNNXA4TTNDNThZcnB1OWVLWEZqblhvZ2lhWUoyOUhhQk8wWVlqbEV2U3VRVmF5NDVYYjVJZnNCbytoV010Sm0wQT09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IklKSjNyYnl2VmdnN3c1M1V6aEZIVzdNbXZPOCtqMERvS1FaNE5ZTFc3d3NRcWlzcWtIckk2YmdtUlNPTDMzV3M0NlIrd2FESWhjYW5yMkVOVGVrM053PT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiRzM2b3N5THZ4dFdNTzFjSVdHWmtWeUdCSXpFSytrc1Bjb1BiN0hpMGlKSUF5eitiVTh1QVhqWTUyOU93YThGNTBvYTB2VUR2cmlzSmxEVWRjVkxFUFE9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJIazlVU3VGT3l1TzYreGRMNUNQL21Nd2ZVcThVSlhRdnBQQkZWWjZ3cnljRExnMUdCK2NISGl3M3N1ZmhFSFZuY1M5UVlRQ3hwa0xMbEhTTkpvckFVZz09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkNkM1VrOGF4ek5ycE4wRTZyeFIyMTdyZHk3T04zdG1YcU1rc253bHAwNmNwZ0JWUFZ5TCtYWXMvSmw4RDNpa0RZYnMzLzBlVElkd3N1ajgwUXNsN2hnPT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiTUJGY3pzVHFoR0lDQm5YZmJUVzFnblUrNGRoNi9scXQ2S01mYWYxL3RqRW9LZU0xbWNtazNmcDJPcTNkY0RpSmE5NHM5S0ZsOFdEaXFxbkErTVAwTlE9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJBZDQ4VnhEZjBQWmpBcWRjdXI0NG5QRm91UG1lR2YyTm5YL29Ib3lXZlRNVDdVaUlUeW5xWWF3OFRNeXZ2TW8xUlpIVWhvYnJoR0JGOHJNcE03RXNLQT09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkZac01FOWkwaGtaaEZSZ1I0WE5TVjc5TDJzY1FQRkQzQmcrWFhFNDhNNGNtbTUrMm5qUFd1clRpQWwwcG52NjNpckh5Zy9Yb0M0S1NlQkNtSEQrYUd3PT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiSFhtVkNFbXFUWlhLNXE5TlNiUitySXFLSmowK0dnWnU2Qml2Ujd4aW1yVWtJa1lncTJmQUIveEVabi9BQ1pJcWdTQUVRMFpDSVNaMHJUam1seTlNU0E9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJFYllDMGVqdVBqaGRkb1VKY3BVWFhDUjhpd1VBUUM1UTFKQXkvZzMybUZnRUF2V0JVSmtIM203K2ozbm12TDhxczh5U1FKM09RU0JOZnlEUTZXWkIwQT09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkY4SmxPVEszM0w1a014bEFmcXNsU1d2MC9pMUZTMjJ5TVNnenhkTWhSVm9tSm9TRjEwaXdyNFF0V1p6SFFTUmwyNC9tdXpOZ2NRZWExdHFTYlF2bER3PT0ifQpyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiSFV3aFBFL3hhM3B6eHJxODFUc1d0NlBVWi9KMVhmVW1LMW5aR0xVYnBFZ3FEQXMyanIrdjQ1ZzhVVU9vQW5ZNWlIM3hlelV0RHl3NCtQREw0M2VOZHc9PSJ9CnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJLd2hod29hMTFQVC9ZSW5MdGJIcG85ZlZXSFpmR0ZiRGVhZUp6WTQ5b1FFRHVFaFV3dFdPc0hvQ29YUXMwbExiS29hampWVm02Vk0zTGE4REpWQVEyQT09In0KcgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkdhajJneVJuSDNodU9EZlF6ZnNkVUtMRklySWQ4ZVpnMUQyNU9abVQ2dk1pbXMrRi8yUnduN1RPYVJwQjVwU1VDcnJBTW83U21rVVlUa2tqR2N4d1p3PT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiRDBCOWwxU1JjS3JFbzBTNExUcG81eFVONFliVUFGckZWMm50M2FKd3FMNEJ5ZEt5UkpPZnFGcVdjRGw3MGhyTXJoNjNQcVFFQllYQnptUU1CRC9YS0E9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJHTU41S1EwYVloOG9kQWpjbDNzMXFrQ1hBc1cwV1VZMUZYaFhTRlNlQUd3a0Jnc2JHUllKVVF3bE1MdWtpQjZTYnQxNUEvSzkrb0dSVjVrN0Y0VjRqQT09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkYwVUg1eFZyYm5WeEhRQTNsLzBsblBod2dWMUFYc1lsOEVkY0VMeWphQWNrbFlZOFBpSWIwSTR2RVBHMHZrV1lXcFNrRWEvYWtrZXNsSzdDVE53Z3p3PT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiRWx3cDdRZmZra2tHWGxxY2oyT1BiWHBEWG5XelhQU3BNRFVPcTZ6Z1Q0RWMyTUR5M2I4R0dINzRvalQ1dkZDS0dsWndweGVDMTNHMFVLcUpxMWY4bUE9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJLeFJZNm52dHBxK1ZLd1kwUkJ5cS93QUx5cE5VTlVrV3VaVVJCR1Y4SzNrWkVuV1RhdWI3UUlDUVRGSFdVNEZEZmNyb3Y0Tmh1N1liUEp3Z3AzenFRQT09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkQraEU2VmxOR3BoRHEzeWVqN1BrV1J2L1kzRElXeGVYN0JiODU4VjdKdkVtZXFRcnRpRDkrZ0lhM1BjK1d4U1BCbUJpOEQ2aVo3bDNqUTkzODJIQlhBPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiRVh1QmpTRm9qNXY5eTFSTjgvT3RTTlNKY3NYOTZJR2lhTlo4SEtEK2V6d3F5bmtSVWpvZk02Mjh2dUFRSGQyYzdWMEtndWhJOFdzRWRodXlYYzhyV2c9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJKcTBkbm5rMlNjSjR6Y2hXTnRnck5PejNJcTlyd2ZjQlNJWHV4ZUFLQlhFczAvRzlBVXRXQmx2K1FLYTRDZlczTitpRDlzUWJLd0UrQlZobGs0ZGxMQT09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkNqb1BNWUJIbEFKMWV1R3lwTUsxampxalk1ZkQxNDJCQ3paTmVoOXlwK2dXaDZUNGVaNTJNY2lrSDRNalcvTG13dmdOdXNrcytKcjl3L2tyL09QeWV3PT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiRjVPei9wVVlMcklMbXB0WXFJcnQ4U050NDAweE5mL05yeExuaUg5YzlHb29EZ3Uwbmk1RDBLRmxISThyamRIYU43Umlvei9tbFZtL1Q1Sm90c3h6aGc9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJJeFgrVHlzdy9QMHk2WTdZaFI2cUkwV3g5Vk4rUnNXZ1FnSGRFdDdhR1Bvc0FWVmJneGdKVEU3elJqUnFkbjdZdEpNZWlsMmorQzFXWE5DVndTdS9rUT09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkRNOTAxeUtqa014Y3Q5ZW5FWGVzNWdDbjN5cEN1M1pSQVlKWjUrODJXdDhSMXZNeXB0OUpkK1AxYVMxdXZ5NzEvQ2tEektndTBjNmxDZi8rUXlLOStnPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiRlR6SnZoMmtNSHVXZ08zMVFQazZEeW9acVZ3M1ZHYUFzWm83L1NscEx0VVZSeE1MeXVZMzRpZDI1VnpSbTRzWmRrUmgwM1NvMnpXbWZ5V0VzSTJXdGc9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJLbXU4YXRRTHVaL2J3aEFzbXhLWFljZnBQVHU3bGp3bXdaN2xOelN4M21zb1pSMnY0RHlURFE0MWRwcE9WbzFnTkd4MUlhZDVqWWFCTy9LcFJGNHpCUT09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IklReVZKSEFkekFqblc4WWxOVWZhRU1Rc3MvL1dTUXZpL2tVTXFSNXdkVEVIZVlIVTV4Q0xhVTRsSThKekFtMzRud3Z1Rk5kZThjbU9ENGxyb2poT2dBPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiSXloTjI3KzlVMWJRRS9rWGVxazBxY0JiMGlaZEY2VzVXdHVCMnhBc3hyWVA0TkxVaEtHeTR0dEE5TmpTNDI4OXhJNUNTN1Z2d0d3SHZtakQ3ZlFwSWc9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJMWnZhM2tJVk12UzQxdXVzMkVZSHlCcFYvRkhqSG95eDJWN1c3MjlVbEdZUFZKQ29oSk1MYWk4amcvNGxURExxZDltdzdSVFZjQTZSRnFoWGplNE42QT09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkM0cWoyUmJnUFd6OEdJSnhZQzltcmRHc3R6VHpLS2NuTW5ETjJUc3ZjdHdhV0VtQVd5Ty9CVFlFUnZUazZKbUFqZHdQd1phSVBYU1psTHdBazFnbmVBPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiRGttbGJwa1JKZ3JvVUZxSGFCV3dWTG9naG5OUmNHcHRLZFVnWWhTbEt0NENkM29kSjRDVWhRbnYzZ2t3M3ZJY0RNZGFnUnFOdHFaSXFSVTVObEdNb2c9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJIRk95NHMwRCsxdEhsSGxNVDE5dW13aytrQWRJeUhyQ3JYVTV1YWowSG13SUJ3OWhQblFNTHVCeVR0K3dya1JoSXFuK2Jka21EdGVaWGJLcXFOVVM5QT09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6Ikd1RGd1TXQ1NHlUWEJJS2dOS2JGVVloMUZOVEM5Vk9VWjAxNzBkRFFYTjRPbytEZWhPZUw2NEdHM2pDbk5NTnppaE9vV3M0Yzd4RlZNcDQ0UzZ6QitnPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiQUlVTHR6TVlKMmtmWFNpQVpDOUdFTzVDOFUzNjFCSmZQWW0zOElPc3NkQXNUSDhlU2cvdmVCVTF6RDlCREpyOFo5T3d5bFJGMjdUdWhOVlhCbUtSV0E9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJITHU3YzVuMkxzYzJjeWlXcllUcFYyZXptdnNiVWNLWGZmQ0RyUkpiblhzaFVLZzRLUmlvWWdULzQxN3JaSjJzd0xteUdTZ0V6VzVNTTlKMXhLWDlodz09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkU3OUZBT0NnVGprVjJ6bHJWeWY5MWYyQjRkK3lTVGljem0zd05JNmg0bXdwUERCZDFpK2V4enlpNUg1VGFiR0xEdFl4RzdzbEFBR3c4UW9OcnUzRzR3PT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiRXpJYzkwT0RhMWxMMktLTGhyV0szTDB1ZFVzSi9sakJUKzhQV0JsWkE3b2NQakd0WHJxZFhSSTZuWmVJcjgvem1yWHRSNzV1Z2w4bllpSCtxOUNjZkE9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJLbXVWZUJ6czZ3Tkg2VC94YnNMeGhuVFVMU2wrWHZ0ZUt4enh5enY5cEU0ZW9tWmJhakVPT1lqTWdkbk9wNVhzYVY2WmFEUGJJV1l3Q2lrbVNjWG9HZz09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkJ1OEVoVDQ4WTJlNi96ZXB5eWdQUzhVUldSTmN4MlNlclVpNzBVcFcvK0VvZmNzVm1kVStDUStKVkUxQUdEbFZDUFJaZGRuV3NMQjdpL0NHNkpoUERRPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiRm9HY0N2TEMyKzJaN0MraytpUXZlVDY1VlM0TEx5bjVGN3BycXFaa0MvQXRzL3V1VzNzRDhPbGdCT0NUeE1IbjZyNUw2VERYWlp4KzhRWHplT2txZ2c9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJHWjMyNXZlWGZEM3M5WFJ4ZWl3WU01SFRhdHZ1UGx4ZUhsM1QrQnpyb3BFaW0xalJQeURWeHoxT0hoYkY2Zzd2bi9mUEs3VmdyczJBS3RFQmQzS0FEdz09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkowVzhOMzlvbFcvSE9PYk9HNXowVFFOQXZqS1VtT1NTcGpLbERqUXMydTBTQTJmd2pMa2wydzVaajN2cHFhLzhRMzJKc1d0U3AzcXAxWnVJYWlSWHpRPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiSU1KWXJ6L2JGWGJ4akxVc0s0ejRlbUpDTDMrQkZsbXhvdDVSZDJGcFozc1RrVURrTjNYRWFMWVV1UkZrRzVaeVFrTkR2cHFZa3kwclMySDBIbXUrUmc9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJLYlp2RGxCUmpJVUJESlhVMUVwQzJBZEZMbU9RREMzM2RUd1VGb1RPMkpJZlRQZ0g1UmE2TjExOXBTOW1WZnpYWGV1SmJwNXovWnBvcDRMd3dKcnRiUT09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6Ikl0OXZqZ204WmUrMXpHTy94STZ1aVZzTExKc2txcmgzREc1a1greGl6QU1WUTZBcjBwaFVYenJqVUVTUUFpYnoxQUhiTnJtKyt1c3lKVTFNdXpXMnRRPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiQWw2UU02cFM0OCtHL2tLa3p0aUFpTFF4UjdXYUk2N1h0THIyOFdvanVZQXE2Nk0wTzRIMXk2bHVxRkRQQTRIRGxxSGpYQVZ4SXd5ZnNjdzNCUy9LU3c9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJDdnlTa01GL2NsbTk2OEFRdGhKc3NzTVZmOUdkbGlPcCsxbngyNkNyZm5VZ0VjczVyN3VjRm92MTlUWkJqSDN3cHVrQUU1dVZKRE1hdlFzWHlRUC9iZz09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkZZcmZCYkE1UjJzUHJac3I1RGNJNzJ4TWk3blAvbDZ6a1RUc0NYbUp1blFuVnV3UjMvOE1iaGlnNno5YmJod2hYMUZMdXdWVWREUGdCMHkzbCt0MUNBPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiRWFPSmdLUG9nZ1hZTVB3RXNobnRhZ1RHTm51V010ZnZlVGlWZElPb2hESU9ieDdNbWlUazlSa204a0R3Q2tLWUZGQUJlc2UxeDh4TnJYZXh2bllBTVE9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJCOFJRRW1SUkdJdDdwdC96K01ET0RPcndyeis1UFRaT2c4UUV4NTV4SnRJTCt4SEJQSnozdUZIdFUwOHdEcFR5SXU2TzkyMUtjSmlYZ2JwcjNESWpmdz09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkU2dFlLZHNRdy9MeEltTURGZ3czcnAwYndGcU5YYm80SllpZW5XUzk4ZnNVNWFTMkFOK2dvdHllS3kzZ1JBNkYzR0s0dlBmaUtHaGcrT2s3OHpZeW93PT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiRjF4WHpiM1dxNVpDcm5Lb2I1TG9EVFNxOU5mVmRjWkZwUnBqdjJ0VzBRRUd4QU5zdzFub01ET3ptK1JHdUNsLzFueUtWNHdGQ0k5Q1Zmc0hia1U2ZGc9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJBT0M3NWpsL3FJb0JBSU9qQU5FWHF1MitvSDVFQXRwY2lyalhtZS90RGM4WjRvRzVlODZUWGNSZ0JIdUMvTk9PWTBkeTJLeDVvQmNKVlI5ZTlsclJyUT09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkpBdEJQemRMa1JkUkFRSVIvc3VOaDJvWnY4SWhaWlZIQzRYTE9BL3RMWkFKd3ZGN2h1V3k2OUpEZVJldllTNGhkTm1wUTVncUtxY1F6Q3ZoaW5lVWFBPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiTEt2YTdMbGtPSnZrMHN6Q016ZnVOalRoM1M1WjlYM1FZdWF5dWYwa1ZxOFNva1JGV3RpUVZuMzJNdG12cEFTVHkzR0p4Kyt6L0lqOVVpUzRIVHdSdWc9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJCWkRYTWU1S1V3RUc1TVhLQkZqNDV0ZVM4eDhtaDA2TkllcjRPV011L0dJYzQ0bU55Z3NxWFBpTWhOWlY2YmhxdnpLT2RxVmR2aDFnbUpGZ3pjSGl3QT09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IktGdkp0M0s4cGlsYlJ0eER1SG84OHJXb0RLTXEzaG53Qk5pSUdLV3NUVU1KRWVqaGZsaVlMMkhobVgrWUxlQ0gzVFFEdlhtYlo5YmNTbk5FQ2NkZURRPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiSkZmZ0RPMFBkWExoYkRFOUdaTEdkbXp6NlFTNkhZazhnaEEzOFVxYXZtVXJUOHU4WkQ3eXZsMFplN1RYRkFxOGJCN0FWSDlQb1kzai9VSS9taFg3QlE9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJKZTFlb29wN0lMS0tMNGoxNVhkODNZZ09qVU5kemVtTXhMVDV2cUV3OWEwY095YVh1Wnk0VnhQTWVTcFNKTnNQVHZCQXlwVnZyRHF4UEdobWpodUpmdz09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkhlUk01elZ3U2F5bCtRY1gxZFVZUm56VUZZaUo1b1UrQk02UTRDS0hJTXNOakpWTU96OU84R2tIWTRIWmxnbzRtajdqOEg5dmRQMWUxM0p4dTZjUkZBPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiRHROOVhwZ0NYRjFQYlBmQ0dwMG54WEk2RnZYWDVJR21mUGZUMjAvZFI3Z202cHB3NU53TmhJV09Gd3ZlR2gyS2xXS05IaFhXVlRmUkRIWmxQd0d6dWc9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJIT0Roalg2NWQrc1RnWmd1aHpYcm1iK1ZHWXV2RU1FWFJHU09JaFVHaUtJSUpuMkcwS2lJZGtVRlFNd253MzN2bGw3L1h6ZVI1MmdwOVdrRDc3ZkdVdz09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkxsNEkyYWZFZXlVdzdXZ1NxT1VlVklZTWE5aFRNVDh4TkxrNmRDUStBMUFtWC8xNTZQUlJER1YrdFlpYmZ3REwrbVRMOHNKMHJjR2c4UGFSYWQvaTB3PT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiS2pya0FsUVBQM0hVdXpCYnVDaXduWXUvZ0g0T2l6cVhETnNJajJzRndHY1dtTkNTdkVHWGZlVzZSakNJZ0RDMkYrUStRRFZPWUR3U3Jkam1aSDdhMGc9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJGQi82a0V3blhOOWNsTUEzR2s4NjdZZ0s2U3ZOckZtK043SVpod3BhRXYwU2dJdGxSalVIdFFqMGhwZnNjOTdraGN3UVFyQUh2QXpqLzJJUC9tWFUxdz09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkVaeFJoM1o1akVYUC8raW5QTWxwbWYwRDlaWjBSMURuc3p1V1UwNzBnNUFlQUZva1cxQW5ldlBLN0F3Zjh3VzBtTmp2NnZKL255RXdkbWJNaFhqU0JnPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiQzRic1VST0xXNkp0aGVpZ1lZeUlsTStQa0ZqREZ5TG9WUTQ5eW0rUVhab291QUNBSThzY0hMdXNidFpGaiswdTI4VzZVeUIxOFlrL01tNFM1dWpsK2c9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJCSGRsUTlYMENXSjBQZFRvSmFwSURXZWtrREluZGl3RUhESWp1OHE0ZXVra0JWNFJtaE40dkIzZDdtejJ5WWhtUkFia05LU0pQSFRvSE0wMG1jTGNoQT09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6Ikkzelg0Z2JPM3Z5NmpadFNzUGhZbDNCd2Z1bzBlQnhZcWRmRkhGbXg5ZVlXNXR3NzNGM2VsMTg5aEJVSFJYZXhnMkIvQytpdTVzMmdpQ2NvQlUwM2JnPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiRDZMazlvWksxdEZJTTFRR2FhN0JLV3V2N3pzQml6blZlVVVBcGViREkzMHFDUklVN3R6THduSmI2d3NVSW05M2M4cWxZdHNqcWRWZlZIcjdqZmJ0b1E9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJJeTN0Y0ZteVk2UUdianRqc2Nqa1JTOThLRUtSWmtIbWF2bkw4TGlyUmpjUVJTSXJnem1qNTZsSUl3RGx5MllPUnlvU1ZOc00wVTVTbWxOUlQ5Q3NJdz09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkR1cVM1dlY2alZPdjZrK3JXREpENXkwOEd2T1pRM0JqTXkxeTZlWDB4VndQcWl4SkYvZE9RZ3ZDRlowMXRqRGtMTVh0RDJYZWlLbHdtSDZUWGNFZ3lRPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiSWJUdXlNUklqOWZrYVZvZ1dNaDAvT2wrU2NkNUptSTQxUmZHa0N2d0tGUXJkS1BuUjNOcVc4NFN0di90YVV2WmEzMHJGSEI4RTkyUGU3SW9DeE5ZbUE9PSJ9EnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJGK0IwNE1wZ3Y4ajdGbjMzSEZLOXJjaE9wR2tvd3ExZFgwQWc2QVpTWk9rVzA0dllydlJWLzB3aHhYb1lTSVBwTnE4NVlNdkptUnhJeVlxMEMwb2drdz09In0ScgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkJLR2VrV2FGNW51Z20vYm03c0lIRWNPMzNtTjlNaERkUmtJbGlLbXg3UFVNcGovVjhXSHorcTZvQzdsejBvalA5VDNLQmY3TTRTWUpJTFEzOFF2bUpBPT0ifRJyCnB7ImN1cnZlIjoxLCJlbGVtZW50IjoiQ0xiZ3czTDJZeU9NTmtER3ZBU3BUYktMb283dm1FTHpLK2tLUkhWajVSY1ZNNnB2bHE0MDgrRkhQbjZNK09uNVo1aVZnV3hQZktPbmFYdE9MNnNiR2c9PSJ9GnIKcHsiY3VydmUiOjEsImVsZW1lbnQiOiJBcXhtUU5QN3ZSalhBQnJrS1NhTmhVWmFyclZMR3NSZmxNRWFueGR1U29FbFlsdThlamhtbmpzOVk2aURqWWZVcDBvYkJiWG9VWUJnL2MwUklDZllOdz09In0icgpweyJjdXJ2ZSI6MSwiZWxlbWVudCI6IkVyTGlndnkzNzVreFB3dERJVEE0Z2xQeFl4RkxOdVJCbmNTUXZCbXhTc0lNMTZ4aEZwRmlXcTR5bDVRV0J5dEV3RUQrd3NmWTNKd2p5dWxkRUdUYmNnPT0ifShAMAYy0gYKywYKAk9VCgRSb2xlCgxFbnJvbGxtZW50SUQKEFJldm9jYXRpb25IYW5kbGUSRAogHPHcNLf9UpUngfoyo8oC8XT4oScouvtMB09WtfkjG0wSIAD+ENAPjMi6MJeel3F7cb4GF92S4Gp+Z7v+5fN/21emGkQKIAU7KpssXV1r0yhbgtZ6Ru0Cn5EggH7VGTolLLeEzYNcEiAfqo4GI7e6LxMoIcHtg9bO9XBSN8niUf+Ia2HoBBdB1CJECiAhGAyC7UUopnJwVP22AtCGTFXaMPnC8wOxsP0MKcy/gRIgFSh5LWCykfGX2h4gr6HZkSwIeZQsa5AwxtmVMwFjelciRAogCM8fLnvX7ZU6hGrjbFvZLKRUXzRs+5po3tUI4Hfyn2ESIBuK0CwqaxtmrdKkrVWp+JWldHxi/xj2YxBH6dYj3QsmIkQKIC7Am20aA927w5ppCqeWjMIlZpB0x8HiFlMr+bQ1aCt5EiADnR5bFZ+uDSpKjnPK0lhyU9EctzfYmW0tILsq6OCfLyJECiATy0zLei5uWLMdivfvJrTX+8jyeCOAehVJMNTmDLGbzxIgBsqhLr3Ym/llcH2YcYUAhras5LlsCkh2Cof2UNqSfKcqiAEKICPvRq9WMtkPBJxo470aD5HH2wIFbNUDvxXt3aunkD0uEiAN/aK2TEw5MtjUXLI4DoxNdanl9fYQPiXmjxy7ZUXIHxogKH15yyvqwOYpncbg0Httv60iY0cYb3HKApOXjGBpE64iIAxH5tliMsTL0qd+7t9mET5xLefg5x6ualw1uShsacxeMkQKICGIxyTo6U8UK87sAUKPeM5WiTdYXrWPbBG4boUcgw+nEiAahkHf93CXNMTDzAoBH+PH6ivpxlKxDsjP4peVL/FFXTpECiAC7WGwFz35G7YccvFPnz1DnD7IfkaI/c9MudAeU9JLcxIgKJ6fGibl6lpDYeehDRBKLL5aJMGPRSZKzBfdZEKkm9hCIBFT8/kG8B4OjXEV2QcqscVxzpIk0CtecxKF2uw04tngSiAG2Pe8BBnM5mrO30PoaPzmESZfWIUG0AphnJ/2A3mgRlIgI+I6WVWdhuZgDwhlxRSMb6Uk3vYC3Ja6MStgsUIfOAkSAggBOusHCugHMIID5AIBAgSCA90tLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0KTUlJQ3JUQ0NBbE9nQXdJQkFnSVJBSlBCbGQvMFVmbSswU0tqRDNhYVd0RXdDZ1lJS29aSXpqMEVBd0l3ZnpFTApNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdUQ2tOaGJHbG1iM0p1YVdFeEZqQVVCZ05WQkFjVERWTmhiaUJHCmNtRnVZMmx6WTI4eEh6QWRCZ05WQkFvVEZrOXlaMkYxWkdsMGIzSXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlYKQkFNVEdXTmhMazl5WjJGMVpHbDBiM0l1WlhoaGJYQnNaUzVqYjIwd0hoY05Nakl3TnpFNE1UVXdNekF3V2hjTgpNekl3TnpFMU1UVXdNekF3V2pCak1Rc3dDUVlEVlFRR0V3SlZVekVUTUJFR0ExVUVDQk1LUTJGc2FXWnZjbTVwCllURVdNQlFHQTFVRUJ4TU5VMkZ1SUVaeVlXNWphWE5qYnpFbk1DVUdBMVVFQXhNZVlYVmthWFJ2Y2k1UGNtZGgKZFdScGRHOXlMbVY0WVcxd2JHVXVZMjl0TUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFSGJQdgovOHo1eUxSOFBUeU5HV3I3eEFiRm9ZbThScnV4Q3dESlduOVRCOFFBdXhoM2ppaXpKbjBjM0ZkTC9sWWFnWEdGClZicjJ1MDlITjQ1VlNGaG1lYU9CeXpDQnlEQU9CZ05WSFE4QkFmOEVCQU1DQjRBd0RBWURWUjBUQVFIL0JBSXcKQURBckJnTlZIU01FSkRBaWdDQ0xYZ3hTY2JJOFJaMUhrL2xZejlzRE9SZjlmaGNwT3h6MUJ1U2FHdHJFTkRCNwpCZ2dxQXdRRkJnY0lBUVJ2ZXlKaGRIUnljeUk2ZXlKb1ppNUJabVpwYkdsaGRHbHZiaUk2SWlJc0ltaG1Ma1Z1CmNtOXNiRzFsYm5SSlJDSTZJbUYxWkdsMGIzSXVUM0puWVhWa2FYUnZjaTVsZUdGdGNHeGxMbU52YlNJc0ltaG0KTGxSNWNHVWlPaUlpTENKeVpXeGhlU0k2SW1aaGJITmxJbjE5TUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSVFEZApJNHlrZERQS0RRQVpQMk5pYlhLOVlUS3dLU2YvaXJYdEJUeTJXem9KbndJZ1V3V0FDR08wVmFZaWRyZnQrQXMzCk9jeFJSYjFmYUM0a1lVeng2LzJhaHhnPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCkLfBwrcBzCCA9gCAQIEggPRLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNwVENDQWsyZ0F3SUJBZ0lSQU80RGdDOGllaWxUc1A5Q0dWVzBxaGd3Q2dZSUtvWkl6ajBFQXdJd2ZURUwKTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFnVENrTmhiR2xtYjNKdWFXRXhGakFVQmdOVkJBY1REVk5oYmlCRwpjbUZ1WTJselkyOHhIakFjQmdOVkJBb1RGVTl5WjJsemMzVmxjaTVsZUdGdGNHeGxMbU52YlRFaE1COEdBMVVFCkF4TVlZMkV1VDNKbmFYTnpkV1Z5TG1WNFlXMXdiR1V1WTI5dE1CNFhEVEl5TURjeE9ERTFNRE13TUZvWERUTXkKTURjeE5URTFNRE13TUZvd1lURUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdUQ2tOaGJHbG1iM0p1YVdFeApGakFVQmdOVkJBY1REVk5oYmlCR2NtRnVZMmx6WTI4eEpUQWpCZ05WQkFNVEhHbHpjM1ZsY2k1UGNtZHBjM04xClpYSXVaWGhoYlhCc1pTNWpiMjB3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVJacTJZck5ZZGsKbFFjenhMR2ZIdU4yVUxROHExTXovejZKRnBSQ0xUZmdrZEpHTldUU3NWdm9iczlENW10QmlxNDJabTdOTXhNLwplSU9vZDVnZXQ1Ni9vNEhKTUlIR01BNEdBMVVkRHdFQi93UUVBd0lIZ0RBTUJnTlZIUk1CQWY4RUFqQUFNQ3NHCkExVWRJd1FrTUNLQUlGR0s3dXc0NUR6MU4yTGl6YUlDSFFrOWo5Tk5RWS9RdUVCR25GRHo1YStXTUhrR0NDb0QKQkFVR0J3Z0JCRzE3SW1GMGRISnpJanA3SW1obUxrRm1abWxzYVdGMGFXOXVJam9pSWl3aWFHWXVSVzV5YjJ4cwpiV1Z1ZEVsRUlqb2lhWE56ZFdWeUxrOXlaMmx6YzNWbGNpNWxlR0Z0Y0d4bExtTnZiU0lzSW1obUxsUjVjR1VpCk9pSWlMQ0p5Wld4aGVTSTZJbVpoYkhObEluMTlNQW9HQ0NxR1NNNDlCQU1DQTBZQU1FTUNJRHROamdsa29EY0sKaFRjWVFIcTA1V2lrdy9jZGdhRTJtalBGTEE5T211bWdBaDk2bGI5cHBIWEM3WjNGYVNNWGVhUTBkOE9xc0VabgpVWWQ3aEFmeWlrMGUKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQpI////////////AVBAWggKAmsxEgJmMVoICgJrMhICZjI="} No newline at end of file

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this file changed?

@HayimShaul

Copy link
Copy Markdown
Contributor

Can you please also add size limit in protobuf?

Comment thread token/services/tokens/tokens.go Outdated
Comment on lines +115 to +121
Config: ValidationConfig{
MaxTokenPayloadSize: 2 * 1024 * 1024, // 2MB
MaxTokenOutputsPerTx: 1000,
MaxBulkDeleteSize: 10000,
MaxWalletIDSize: 1024,
MaxOwnerRawSize: 16 * 1024, // 16KB for Idemix
MaxIssuerRawSize: 16 * 1024,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe have these value configurable?

@adecaro

adecaro commented May 12, 2026

Copy link
Copy Markdown
Contributor

Hi @SurbhiAgarwal1 , any update on this? Any clarification needed? Many thanks 🙏

@SurbhiAgarwal1

Copy link
Copy Markdown
Contributor Author

Thanks @HayimShaul and @adecaro for the detailed feedback.

You're right — the current validation in tokens.Service.Append mainly protects the local token database after the transaction processing flow, so it should not be the primary enforcement point. I’ll revise the implementation to add the main validation earlier in the Validator path before transaction commitment, while keeping the current checks in tokens.Service.Append as an additional defense layer.

I’ll also:

  • remove unrelated file changes from the PR,
  • add protobuf/message size bounds where applicable,
  • make validation limits configurable,
  • and resolve the current merge conflicts.

I’ll push an updated revision soon. Thanks again for the guidance 🙏

@SurbhiAgarwal1
SurbhiAgarwal1 force-pushed the security/tokens-validation branch 5 times, most recently from 2965556 to cc8ac24 Compare May 12, 2026 20:14
…s.Service

This commit implements a comprehensive security validation layer to mitigate resource exhaustion and DoS risks.

- Refactored Validator layer to serve as the primary enforcement point for payload and action constraints before transaction commitment.

- Updated ValidationConfig to incorporate configurable limits for total token request size and action counts.

- Added strict protobuf unmarshaling bounds in driver/request.go for all message types.

- Propagated configurable validation limits through TMS and service layers for consistent enforcement.

- Updated validator mocks and test suites to verify new security bounds.

Fixes LFDT-Panurus#1608

Signed-off-by: SurbhiAgarwal1 <agarwalsurbhi1807@gmail.com>
@SurbhiAgarwal1
SurbhiAgarwal1 force-pushed the security/tokens-validation branch 3 times, most recently from eeeced7 to 1ef1543 Compare May 13, 2026 11:47
sid200727 and others added 14 commits May 13, 2026 22:03
…rus#1597)

Signed-off-by: Siddhi Khandelwal <siddhi.200727@gmail.com>
…WalletStore.StoreIdentity (LFDT-Panurus#1662)

Signed-off-by: Rama542 <Rama542@users.noreply.github.com>
…dex-friendly branches (LFDT-Panurus#1681)

Signed-off-by: Evan <evanyan@sign.global>
Co-authored-by: Evan <evanyan@sign.global>
…rics (LFDT-Panurus#1660)

Signed-off-by: Soumya8898 <soumyaranjanmohapatra784@gmail.com>
Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
Co-authored-by: Soumya Mohapatra <mohapatras@microsoft.com>
…LFDT-Panurus#1694)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ecurrence (LFDT-Panurus#1696)

Signed-off-by: Ankit Basu <ankitbasu14@gmail.com>
Signed-off-by: atharrva01 <atharvaborade568@gmail.com>
LFDT-Panurus#1689)

Signed-off-by: Rama542 <ramasasankgudipati@gmail.com>
Co-authored-by: Rama542 <Rama542@users.noreply.github.com>
LFDT-Panurus#1628)

Signed-off-by: SuyashAlphaC <suyashagrawal862@gmail.com>
Co-authored-by: Angelo De Caro <adc@zurich.ibm.com>
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
…st (LFDT-Panurus#1691)

Signed-off-by: SuyashAlphaC <suyashagrawal862@gmail.com>
Signed-off-by: SurbhiAgarwal1 <agarwalsurbhi1807@gmail.com>
@SurbhiAgarwal1
SurbhiAgarwal1 force-pushed the security/tokens-validation branch from 1ef1543 to 830e18c Compare May 13, 2026 16:36
@SurbhiAgarwal1

Copy link
Copy Markdown
Contributor Author

Hi @HayimShaul and @adecaro ,

I've just pushed a clean, rebased version of this PR. I apologize for the noise earlier—I wanted to make sure the implementation was fully synchronized with the latest upstream changes (especially the recent FSC updates) and that all local regressions were addressed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enforce Strict Input Validation and Payload Bounds on Token Store Writes [MED]

10 participants