elementsinteractive/twyn

GitHub: elementsinteractive/twyn

一款针对依赖名称的 typosquatting 攻击防护安全工具。

Stars: 55 | Forks: 6

# Twyn ![Build Status](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/f0dd6c3d53042316.svg) [![PyPI version](https://img.shields.io/pypi/v/twyn)](https://pypi.org/project/twyn/) [![Docker version](https://img.shields.io/docker/v/elementsinteractive/twyn?label=DockerHub&logo=docker&logoColor=f5f5f5)](https://hub.docker.com/r/elementsinteractive/twyn) [![Python Version](https://img.shields.io/badge/python-%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue?logo=python&logoColor=yellow)](https://pypi.org/project/twyn/) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![License](https://img.shields.io/github/license/elementsinteractive/twyn)](LICENSE) ## 目录 - [Overview](#overview) - [Quickstart](#quickstart) - [Using `Twyn` as a cli tool](#using-twyn-as-a-cli-tool) - [Installation](#installation) - [Docker](#docker) - [CLI Options Reference](#cli-options-reference) - [Run](#run) - [JSON Format](#json-format) - [Using `Twyn` as a library](#using-twyn-as-a-library) - [Logging level](#logging-level) - [Configuration](#configuration) - [Allowlist](#allowlist) - [Dependency files](#dependency-files) - [Check dependencies introduced through the CLI](#check-dependencies-introduced-through-the-cli) - [Selector method](#selector-method) - [Configuration file](#configuration-file) - [Cache](#cache) ## 概述 `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](https://en.wikipedia.org/wiki/Typosquatting). 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](#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. ## 快速开始 ### 将 Twyn 用作 CLI 工具 #### 安装 `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](https://hub.docker.com/r/elementsinteractive/twyn). Use it like so: ``` docker pull elementsinteractive/twyn:latest docker run elementsinteractive/twyn --help ``` ##### CLI 选项参考 | 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. | #### 运行 **Usage Example:** ``` twyn run ``` or get help with ``` twyn run --help ``` #### JSON 格式 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. ### 将 Twyn 用作库 #### 安装 `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)}]") ``` #### 日志级别 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) ``` ## 配置 ### 允许列表 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 ``` To remove it simply: ``` twyn allowlist remove ``` ### 依赖文件 To specify a dependency file through the command line run: ``` twyn run --dependency-file ``` 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) ### 通过 CLI 检查引入的依赖 You can also check a dependency by entering it through the command line: ``` twyn run --dependency ``` It does accept multiple dependencies at a time: ``` twyn run --dependency --dependency ``` When this option is selected, no dependency file is checked. ### 选择器方法 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. To select a specific operational mode through the CLI use the following command ``` twyn run --selector-method ``` ### 配置文件 You can 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 ``` 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" } ] } ``` ### 缓存 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 ```
标签:CI/CD 安全, CLI 工具, Docker, PyPI, Python 工具, Ruff, Twyn, typo squatting, URL发现, 依赖安全, 依赖扫描, 依赖注入, 依赖混淆, 依赖混淆攻击, 包名校验, 包名相似性检测, 安全检测, 安全防御评估, 开源框架, 恶意包, 持续集成, 数据投毒防御, 模型提供商, 请求拦截, 软件供应链, 逆向工具