TON security record

BNB Chain, Ethereumton.orgXGitHub

As of 10 Nov 2026, TON has 6 audit reports by 2 security firms on Trustblock; the latest is by Trail of Bits, dated 25 Mar 2024. Those reports list no open critical findings.

Critical findings
No open critical findings
Across 6 reports.
Open the latest report
Your label, live
Get the label for your site

Record last updated . It holds audits and findings, contracts and incidents up to Nov 2026. Trustblock does not review code.

Audits5· Formal verifications 1

Newest first

1 other security report listed, not counted

ReportSecurity firmDateScopeCritical findingsSource
TON Foundation Multisignature WalletSecurity firm: Trail of BitsDate: Scope: Not recorded; see the reportNone openGitHub ↗
TON-EVM BridgeSecurity firm: CertiKDate: Scope: Files listedNone openskynet.certik.com ↗
TON StablecoinSecurity firm: CertiKDate: Scope: Not recorded; see the reportNone openskynet.certik.com ↗
Ton Bridge Web Application

Penetration test of off-chain systemsNot counted as an audit report

Security firm: CertiKDate: Scope: Not recorded; see the reportNone openskynet.certik.com ↗
TON Masterchain Contracts Formal VerificationFormal verificationSecurity firm: CertiKDate: Scope: Not recorded; see the reportNone openskynet.certik.com ↗
TON VestingSecurity firm: CertiKDate: Scope: Not recorded; see the reportNone openskynet.certik.com ↗
The Open Network - Audit 1 (Phase 2)Security firm: CertiKDate: Scope: Not recorded; see the reportNone openskynet.certik.com ↗

Findings77

Statuses are the security firm’s own, from each report.

SeverityOpenAcknowledgedFixed
Critical000
High312
Medium2011
Low17037
HighThe wallet cannot execute new orders if the threshold is set to 0TON Foundation Multisignature Wallet · Trail of Bits · 25 Mar 2024Fixed

The report gives no description here.

Open the report
High`block->data->deps` can be altered by a maliciousThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

Malicious actor can receive a valid block, alter the `block->data->deps` array and rebroadcast the block to other nodes. New block will be valid for catchain nodes but invalid for BCP. The block validation works this way: 1. Overlay gets the block and calls `CatChainReceiverImpl::receive_message_from_overlay(src, data)` 2. `catchain_block` is fetched from `data`, the rest is treated `payload` 3. `CatChainReceiverImpl::receive_block(src, catchain_block, payload)` is called 4. `CatChainReceiverImpl::validate_block_sync(block, payload)` is called 5. `CatChainReceivedBlock::pre_validate_block(block, payload)` is called - `block->incarnation` is verified - `block->src` is verified - `block->data->deps.size()` is verified to be not more than `max_deps` - `block->data->prev->src` is verified to be the same as `block->src` - `block->data->prev->height + 1 == block->height` is verified - it is verified that there are no `deps` from the same source - it is verified that `payload` is not empty - **`block->data->deps` array is not checked and not covered by signature** 6. For each `deps` and `prev` as argument `CatChainReceiverImpl::validate_block_sync(dep)` is called - Signature (by `dep.src`) of `block_dep_id` is checked. `block_dep_id = { incarnation, source_hash(dep.src), dep.height, dep.data_hash }` 8. Signature (by `src`) of `block_id` is checked. `block_id = { incarnation, source_hash(src), height, hash(payload) }` of original block 9. `CatChainReceiverImpl::create_block(block, payload)` is called and updates `blocks_[hash(block_id)]` This can lead to network stalling without ability to punish the malicious actor. For example: 1. Malicious actor can clear the `deps` array of received block and force `CatChainReceiverImpl::synchronize_with()` all other nodes. They will accept the modified block and `CatChainReceiverImpl::deliver_block()` immediately to `ValidatorSessionImpl::preprocess_block()` with undefined result. 2. Malicious actor can replace one `dep` with unexisting correctly signed `block_id` and push it to other nodes. They will accept it, will never be able to deliver that block to `ValidatorSession`, and will reject the same block with correct `deps` from other nodes as duplicate.

