Skip to main content

Security tool against dependency typosquatting attacks

Project description

Twyn

Build Status PyPI version Docker version Python Version Ruff License

Table of Contents

Overview

Twyn is a security tool that compares the name of your dependencies against a set of the most popular ones, in order to determine if there is any similarity between them, preventing you from using a potentially illegitimate one. In short, Twyn protects you against typosquatting attacks.

It works as follows:

  1. Either choose to scan the dependencies in a dependencies file you specify (--dependency-file) or some dependencies introduced through the CLI (--dependency). If no option was provided, it will try to find a dependencies file in your working path. It will try to parse all the supported dependency files that it finds. To know which files are supported head to the Dependency files section.
  2. If the name of your package name matches with the name of one of the most well known packages, the package is accepted.
  3. If the name of your package is similar to the name of one of the most used packages, Twyn will prompt an error.
  4. If your package name is not in the list of the most known ones and is not similar enough to any of those to be considered misspelled, the package is accepted. Twyn assumes that you're using either a not so popular package (therefore it can't verify its legitimacy) or a package created by yourself, therefore unknown for the rest.

Quickstart

Using twyn as a CLI tool

Installation

Twyn is available on PyPi repository, you can install it by running

pip install twyn[cli]

Docker

Twyn provides a Docker image, which can be found here.

Use it like so:

docker pull elementsinteractive/twyn:latest
docker run elementsinteractive/twyn --help
CLI Options Reference
Option / Argument Type / Values Description
--config str (path) Path to configuration file (twyn.toml or pyproject.toml by default).
--dependency-file str (path) Dependency file to analyze. Supported: requirements.txt, poetry.lock, uv.lock, etc.
--dependency str (multiple allowed) Dependency to analyze directly. Can be specified multiple times.
--selector-method all, first-letter, nearby-letter Method for selecting possible typosquats.
--package-ecosystem pypi, npm, dockerhub Package ecosystem for analysis.
-v flag Enable info-level logging.
-vv flag Enable debug-level logging.
--no-cache flag Disable use of trusted packages cache. Always fetch from the source.
--no-track flag Do not show the progress bar while processing packages.
--json flag Display results in JSON format. Implies --no-track.
-r, --recursive flag Scan directories recursively for dependency files.

Run

Usage Example:

twyn run <OPTIONS>

or get help with

twyn run --help

JSON format

If you want your output in JSON format, you can run Twyn with the following flag:

  twyn run --json

This will output:

 {"results":[{"errors":[{"dependency":"my-package","similars":["mypackage"]}],"source":"manual_input"}]}

If Twyn was run by manually giving it dependencies (with --dependency), the source will be manual_input.

In any other case (when dependencies are parsed from a file), the source will be the path to the dependencies file. One entry will be created for every source.

Using Twyn as a library

Installation

Twyn also supports being used as 3rd party library for you project. To install it, run:

pip install twyn

Example usage in your code:

from twyn import check_dependencies

typos = check_dependencies()

for typo in typos.errors:
  print(f"Dependency:{typo.dependency}")
  print(f"Did you mean any of [{','.join(typo.similars)}]")
  

Logging level

By default, logging is disabled when running as a 3rd party library. To override this behaviour, you can:

logging.basicConfig(level=logging.INFO)
logging.getLogger("twyn").setLevel(logging.INFO)

Configuration

Allowlist

It can happen that a legitimate package known by the user raises an error because it is too similar to one of the most trusted ones. Imagine that you are using internally a package that you developed called reqests. You can then add this packages to the allowlist, so it will not be reported as a typo:

twyn allowlist add <package>

To remove it simply:

twyn allowlist remove <package>

Dependency files

To specify a dependency file through the command line run:

twyn run --dependency-file <file path>

The following dependency file formats are supported:

  • requirements.txt
  • poetry.lock (<1.5, >=1.5)
  • uv.lock
  • package-lock.json (v1, v2, v3)
  • yarn.lock (v1, v2)
  • pnpm-lock.yaml (v9)
  • Dockerfile
  • docker-compose.yml, docker-compose.yaml, compose.yml, compose.yaml (v1, v2, v3)

