Learn how to introduce threat modeling in your team and take care of security before it's too late.

Thanks to this guide you will:

  • reduce the number of security bugs in your code,
  • use the audit time effectively,
  • understand the concept of threat modeling and its importance,
  • learn why you should carry them out,

but most of all, you'll be ready to conduct your first threat modeling session!

As a developer, the security of the project is in your hands. Be security-centric through the process, and become a security champ.

During conversations with clients, we always try to get to know their problems in depth, and we listen carefully to what they think they result from.

These are very valuable comments, thanks to which we are able not only to diagnose the problem much better but also start working on a solution.

A common problem is thinking too late about security.

Smart contract audit before the release

Many projects come into contact with security only before the release. They focus so heavily on product building that they leave the discovering vulnerabilities and implementing additional protections for the end. Audit, patch, and that’s it. Some of them, having a better understanding of responsibility, will also be tempted to participate in the bug bounty program.

Is that all we can do for users to keep them secure?

No, all of this is just an absolute minimum. If you are reading this article, you feel that something more can be done… and - you are absolutely right.

You are right!

Why is threat modeling important?

What if I tell you that you are not only able to significantly increase the security of your project by some small changes in your process, but also reduce the costs associated with time-consuming corrections after audits?

Sounds good? Then start doing threat modeling sessions with your team. It's really not worth leaving it to the last minute and having a ton of work to do when deadlines are tight.

A much smarter approach is to build a project based on good security assumptions. By working closely with many great teams, we know it's possible. Sometimes they just need guidance and advice on HOW and WHEN to do it.

How to perform threat modeling within a team

1. Explain what threat modeling is

Threat modeling is nothing else, but brainstorming. An exercise to spot potential threats at a very early stage. Take on the role of this evil hacker for a moment. In addition to the valuable contribution, it is simply great fun.ssss

2. Tell them why you want to introduce threat modeling and what it is for

Thanks to this, we will realistically increase the security of our project and reduce the costs associated with introducing post-audit fixes, which sometimes might even require redesigning the protocol. Our users will be sure that their security is our priority.

3. Introduce the rules

It is very important that each participant feels comfortable. If you want to use your colleagues' knowledge, don't let their ideas be criticized. All topics discussed should stay in the group. Shortcomings and omissions should be addressed, BUT not stigmatized. People must not be afraid to admit they were wrong or missed something, they all must feel at ease, otherwise, they may hide important information to protect themselves from consequences.

4. Select the session object

Anything can be the subject of the session. Every slight change in the code, new feature, update process, next integration, or even a whole project architecture. That’s up to you.

5. Gather people who have knowledge about the session object

To find numerous threats, it is worth exploring various perspectives and gathering experience. During the session, not only developers’ colleagues are useful. Architects and business people have great knowledge and are able to determine what might have a negative impact on the project’s success. Keep the balance, do not invite the whole team for all sessions. Some of them can be done even by one developer.

6. Start by drawing the architectural diagram

You can use a blackboard, sheet of paper, or application. It does not matter. It is important that you have a place to accurately reproduce your idea. Furthermore, it is not worth getting into details, usually the most important are:

  • components - smart contracts,
  • business core functionalities - the most important functions of a smart contract that are used in the main business flow,
  • roles - all users participating in the system with various rights (governance, owner, user, team member, etc.).

Keep it simple.

Architectual diagram
Architectual diagram

7. Determine the potential attacker

When the diagram is ready, start thinking together about possible attack vectors and threats. Where can they come from? From which side can the component be attacked?

  • What roles are there in the system?
  • Who potentially might not want you to succeed?
  • Which role do most people have access to?

The shorthand term might be to consider everyone as potential attackers. Yes, even team members and DAO, they too can be compromised, and we don't estimate the probability of it yet.

Architectual diagram with attackers
Architectual diagram with attackers

8. Think about what the attacker will want to achieve

Well, as you already know who might want to attack your project. Now the question is what for? Steal your users' funds? Make your project unavailable? Read some secret data? Or just harm your reputation in any way possible? Think about questions such as:

  • What from our project has value in the market?
  • What's the worst that could happen to our project?
  • In what case are we losing money?

Thanks to this, you will know exactly what should be important to you. Determine the key assets that you need to protect.

Architectual diagram with goals
Architectual diagram with goals

9. Identify how attackers can do that

You know who can attack your project, and you know what they want to achieve - it's time to play the hacker and think about how you would try to achieve the goals set in the previous point.

  • Which functions handle token transfer?
  • Do we check who is calling the functions?
  • What if the component we integrate with starts sending incorrect data?
  • Are we sure about the arithmetic operation result?
  • What if the user has a significant amount of tokens?
  • Can I call functions in a different order than expected?
  • What if the private key of one of the team members is compromised?
  • ...