Open the report
MediumA non-executed order can be marked as executedTON Foundation Multisignature Wallet · Trail of Bits · 25 Mar 2024Fixed

The report gives no description here.

Open the report
MediumTON balance of non-executed or expired orders is not recoverableTON Foundation Multisignature Wallet · Trail of Bits · 25 Mar 2024Fixed

The report gives no description here.

Open the report
MediumBridge migration process flawTON-EVM Bridge · CertiK · 19 Jan 2023Fixed

`config_param` contains `bridge_address` and `oracles_address`. Governance (`multisig-code`) is saved as `oracles_address`. It can only send messages to `bridge_address` or to any address if it is no longer assigned as `oracles_address`. Bridge (`bridge_code`) is saved as `bridge_address`. It accepts "swap" commands from any address (locking TONs) or control commands from `oracles_address`. If Validators update both `config_param` values at once, then old Bridge no longer can get control commands: old Governance will be unauthorized, new Governance will send commands only to new Bridge. The reward accumulated on old Bridge will be locked. If Validators update only `bridge_address`, then old Bridge no longer can get control commands: Governance will send commands only to the new Bridge. That means that to perform a Bridge "migration", new Governance contract has to be modified to allow additional messages recipient, new Bridge contract has to be modified to accept `0xf00d` message. That can potentially lead to stake extraction risk.

Open the report
MediumMalicious oracle can block the bridge workTON-EVM Bridge · CertiK · 19 Jan 2023Fixed

`votes-collector` collects Secp256k1 signatures to be used in ETH Bridge call. One malicious oracle can submit invalid signatures to each voting. This will practically block the ETH side of the bridge - it will `revert()` trying to validate the signature. To restore the correct work, the honest oracles have to 1. Notice that ETH transactions are failing 2. Determine which signature is invalid 3. Cut the invalid signature from the list 4. Resubmit the failed ETH transactions 5. Ignore the malicious oracle in future This will likely take a significant time to implement.

Open the report
Medium`workchain` is not enforced in `op::mint`TON Stablecoin · CertiK · 7 Dec 2022Fixed

`jetton-minter` during processing of `op::mint` message uses `calculate_user_jetton_wallet_address()` to prepare the `jetton-wallet` address. However, even if `to_address` is not in basechain, the generated wallet address is in `workchain = 0`. As a result, the minted jettons will not be accessible.