Check dependencies introduced through the CLI

You can also check a dependency by entering it through the command line:

twyn run --dependency <dependency>

It does accept multiple dependencies at a time:

twyn run --dependency <dependency> --dependency <another_dependency>

When this option is selected, no dependency file is checked.

Selector method

You can choose between different operational modes. These will determine which dependencies from the trusted set the analyzed dependency can be a typosquat of.

  • all: Default option. It is the most exhaustive mode. It will check your package names against all the trusted ones without any assumption.
  • nearby-letter: It will assume a typo on the first letter of the dependency is possible, but improbable if letters are farther apart in the keyboard. Specifically, it will compare the analyzed dependency against dependencies whose first letter is one step away in an ANSI keyboard layout.
  • first-letter: It will assume a typo on the first letter is very improbable, and won't compare the analyzed dependency against dependencies with a different first letter.

[!NOTE] Selecting an option is a matter of preference: all is the slowest, but will have more false positives and less false negatives; while first-letter is the fastest, but it will have less false positives and more false negatives.

To select a specific operational mode through the CLI use the following command

twyn run --selector-method <method>

Configuration file

You can save your configurations in a .toml file, so you don't need to specify them everytime you run Twyn in your terminal.

By default, it will try to find a twyn.toml file in your working directory when it's trying to load your configurations. If it does not find it, it will fallback to pyproject.toml. However, you can specify a config file as follows:

twyn run --config <file>

All the configurations available through the command line are also supported in the config file.

[tool.twyn]
dependency_file="/my/path/requirements.txt" # it can be either a string or a list of strings
selector_method="first_letter"
logging_level="debug"
allowlist=["my_package"]
pypi_source="https://mirror-with-trusted-dependencies.com/file-pypi.json"
npm_source="https://mirror-with-trusted-dependencies.com/file-npm.json"
dockerhub_source="https://mirror-with-trusted-dependencies.com/file-dh.json"

The file format for each reference is as follows:

{
  "date": "string (ISO 8601 format, e.g. 2025-09-10T14:23:00+00)",
  "packages": [
    { "name": "string" }
  ]
}

Cache

By default, Twyn will cache the list of trusted packages to a cache file, within the .twyn directory that will be automatically created.

You can disable the cache by adding the following flag:

  twyn run --no-cache

In which case it will download again the list of trusted packages, withou saving them to the cache file.

Cache file is valid for 30 days, after that period it will download again the trusted packages list.

To clear the cache, run:

  twyn cache clear

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

twyn-6.1.0.tar.gz (32.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

twyn-6.1.0-py3-none-any.whl (51.6 kB view details)

Uploaded Python 3

File details

Details for the file twyn-6.1.0.tar.gz.

File metadata

  • Download URL: twyn-6.1.0.tar.gz
  • Upload date:
  • Size: 32.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.8.22

File hashes

Hashes for twyn-6.1.0.tar.gz
Algorithm Hash digest
SHA256 b65b30aff7435acbf19e0497142213ff40228e127e60fef201812cce172a8412
MD5 4ea9107a7b2f1ec32db150922b3791d2
BLAKE2b-256 0edb783c898e36d44d65257dbcad259009024246446ccdd2f3c96787be218ef9

See more details on using hashes here.

File details

Details for the file twyn-6.1.0-py3-none-any.whl.

File metadata

  • Download URL: twyn-6.1.0-py3-none-any.whl
  • Upload date:
  • Size: 51.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.8.22

File hashes

Hashes for twyn-6.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1084e166196d9baed46084bb34a9b7f965122a95a97ffc479fa26caf039c93db
MD5 2ac95091211e9416d96cfe3b8548eea1
BLAKE2b-256 b141ddd9047d4b30ab41bb3af4ccc053f5337c76279aa2858183acfebee4a246

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page