Learn how to check if anyone can become your contract's owner.
In this tutorial, you'll learn how to identify and prevent the ownership hijack attack — a vulnerability that lets malicious actors seize control of a contract or access privileged administrative functions.
You'll start by creating a deliberately vulnerable TON smart contract, then use the TSA Blueprint plugin to detect the security flaw. This practical approach shows how vulnerabilities can appear in code and how automated tools can catch them before deployment.
By the end, you'll be able to:
To see the TON ownership hijack checker in action, we'll first create a smart contract with a deliberate vulnerability — one that would allow an attacker to take over contract ownership.
Follow these steps to set up the project and implement the flawed contract.
Before you begin, make sure you meet all the requirements for working with Blueprint. You can find the details in the Blueprint documentation.
Once everything is set up, create a new project by running:
npm create ton@latestYou'll be prompted to enter:
OwnerHijackDemoVulnerableContractAn empty contract (Tolk)We'll use this empty contract as a starting point to build our intentionally vulnerable example.
Enter the generated directory:
cd OwnerHijackDemoThe generated empty contract is located at contracts/vulnerable_contract.tolk.
Open this file and replace its contents with the following:
const OP_CHANGE_OWNER = 0
struct Storage { owner: address }
fun Storage.load() { return Storage.fromCell(contract.getData()); }
fun Storage.save(self) { contract.setData(self.toCell()); }
get fun getOwner(): address { return Storage.load().owner; }
fun setOwner(newOwner: address) { Storage { owner: newOwner }.save(); }
fun onInternalMessage(in: InMessage) {
var msgBody = in.body;
var opcode: int = msgBody.loadUint(32);
if (opcode == OP_CHANGE_OWNER) {
setOwner(msgBody.loadAddress());
}
}
Security Issue: This contract contains a critical vulnerability — it lacks authorization checks. Any user can send a message to change the owner however they like, including assigning the owner to oneself!
To detect and analyze security vulnerabilities like the one in our contract, we'll use the TSA plugin.
Refer to TSA Blueprint Plugin Installation Guide for instructions.
Now let's analyze our vulnerable contract. Run the TSA owner-hijack checker with the following command:
yarn blueprint tsa owner-hijack-check -m getOwner -c VulnerableContractBy default, built-in checkers are interactive: TSA asks for confirmation twice — first before preparation and timeout calculation, and then again before the analysis starts.
If you want to skip both prompts, add --no-interactive.
When you execute this command, TSA performs symbolic analysis of your contract. This means it systematically explores different execution paths to identify any that could lead to vulnerabilities.
Here's what the command options mean:
owner-hijack-check refers specifically to the TON ownership hijack checker — a specialized analyzer that searches only for execution paths where the owner of the contract might change.-m getOwner specifies a get-method that retrieves the owner.-c VulnerableContract specifies the name of the contract to analyze.You can customize the analysis with additional options. To see all available parameters, run:
yarn blueprint tsa owner-hijack-check --help
The analysis process consists of:
When vulnerabilities are found, the tool reports them along with detailed steps to reproduce each vulnerable execution path.
After a few moments, you'll see a vulnerability report similar to this:
⚠️ Vulnerability found!
Summary path: tsa/reports/run-<id>/summary.txt
Typed input: tsa/reports/run-<id>/typed-input.yaml
SARIF with full information: tsa/reports/run-<id>/report.sarif
The generated files are stored in tsa/reports/run-<id>:
tsa
└── reports
└── run-<id>
├── contract-data.boc
├── message-body.boc
├── report.sarif
├── summary.txt
├── tsa-reproduce-config.json
└── typed-input.yaml
There are two options for proceeding:
We'll explore both approaches starting with manual investigation. The automated reproduction will be described in Section 4 of this tutorial.
Let's break down what each component of the report means:
summary.txt): A concise overview of the vulnerability — this is what was displayed in your terminal.typed-input.yaml): The recommended file for investigation. It contains the typed representation of the reproducing message body and contract data in one place.message-body.boc, contract-data.boc): The exact message body and contract data that reproduce the vulnerability.report.sarif): A standardized format for static analysis results. This file contains comprehensive details about analyzed execution paths. For most use cases, you won't need to examine this file directly.The checker has successfully identified our missing authorization check — anyone can change the owner of the contract.
Before proceeding, ensure you have:
For this tutorial, you'll need at least 1.5 TestNet TONs to cover deployment and transaction fees.
The vulnerability report includes a command to reproduce the issue on-chain:
To reproduce the vulnerability on the blockchain, run:
> yarn blueprint tsa reproduce --config tsa/reports/run-<id>/tsa-reproduce-config.json
This configuration file, tsa-reproduce-config.json, is generated by tsa owner-hijack-check and contains all necessary data for the reproduction process.
yarn blueprint tsa reproduce --config tsa/reports/run-<id>/tsa-reproduce-config.jsonYou'll be prompted to:
testnetNext, you'll deploy the contract to TestNet. When asked:
noAnswer
noissues a fresh deployment of a contract under test that will receive a message that triggers the found vulnerability. This is outside of the scope for this tutorial, but you can also send a reproduction message to an already deployed contract. To do this, answer "yes" to this question and proceed according to prompts. The data of the input contract will be checked, so don't be afraid to type the wrong address — the plugin will report the wrong contract state.
0.5 TONs. This is the money you are about to withdrawYou'll then specify how much you're willing to spend on reproducing the vulnerability:
0.5 TONsTSA will now:
Once confirmed, you'll receive a transaction ID.
You can use the following explorers to view the transaction (TonViewer is recommended for better debugging tools):
TonViewer:
https://testnet.tonviewer.com/transaction/<transaction_id>
TonScan:
https://testnet.tonscan.org/tx/<transaction_id>
You can verify that the owner of the contract was changed.
For deeper analysis, you can use:
Since we already understand this vulnerability (missing authorization), extensive investigation isn't necessary — but these tools are useful for analyzing more complex issues.
The vulnerability stems from missing authorization checks. To fix it, we need to add authorization logic: check the sender of the message for having the right to change the owner (or, in other words, check that the sender is the owner).
Update contracts/vulnerable_contract.tolk with the following corrected code:
const OP_CHANGE_OWNER = 0
struct Storage { owner: address }
fun Storage.load() { return Storage.fromCell(contract.getData()); }
fun Storage.save(self) { contract.setData(self.toCell()); }
get fun getOwner(): address { return Storage.load().owner; }
fun setOwner(newOwner: address) { Storage { owner: newOwner }.save(); }
fun onInternalMessage(in: InMessage) {
var msgBody = in.body;
var opcode: int = msgBody.loadUint(32);
if (opcode == OP_CHANGE_OWNER) {
assert(in.senderAddress == getOwner()) throw 501; // added check
setOwner(msgBody.loadAddress());
}
}
Re-run the TSA ownership hijack checker to confirm the vulnerability is resolved:
yarn blueprint tsa owner-hijack-check -m getOwner -c VulnerableContractExpected Result: The tool should report that no vulnerabilities were found, confirming our security fix is effective.
In this tutorial, you've learned how to use the TSA ownership hijack checker to identify and fix a critical smart contract vulnerability. You've successfully:
The TSA plugin offers additional security checkers beyond ownership hijack analysis — explore them with yarn blueprint tsa --help or read our other tutorials to further strengthen your contract security.
Happy secure coding!