Open the report
MediumBounced `op::internal_transfer` message from `jetTON Stablecoin · CertiK · 7 Dec 2022Fixed

When `op::internal_transfer` message is bounced from one `jetton-wallet` to another one, the `balance` is updated (increased back). However, if `op::internal_transfer` message is bounced from `jetton-wallet` to `jetton-minter`, the `total_supply` is not updated. `master_msg` provided to `op::mint` is not validated and passed as is to `jetton-wallet`. Underflow can happen. As a result the total circulating supply will be less than `total_supply`.

Open the report
MediumLack of arguments validation in `jetton-minter`TON Stablecoin · CertiK · 7 Dec 2022Fixed

During processing of `op::upgrade` the inconsistent `new_data` can be assigned. That will invalidate all the deployed wallets or `total_supply` value. `new_code` is not validated for correctness. Inconsistent storage can be also set during `jetton-minter` deployment. During processing of `op::call_to` and `op::mint` the `master_msg` and `amount` are not validated. During processing of `op::change_content` it is not validated that updated `content` follows [TIP-64 (Token Data Standard)](https://github.com/ton-blockchain/TIPs/issues/64). Incorrect data can be assigned. `symbol`, `name`, `decimals` can be changed. Well known Jetton can be renamed to something else or to another well known Jetton. This can influence the Jetton price. During processing of `op::change_admin` the `new_admin_address` is not validated. Assigning the wrong admin can prevent further minting.

Open the report
MediumUsing components with known vulnerabilitiesTon Bridge Web Application · CertiK · 29 Nov 2022Fixed

The result of the "npm audit" command shows the application is using outdated libraries with know vulnerabilities. ![npm_1669656371208.png=500x](https://accelerator-projects-prod.acc.corp.certik.com/5869efc0-85e7-11ec-aa17-2fc5451c4a10/upload/attachments/npm_1669656371208.png)

Open the report
Show 10 more
MediumPortion of bid above `max_stake` silently discardTON Masterchain Contracts Formal Verification · CertiK · 14 Sep 2022Fixed

The function `process_new_stake` has a test that the submitted stake is larger than `min_stake`. ```func if (msg_value < min_stake) { ;; stake too small, return it return return_stake(s_addr, query_id, 5); } ``` However, nothing prevents a user from submitting a bid larger that `max_stake`. The function `try_elect` will then restrict the bid to be less than `max_stake`: ```func var (stake, _, pubkey) = (min(key~load_uint(128), max_stake), key~load_uint(32), key.preload_uint(256)); ``` If the user submitted more than `max_stake`, then at this point the contract will forget about the excess part, which will become unretrievably locked in the contract balance. Note that `max_stake` is a configuration parameter which can be changed at any time by the owner of the config contract. This makes the situation potentially more error prone, because such a change could happen between the user's bid submission and the next election. So if the limit was lowered, the user could submit a bid which was valid at the time time of submission but triggered this bug at the time of election.

Open the report
MediumCatchain DoS can be provoked by valid blocks flooThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

Malicious actor can create many valid blocks to overflow internal structures of honest nodes and provoke their crash. 1. Many blocks with increasing `height` can be formed and sent by the malicious actor 2. Honest node Overlay gets the block and calls `CatChainReceiverImpl::receive_message_from_overlay(src, data)` 3. `CatChainReceiverImpl::receive_block()` is called 4. `CatChainReceiverImpl::create_block()` is called 5. `CatChainReceivedBlock::create()` allocates memory in heap Old blocks unloading is not implemented in general.

Open the report
MediumCycles in `deps` are not preventedThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

According to [Whitepaper](https://test.ton.org/catchain.pdf) the Catchain blocks form a directed acyclic graph using their `deps`. The Catchain code doesn't ensure that. Let's assume: 1. Malicious actor A creates a BlockA and shares its `block_id_A (incarnation, hash(src), height, hash(payload)` with malicious actor B 2. Malicious actor B creates a BlockB, shares its `block_id_B` with A 3. Malicious actor A uses `block_id_B` as part of `BlockA->data->deps` and broadcasts the block in the Catchain 4. Malicious actor B uses `block_id_A` as part of `BlockB->data->deps` and broadcasts the block in the Catchain 5. Honest node C gets two blocks that depend on each other Currently the code works correctly in this situation.

Open the report
Low`spend_delay` name is misleadingTON-EVM Bridge · CertiK · 19 Jan 2023Fixed

`spend_delay` in fact holds the timestamp, not "delay".

Open the report
Low`state_flags` are not describedTON-EVM Bridge · CertiK · 19 Jan 2023Fixed

The meaning of `state_flags` is not described. Setting the first bit prevents locking of TONs, however, doesn't prevent withdrawing.

Open the report
LowData structures are not describedTON-EVM Bridge · CertiK · 19 Jan 2023Fixed

Contract storage organization and incoming message layout are not described explicitly.

Open the report
LowLicense Identifier should be on the first lineTON-EVM Bridge · CertiK · 19 Jan 2023Fixed

License Identifier should be on the first line.

Open the report
LowMisleading commentsTON-EVM Bridge · CertiK · 19 Jan 2023Fixed

```cpp=83 ;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool src:MsgAddress -> 011000 var msg = begin_cell() .store_uint(0x10, 6) ;; #int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool src:MsgAddressInt = 0 1 0 0 0 00 ``` First comment mentions the binary 011000 (0x18), however, the code uses 010000 (0x10). The second comment mostly duplicates the first one, but erroneously contains `MsgAddressInt` and wrong bit sequence.

Open the report
LowTyposTON-EVM Bridge · CertiK · 19 Jan 2023Fixed

There are typos: - "transder" is supposed to be "transfer" - "transfer" is supposed to be "burn"

Open the report
Low`end_parse()` Is MissingTON Stablecoin · CertiK · 7 Dec 2022Fixed

The function `load_data()` reads all the fields of Storage, however, it does not ensure that the slice is empty after that.

Open the report
Show 10 more
Low`status` is not documentedTON Stablecoin · CertiK · 7 Dec 2022Fixed

According to the code zero `status` is considered "unlocked". Any other `status` is considered "locked". Locked status forbids performing `send_tokens()` but allows to `burn_tokens()` and `receive_tokens()`.

Open the report
LowCode documentation can be improvedTON Stablecoin · CertiK · 7 Dec 2022Fixed

In `calculate_jetton_wallet_state_init()` `StateInit` structure is used: ```c _ split_depth:(Maybe (## 5)) special:(Maybe TickTock) code:(Maybe ^Cell) data:(Maybe ^Cell) library:(HashmapE 256 SimpleLib) = StateInit; ``` In `calculate_jetton_wallet_address()` `MsgAddressInt` structure is used: ```c addr_std$10 anycast:(Maybe Anycast) workchain_id:int8 address:bits256 = MsgAddressInt; ``` `send_raw_message()` arguments preparation is not documented. `send_raw_message()` `mode` argument is not documented in comments. No corresponding constants introduced.

Open the report
LowInaccurate commentsTON Stablecoin · CertiK · 7 Dec 2022Fixed

`Storage` comment in `jetton-wallet` doesn't mention `status` field. `transfer` and `internal_transfer` comments don't contain the structure tags. Other structures: `transfer_notification`, `excesses`, `burn`, `burn_notification`, - should be described. `founds` is supposed to be `funds`. `steel` is supposed to be `still`. `uin4` is supposed to be `uint4`. `is only decreases` is supposed to be `only decreases`.

Open the report
LowTIP-74 standard is not followed regarding `op::exTON Stablecoin · CertiK · 7 Dec 2022Fixed

According to [TIP-74 standard (TON fungible tokens)](https://github.com/ton-blockchain/TIPs/issues/74) "After processing the request, the receiver's jetton-wallet **must** send at least `in_msg_value - forward_amount - 2 * max_tx_gas_price` to the `response_destination` address. If the sender jetton-wallet cannot guarantee this, it must immediately stop executing the request and throw error." So, the `op::transfer` is allowed to do two processings only. However, these values can be deducted: 1. Up to `min_tons_for_storage` can be left on the `receiver_wallet` 2. Up to 2 forward fees can be spent: one for `op::internal_transfer` from `sender_wallet` to `receiver_wallet`, one for `op::transfer_notification` from `receiver_wallet` to `receiver_owner` 3. 2 processing fees can be spent: one for `op::transfer` processing, one for `op::internal_transfer` processing In fact `op::excesses` message will get only `op::transfer::in_msg_value - forward_ton_amount - min_tons_for_storage - 2 * fwd_fee - 2 * max_tx_gas_price`. Also, `gas_consumption` constant is hardcoded, not obtained from `ConfigParam21 gas_limit`. This makes the calculations inaccurate for different workchains.

Open the report
LowClickjackingTon Bridge Web Application · CertiK · 29 Nov 2022Fixed

The HTTP response of the GET request to https://ton.org/bridge/ doesn't contain any security headers to prevent the website from loading in an iframe.

Open the report
LowPotential insecure application hostingTon Bridge Web Application · CertiK · 29 Nov 2022Fixed

The bridge application "https://ton.org/bridge/" is hosted on a third-party platform, "Github". If the application is hosted on a third-party platform, then the team is trusting the platform's own security to prevent an attacker from modifying the site to perform malicious actions within the application. The host "ton.org" points to the Cloudflare CDN. One of the benefits of using Cloudflare is that it offers security features such as "WAF" and DDOS protection. However, the application can be accessed with the alternative URL "https://newton-blockchain.github.io/bridge/". This exposed the application from Cloudflare's protection.

Open the report
LowNo check for existing key in `annouce_new_electioTON Masterchain Contracts Formal Verification · CertiK · 14 Sep 2022Fixed

The `conduct_elections` function computes the next validator set and then stores it in the `past_elect` dictionary. The key it is stored under is the `elect_at` field, the time at which the election takes place. If there somehow was already a past validator set stored under the same key, the past set would be overwritten and all the stakes in it lost. The `elect_at` field is chosen in `announce_new_elections` to be a time in the future (`now() + elect_begin_before`), so intuitively it will be distinct from other election times in the past. However, there is some extra logic that can move it to a slightly earlier time ("pretend that the elections started at t0"). Exactly which time `t0` would be depends on configuration parameters which are set and changed outside the elector contract, which makes it hard to formally prove that there can never be a clash. The likelihood of this going wrong may seem remote, but another check would make the contract more self-contained.

Open the report
LowNot deducting message cost in `conduct_elections`TON Masterchain Contracts Formal Verification · CertiK · 14 Sep 2022Fixed

There are two cases in the elector contract when it sends a message and includes approximately 1 Gram of value in order to pay for the message processing costs. These are in `process_new_stake` (the call to `send_confirmation`) and in `conduct_elections` (the call to `send_validator_set_to_config`). In `process_new_stake` this cost is deducted from the posted stake, so that the accounting is correct: ```func msg_value -= 1000000000; ;; deduct GR$1 for sending confirmation ``` However, there is no logic in `conduct_elections` which explains where the value of the message should be deducted from, which breaks the invariant that data structures reflect the current balance of the contract.

Open the report
LowUnused function argument in `announce_new_electioTON Masterchain Contracts Formal Verification · CertiK · 14 Sep 2022Fixed

The function `announce_new_elections` takes an argument `elect` despite declaring a local variable with the same name which is used in the function body. The argument is redundant.

Open the report
Low`send_raw_message()` is used in "Ignore errors" mTON Vesting · CertiK · 5 Aug 2022Fixed

`mode = 3` means: +1 - sender pays fees, +2 - ignore errors. It is unclear, why "ignore errors" mode is enforced by the contract.

Open the report
Show 10 more
LowImproper Usage of `impure` ModifierTON Vesting · CertiK · 5 Aug 2022Fixed

The function `recv_internal()` is defined as `impure`, but it does not modify the storage or throw an exception.

Open the report
Low`CatChainReceivedBlockImpl::deps_` should be nameThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

`CatChainReceivedBlockImpl` has fields `block_deps_`, `deps_`, `rev_deps_`, `pending_deps_`. - `block_deps_` holds pointers to blocks from other nodes - `deps_` holds **heights** of this block source chain pieces - `rev_deps_` holds pointers to blocks that depend on this one - `pending_deps_` holds the number of full blocks required to `CatChainReceiverImpl::run_block()` `deps_` name is misleading.

Open the report
Low`data_hash_` should be named `payload_hash_`The Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

`CatChainReceivedBlockImpl` has fields `data_`, `hash_`, `payload_` and `data_hash_`. `data_` field is unused. `data_hash_` in fact holds `payload_` hash.

Open the report
Low`deps` size is not limited for outgoing blocksThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

Catchain expects every full block received to have not more than `max_deps` dependencies. `max_deps` is 4 at this moment. However, when full block is sent to network, the `deps` size is not checked.

Open the report
Low`empty()` can be used instead of `!size()`The Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

```cpp=85 if (!blocks_.size()) { ``` `blocks_.empty()` can be used instead of `!blocks_.size()`.

Open the report
Low`map::emplace()` result can be used instead of `mThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

`map::emplace()` returns `std::pair<iterator,bool>`. `iterator` can be used to avoid the call to `map::find()`.

Open the report
Low`src_id` bounds are not checked before indexing `The Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

Indexing `blamed_sources_[src_id]` is done without validation of `src_id` correctness.

Open the report
Low`top_blocks_` element source bounds are not checkThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

```cpp=35 auto B = *top_blocks_.get_random(); CHECK(B != nullptr); top_blocks_.remove(B->hash()); if (B->source() == sources_.size() || !blamed_sources_[B->source()]) { ``` The code allows `B->source() == sources_.size()`, however, all the insertions to `top_blocks_` ensure the valid `src_`.

Open the report
Low`validate_dep_sync()` is never usedThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

`CatChainReceiverSourceImpl::validate_dep_sync()` is never used. `CatChainReceiverImpl::validate_block_sync(dep)` is used instead.

Open the report
Low`vector::reserve()` can minimize relocationsThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

The resulting size of `ids` vector is known in advance. Using of `vector::push_back()` leads to unnecessary relocations.

Open the report
Show 10 more
LowCatchain hangs if can't `td::RocksDb::destroy()`The Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

`CatChainReceiverImpl::destroy()` is supposed to stop trying after 10 failed attempts. However, the counter is not incremented - it will try endlessly. The same problem affects also `validator/db/archive-slice.cpp` (out of audit scope).

Open the report
LowMagic numbersThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

Magic numbers are used directly in code.

Open the report
LowPointer dereferenced before checkThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

```cpp=568 B->written(); CHECK(B); ``` The pointer `B` is dereferenced before it is checked.

Open the report
LowPointer is not checked before dereferencing in `sThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

The code assumes `dst` argument is valid and source `S` is non-zero. No check is performed before dereferencing.

Open the report
LowRedundant StatementsThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

The linked statement does not affect the functionality of the codebase. Both `r` and `my_vt[i] - vt[i]` are checked to be positive.

Open the report
LowThe code assumes the hash is 32 bytes longThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

```cpp=283 td::BufferSlice raw_data{32}; raw_data.as_slice().copy_from(as_slice(id)); ``` Magic number 32 assumes the hash value fits 32 bytes.

Open the report
LowTypoThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

"syncronize" is supposed to be "synchronize".

Open the report
LowUnmodified arguments should be declared as `constThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

If the function doesn't modify the argument, it should accept it as `const *` or `const &`. ```cpp=362 td::Status CatChainReceivedBlock::pre_validate_block(CatChainReceiver *chain, tl_object_ptr<ton_api::catchain_block> &block, td::Slice payload) { ``` This and some other functions don't modify the arguments. Methods that don't modify the object state should be declared as `const`. If cycle doesn't modify the container elements, the variable `X` should be declared as `const`: ```cpp=400 for (auto &X : block->data_->deps_) { ```

Open the report
LowUnnecessary structures copyingThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

In many functions non-trivial arguments are passed by value. This leads to unnecessary copying. Non-trivial arguments are `PublicKeyHash`, `CatChainSessionId`, `td::Slice`, `td::SharedSlice` and others.

Open the report
LowVariable name `l` is not recommendedThe Open Network - Audit 1 (Phase 2) · CertiK · 1 Aug 2022Fixed

It is not recommended to use `l`, `o` and some other variable names for better code readability.

Open the report

Contracts

No deployed address is recorded for these audits.

The reports name a repository or files. Open a report to see its scope.

The repositories and files the reports name

Show this on your site

Is this your project? Show this record on your own website. The label states what the record holds, links to this page and updates by itself. It is free and needs no sign-in.

Content

Facts

Automatic: the three strongest facts of this project’s own record (its last audit and two more), highlighted. They update with the record. Picking a fact turns Automatic off.

Fixed as
Language

Style

Layout
Theme
Accent
Corners

Format

Size
Date
Embed as
HTML
<head>
<script src="https://widget.trustblock.run/project-widget.min.js" defer></script>
</head>
<body>
<div
data-tb-project-widget
data-tb-project-slug="the-open-network"
></div>
</body>

Paste the code where the label should appear. It uses no API credit and updates by itself.

Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.

Tell us