Make this brainstorm on every component and every function. Do not check whether these threats are real and reflected in the code. Write everything on the diagram. In the worst case, you'll expand your database of known threats.

Architectual diagram with threats
Architectual diagram with threats

10. Write down discovered threats

After you have gone through all the components, write down discovered threats. You can use a table to have a place where you can easily decide what to do with them later.

IDThreatPriorityAction
1Increase user balance without a deposit
2Withdraw more than the user's balance contains
3Withdraw another user's funds
4Compromise of a team member's private key
5Invalid data format by oracle updates
N...

11. Prioritize

There can be many threats and handling all of them might be time-consuming. It is worth considering which of them is the most important. This table will help you with that - the higher the overall risk severity, the higher your priority should be.

Overall risk severity
Impact on riskHIGHCRITICALMAJORMEDIUM
MEDIUMMEDIUMMEDIUMMINOR
LOWMINORMINORINFO
LOWMEDIUMHIGH
Exploitation conditions

12. Decide what to do with threats

Each threat must be handled. You can choose from the following options:

  • Accept the risk - not all the vulnerabilities need to be fixed, and not all the threats will eventually turn out to be significant. If something is very unlikely or irrelevant from your point of view - you can accept the risk.
  • Delegate - Some of the risks arising from the necessary use of third-party resources. A great example of this is using AWS to host your platform. In many cases, you may find AWS responsible for the availability of your platform.
  • Communicate - Some of the detected threats, the risk of which we can accept if disclosed, may harm the company's image. In these cases, you can accept the risk, but you should also send a message stating that it is a deliberate decision so that users have no doubts. This could be a documentation entry, a tweet, or a terms and conditions entry.
  • Verify - If you are not sure if this threat exists, check it. Use your team or a professional auditing firm for this. If it’s confirmed, you will have to decide again how to handle it.
  • Fix - When you are certain that there is a vulnerability with real risk, there is nothing else to do but remove it. In some cases, this may require rapid intervention if threat modeling was organized late. However, if you did it at the beginning of the process as recommended - you can do it without a rush.
  • Prevent - If the threat is real and you are at the initial stage of the project. Address potential vulnerabilities by providing developers with detailed threat information, such as checklists or tests. Instill a proactive, security-conscious mindset throughout the development process.
IDThreatPriorityAction
1Increase user balance without a depositHighPrevent
2Withdraw more than the user's balance containsHighPrevent
3Withdraw another user's fundsHighPrevent
4Compromise of a team member's private keyMediumVerify
5Invalid data format by oracle updatesLowAccept the risk
N...

13. Write tests

If you choose to Verify, Fix or Prevent, it is worth trying to convert this scenario to a unit test. At the moment, the name of the scenario is enough. You don’t have to implement all the tests. Each time someone runs them, they will remember the existing threats that you want to avoid. Moreover, in some cases, you will be able to automatically confirm that the vulnerability does not exist.

Foundry template:

1contract TestThreats is Test { 
2  // Should not be possible to increase user balance without a deposit
3  function testIncreasingBalance() public {
45  }
6 // Should not be possible to withdraw more than the user's balance contains
7  function testWithdrawingMore() public {
89  }
10 // Should not be possible to withdraw another user's funds
11  function testWithdrawingAnotherUserFunds() public {
1213  }
14}

Hardhat example:

1describe("Preventing threats", () => {
2    it("Should not be possible to increase user balance without a deposit", async function () {
34    });
5    it("Should not be possible to withdraw more than the user's balance contains", async function () {
67    });
8    it("Should not be possible to withdraw another user's funds", async function () {
910    });
11});

14. Take further action

Delegate responsibilities who should do what, and share the work. It's also a good idea to save your materials and build your own threat databases

When to perform threat modeling within a team?

The simple answer to that question is every time you want to make some changes, or you are designing something new.

You don’t need a code for that. You don't need a whole team for it, you even don't always have to do it with anyone at all. BUT you always have to ask yourself whether a particular change may have any impact on security. And if the answer is yes - you need to carry out at least a short threat modeling session by yourself.

Then, you will introduce this change by being aware of potential threats. That’s simple, but a huge change. We promise that if you do this, there will be much fewer vulnerabilities in your project code.

High five

First session

The first threat modeling session is very important. If we do it for the entire architecture of the project, it is not only time-consuming but can also be a challenge. This requires knowledge of many attack vectors and keeping the appropriate level of abstraction.

Let's do this together. We will be happy to help you by conducting the first session with your team. After such a session, you will not only know exactly how it should look but also get great materials to not start from scratch.

If you are interested in such a session, contact us, and we will take care of the rest.

Paweł Kuryłowicz

Paweł Kuryłowicz

Managing Partner & Smart Contract Security Auditor

About the author

Co-author of SCSVS and White Hat. Professionally dealing with security since 2017 and since 2019 contributing to the crypto space. Big DeFi fan and smart contract security researcher.

View all posts (9)