dirty-waters


Namedirty-waters JSON
Version 0.70.0 PyPI version JSON
download
home_pageNone
SummaryAutomatically detect software supply chain smells and issues
upload_time2025-03-11 16:26:47
maintainerNone
docs_urlNone
authorNone
requires_python>=3.12
licenseMIT
keywords software supply chain ssc dependencies npm
VCS
bugtrack_url
requirements attrs cattrs certifi charset-normalizer exceptiongroup GitPython idna markdown-it-py numpy pandas platformdirs pytest python-dateutil pytz PyYAML requests requests-cache six tabulate tqdm typing_extensions tzdata url-normalize urllib3 xmltodict
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # dirty-waters

Dirty-waters automatically finds software supply chain issues in software projects by analyzing the available metadata of all dependencies, transitively.

Reference: [Dirty-Waters: Detecting Software Supply Chain Smells](http://arxiv.org/pdf/2410.16049), Technical report 2410.16049, arXiv, 2024.

By using `dirty-waters`, you identify the shady areas of your supply chain, which would be natural target for attackers to exploit.

`dirty-waters`'s static analyses report the following smells:

- Dependencies with no/invalid\* link to source code repositories (high severity)
- Dependencies with no tag/commit SHA for release, impossible to have reproducible builds (medium severity)
- Deprecated Dependencies (medium severity)
- Depends on a fork (low severity), **disabled by default**
- Dependencies without/with invalid code signature (medium severity)
- Dependencies with no build attestation (low severity)

\* We consider invalid links to be links which do not return a 200 status code.
Furthermore, if the dependencies are not hosted on GitHub, not all checks will be possible to be made (e.g., code signature).

As for its differential analyses, `dirty-waters` reports the following smells:

- Dependencies with code signature changes (high severity)
- Downgraded dependencies (medium severity)
- Dependencies with commits made by both new authors and reviewers (medium severity)
- Dependencies with commits approved by new reviewers (medium severity)
- Dependencies with new contributors (low severity)

Additionally, `dirty-waters` gives a supplier view on the dependency trees (who owns the different dependencies?)

`dirty-waters` is developed as part of the [Chains research project](https://chains.proj.kth.se/).

## Installation

### Installation via pip

You can install `dirty-waters` via pip:

```bash
pip install dirty-waters
# or
pipx install dirty-waters
```

Set up the GitHub API token (or with a `.env` file):

```bash
export GITHUB_API_TOKEN=<your_token>
```

## Usage

### Command line

Run the tool using the following command structure:

```
# analyzing the software supply chain of Maven project INRIA/spoon
$ dirty-waters -p INRIA/spoon -pm maven
```

All configuration options

```
usage: main.py [-h] -p PROJECT_REPO_NAME [-v RELEASE_VERSION_OLD]
               [-vn RELEASE_VERSION_NEW] [-d] [-n] -pm
               {yarn-classic,yarn-berry,pnpm,npm,maven}
               [--pnpm-scope PNPM_SCOPE] [--debug] [--config CONFIG]
               [--gradual-report GRADUAL_REPORT | --no-gradual-report]
               [--check-source-code] [--check-release-tags]
               [--check-deprecated] [--check-forks] [--check-provenance]
               [--check-code-signature] [--check-aliased-packages]

options:
  -h, --help            show this help message and exit
  -p PROJECT_REPO_NAME, --project-repo-name PROJECT_REPO_NAME
                        Specify the project repository name. Example:
                        MetaMask/metamask-extension
  -v RELEASE_VERSION_OLD, --release-version-old RELEASE_VERSION_OLD
                        The old release tag of the project repository.
                        Defaults to HEAD. Example: v10.0.0
  -vn RELEASE_VERSION_NEW, --release-version-new RELEASE_VERSION_NEW
                        The new release version of the project repository.
  -d, --differential-analysis
                        Run differential analysis and generate a markdown
                        report of the project
  -n, --name-match      Compare the package names with the name in the in the
                        package.json file. This option will slow down the
                        execution time due to the API rate limit of code
                        search.
  -pm {yarn-classic,yarn-berry,pnpm,npm,maven}, --package-manager {yarn-classic,yarn-berry,pnpm,npm,maven}
                        The package manager used in the project.
  --pnpm-scope PNPM_SCOPE
                        Extract dependencies from pnpm with a specific scope
                        using 'pnpm list --filter <scope> --depth Infinity'
                        command. Configure the scope in tool_config.py file.
  --debug               Enable debug mode.
  --config CONFIG       Path to configuration file (JSON)
  --gradual-report GRADUAL_REPORT
                        Enable/disable gradual reporting (default: true)
  --no-gradual-report   Disable gradual reporting (deprecated, use --gradual-
                        report=false instead)

smell checks:
  --check-source-code   Check for dependencies with no link to source code
                        repositories
  --check-release-tags  Check for dependencies with no tag/commit sha for
                        release
  --check-deprecated    Check for deprecated dependencies
  --check-forks         Check for dependencies that are forks
  --check-provenance    Check for dependencies with no build attestation
  --check-code-signature
                        Check for dependencies with missing/invalid code
                        signature
  --check-aliased-packages
                        Check for aliased packages
```

Reports are gradual by default: that is, only the highest severity smell type with issues found within this project is reported. You can disable this feature, and get a full report,
by setting the --gradual-report flag to false.

1. Static analysis:

```bash
# If manually cloned
python3 main.py -p MetaMask/metamask-extension -pm yarn-berry
# If installed via pip
dirty-waters -p MetaMask/metamask-extension -pm yarn-berry
```

- Example output: [Static Analysis Report Example](example_reports/static_analysis_report_example.md)

2. Differential analysis:

```bash
# If manually cloned
python3 main.py -p MetaMask/metamask-extension -v v11.11.0 -vn v11.12.0 -d -pm yarn-berry
# If installed via pip
dirty-waters -p MetaMask/metamask-extension -v v11.11.0 -vn v11.12.0 -d -pm yarn-berry
```

- Example output: [Differential Analysis Report Example](example_reports/differential_analysis_report_example.md)

Notes:

- `-v` should be the version of GitHub release, e.g. for [this release](https://github.com/MetaMask/metamask-extension/releases/tag/v11.1.0), the value should be `v11.11.0`, not `Version 11.11.0` or `11.11.0`.
- When using `-d` for differential analysis, `-vn` must be specified.

### Development

To set up `dirty-waters`, follow these steps:

1. Clone the repository:

```bash
git clone https://github.com/chains-project/dirty-waters.git
cd dirty-waters
```

2. Set up a virtual environment and install dependencies:

```bash
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cd tool
```

In alternative to virtual environments, you may also use the Nix flake present in this repository.

3. Set up the GitHub API token (ideally, in a `.env` file):

```bash
export GITHUB_API_TOKEN=<your_token>
```

### Configuration

You can set the tool's configuration through a JSON file, which can be then passed to the tool using the `--config` flag.
At the moment, we have configuration support to ignore specific packages from the analysis.

An example configuration file:

```json
{
  "ignore": ["package_name_1@versionx.y.z", "package_name_2@versiona.b.c"]
}
```

Note that for cases where a package is aliased, we check for the original package name, not the aliased one:
i.e., if we alias the package `string-width` to `string-width-cjs`, we will check for `string-width@versionx.y.z`, not `string-width-cjs@versionx.y.z`.

### Continuous integration

See Github action at <https://github.com/chains-project/dirty-waters-action>

## Software Supply Chain Smell Support

`dirty-waters` currently supports package managers within the JavaScript and Java ecosystems. However, due to some constraints associated with the nature of the package managers, the tool may not be able to detect all the smells in the project. The following table shows the supported package managers and their associated smells, for static analysis:

| Package Manager | No Source Code Repository | Invalid Source Code Repository URL | No Release Tag | Deprecated Dependency | Depends on a Fork | No Build Attestation | No/Invalid Code Signature |
| --------------- | ------------------------- | ---------------------------------- | -------------- | --------------------- | ----------------- | -------------------- | ------------------------- |
| Yarn Classic    | Yes                       | Yes                                | Yes            | Yes                   | Yes               | Yes                  | Yes                       |
| Yarn Berry      | Yes                       | Yes                                | Yes            | Yes                   | Yes               | Yes                  | Yes                       |
| Pnpm            | Yes                       | Yes                                | Yes            | Yes                   | Yes               | Yes                  | Yes                       |
| Npm             | Yes                       | Yes                                | Yes            | Yes                   | Yes               | Yes                  | Yes                       |
| Maven           | Yes                       | Yes                                | Yes            | No                    | Yes               | No                   | Yes                       |

All package managers support every smell in the differential analysis scenario.

### Smell Check Options

By default, all supported checks for the given package manager are performed in static analysis.
You can specify individual checks using the following flags (note that if at least one flag
is passed, instead of all checks being performed, only the flagged ones will be):

- `--check-source-code`: Check for dependencies with no link to source code repositories
- `--check-release-tags`: Check for dependencies with no tag/commit sha for release
- `--check-deprecated`: Check for deprecated dependencies
- `--check-forks`: Check for dependencies that are forks
- `--check-provenance`: Check for dependencies with no build attestation
- `--check-code-signature`: Check for dependencies with no/invalid code signature

**Note**: The `--check-release-tags` and `--check-forks` flags require `--check-source-code` to be enabled, as release tags can only be checked if we can first verify the source code repository.

As an example of running specific checks:

```bash
dirty-waters -p MetaMask/metamask-extension -v v11.11.0 -pm yarn-berry --check-source-code --check-release-tags
```

This run will only check for dependencies with no link to source code repositories and dependencies with no tag/commit sha for release.

For **differential analysis**, it is currently not possible to specify individual checks -- all checks will be performed.

### Notes

#### Inaccessible Tags

Sometimes, the release version specified in a lockfile/pom/similar is not necessarily the same
as the tag used in the repository. This can happen for a variety of reasons. We have
compiled several tag formats which were deemed reasonable to lookup, if the exact tag
specified in the lockfile/pom/similar is not found. They come from a combination of [AROMA](https://dl.acm.org/doi/pdf/10.1145/3643764)'s
work and our own research on this subject.
These formats are the following:

<details> <summary>Tag formats</summary>

- `<tag>`
- `v<tag>`
- `r-<tag>`
- `release-<tag>`
- `parent-<tag>`
- `<package_name>@<tag>`
- `<package_name>-v<tag>`
- `<package_name>_v<tag>`
- `<package_name>-<tag>`
- `<package_name>_<tag>`
- `<repo_name>@<tag>`
- `<repo_name>-v<tag>`
- `<repo_name>_v<tag>`
- `<repo_name>-<tag>`
- `<repo_name>_<tag>`
- `<project_name>@<tag>`
- `<project_name>-v<tag>`
- `<project_name>_v<tag>`
- `<project_name>-<tag>`
- `<project_name>_<tag>`
- `release/<tag>`
- `<tag>-release`
- `v.<tag>`
- `p1-p2-p3<tag>`

As examples of what `package_name`, `repo_name`, and `project_name` could be, `maven-surefire`
is an interesting dependency:

- `maven-surefire-common` is the package name
- `maven-surefire` is the repo name (we remove the owner prefix)
- `surefire` is the project name

In particular, there are many `maven-*` dependencies whose tags follow these last conventions.

</details>

Note than this does not mean that if `dirty-waters` does not find a tag, it doesn't exist:
it means that it either doesn't exist, or that its format is not one of the above.

This list may be expanded in the future. If you feel that a relevant format is missing, please
open an issue and/or a pull request!

## Academic Work

- [Dirty-Waters: Detecting Software Supply Chain Smells](https://arxiv.org/abs/2410.16049)

## Other issues not handled by dirty-waters

- Missing dependencies: simply run mvn/pip/... install :)
- Bloated dependencies: we recommend [DepClean](https://github.com/ASSERT-KTH/depclean) for Java, [depcheck](https://github.com/depcheck/depcheck) for NPM
- Version constraint inconsistencies: we recommend [pipdeptree](https://github.com/tox-dev/pipdeptree) for Python

## License

MIT License.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "dirty-waters",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": null,
    "keywords": "software supply chain, ssc, dependencies, npm",
    "author": null,
    "author_email": "Raphina Liu <raphina@kth.se>, Diogo Gaspar <dgaspar@kth.se>, Martin Monperrus <monperrus@kth.se>",
    "download_url": "https://files.pythonhosted.org/packages/aa/19/c3886cced6601a4eb3cfb753765662b3abcd5952cd67a2eb715fd24796d3/dirty_waters-0.70.0.tar.gz",
    "platform": null,
    "description": "# dirty-waters\n\nDirty-waters automatically finds software supply chain issues in software projects by analyzing the available metadata of all dependencies, transitively.\n\nReference: [Dirty-Waters: Detecting Software Supply Chain Smells](http://arxiv.org/pdf/2410.16049), Technical report 2410.16049, arXiv, 2024.\n\nBy using `dirty-waters`, you identify the shady areas of your supply chain, which would be natural target for attackers to exploit.\n\n`dirty-waters`'s static analyses report the following smells:\n\n- Dependencies with no/invalid\\* link to source code repositories (high severity)\n- Dependencies with no tag/commit SHA for release, impossible to have reproducible builds (medium severity)\n- Deprecated Dependencies (medium severity)\n- Depends on a fork (low severity), **disabled by default**\n- Dependencies without/with invalid code signature (medium severity)\n- Dependencies with no build attestation (low severity)\n\n\\* We consider invalid links to be links which do not return a 200 status code.\nFurthermore, if the dependencies are not hosted on GitHub, not all checks will be possible to be made (e.g., code signature).\n\nAs for its differential analyses, `dirty-waters` reports the following smells:\n\n- Dependencies with code signature changes (high severity)\n- Downgraded dependencies (medium severity)\n- Dependencies with commits made by both new authors and reviewers (medium severity)\n- Dependencies with commits approved by new reviewers (medium severity)\n- Dependencies with new contributors (low severity)\n\nAdditionally, `dirty-waters` gives a supplier view on the dependency trees (who owns the different dependencies?)\n\n`dirty-waters` is developed as part of the [Chains research project](https://chains.proj.kth.se/).\n\n## Installation\n\n### Installation via pip\n\nYou can install `dirty-waters` via pip:\n\n```bash\npip install dirty-waters\n# or\npipx install dirty-waters\n```\n\nSet up the GitHub API token (or with a `.env` file):\n\n```bash\nexport GITHUB_API_TOKEN=<your_token>\n```\n\n## Usage\n\n### Command line\n\nRun the tool using the following command structure:\n\n```\n# analyzing the software supply chain of Maven project INRIA/spoon\n$ dirty-waters -p INRIA/spoon -pm maven\n```\n\nAll configuration options\n\n```\nusage: main.py [-h] -p PROJECT_REPO_NAME [-v RELEASE_VERSION_OLD]\n               [-vn RELEASE_VERSION_NEW] [-d] [-n] -pm\n               {yarn-classic,yarn-berry,pnpm,npm,maven}\n               [--pnpm-scope PNPM_SCOPE] [--debug] [--config CONFIG]\n               [--gradual-report GRADUAL_REPORT | --no-gradual-report]\n               [--check-source-code] [--check-release-tags]\n               [--check-deprecated] [--check-forks] [--check-provenance]\n               [--check-code-signature] [--check-aliased-packages]\n\noptions:\n  -h, --help            show this help message and exit\n  -p PROJECT_REPO_NAME, --project-repo-name PROJECT_REPO_NAME\n                        Specify the project repository name. Example:\n                        MetaMask/metamask-extension\n  -v RELEASE_VERSION_OLD, --release-version-old RELEASE_VERSION_OLD\n                        The old release tag of the project repository.\n                        Defaults to HEAD. Example: v10.0.0\n  -vn RELEASE_VERSION_NEW, --release-version-new RELEASE_VERSION_NEW\n                        The new release version of the project repository.\n  -d, --differential-analysis\n                        Run differential analysis and generate a markdown\n                        report of the project\n  -n, --name-match      Compare the package names with the name in the in the\n                        package.json file. This option will slow down the\n                        execution time due to the API rate limit of code\n                        search.\n  -pm {yarn-classic,yarn-berry,pnpm,npm,maven}, --package-manager {yarn-classic,yarn-berry,pnpm,npm,maven}\n                        The package manager used in the project.\n  --pnpm-scope PNPM_SCOPE\n                        Extract dependencies from pnpm with a specific scope\n                        using 'pnpm list --filter <scope> --depth Infinity'\n                        command. Configure the scope in tool_config.py file.\n  --debug               Enable debug mode.\n  --config CONFIG       Path to configuration file (JSON)\n  --gradual-report GRADUAL_REPORT\n                        Enable/disable gradual reporting (default: true)\n  --no-gradual-report   Disable gradual reporting (deprecated, use --gradual-\n                        report=false instead)\n\nsmell checks:\n  --check-source-code   Check for dependencies with no link to source code\n                        repositories\n  --check-release-tags  Check for dependencies with no tag/commit sha for\n                        release\n  --check-deprecated    Check for deprecated dependencies\n  --check-forks         Check for dependencies that are forks\n  --check-provenance    Check for dependencies with no build attestation\n  --check-code-signature\n                        Check for dependencies with missing/invalid code\n                        signature\n  --check-aliased-packages\n                        Check for aliased packages\n```\n\nReports are gradual by default: that is, only the highest severity smell type with issues found within this project is reported. You can disable this feature, and get a full report,\nby setting the --gradual-report flag to false.\n\n1. Static analysis:\n\n```bash\n# If manually cloned\npython3 main.py -p MetaMask/metamask-extension -pm yarn-berry\n# If installed via pip\ndirty-waters -p MetaMask/metamask-extension -pm yarn-berry\n```\n\n- Example output: [Static Analysis Report Example](example_reports/static_analysis_report_example.md)\n\n2. Differential analysis:\n\n```bash\n# If manually cloned\npython3 main.py -p MetaMask/metamask-extension -v v11.11.0 -vn v11.12.0 -d -pm yarn-berry\n# If installed via pip\ndirty-waters -p MetaMask/metamask-extension -v v11.11.0 -vn v11.12.0 -d -pm yarn-berry\n```\n\n- Example output: [Differential Analysis Report Example](example_reports/differential_analysis_report_example.md)\n\nNotes:\n\n- `-v` should be the version of GitHub release, e.g. for [this release](https://github.com/MetaMask/metamask-extension/releases/tag/v11.1.0), the value should be `v11.11.0`, not `Version 11.11.0` or `11.11.0`.\n- When using `-d` for differential analysis, `-vn` must be specified.\n\n### Development\n\nTo set up `dirty-waters`, follow these steps:\n\n1. Clone the repository:\n\n```bash\ngit clone https://github.com/chains-project/dirty-waters.git\ncd dirty-waters\n```\n\n2. Set up a virtual environment and install dependencies:\n\n```bash\npython3 -m venv venv\nsource venv/bin/activate\npip install -r requirements.txt\ncd tool\n```\n\nIn alternative to virtual environments, you may also use the Nix flake present in this repository.\n\n3. Set up the GitHub API token (ideally, in a `.env` file):\n\n```bash\nexport GITHUB_API_TOKEN=<your_token>\n```\n\n### Configuration\n\nYou can set the tool's configuration through a JSON file, which can be then passed to the tool using the `--config` flag.\nAt the moment, we have configuration support to ignore specific packages from the analysis.\n\nAn example configuration file:\n\n```json\n{\n  \"ignore\": [\"package_name_1@versionx.y.z\", \"package_name_2@versiona.b.c\"]\n}\n```\n\nNote that for cases where a package is aliased, we check for the original package name, not the aliased one:\ni.e., if we alias the package `string-width` to `string-width-cjs`, we will check for `string-width@versionx.y.z`, not `string-width-cjs@versionx.y.z`.\n\n### Continuous integration\n\nSee Github action at <https://github.com/chains-project/dirty-waters-action>\n\n## Software Supply Chain Smell Support\n\n`dirty-waters` currently supports package managers within the JavaScript and Java ecosystems. However, due to some constraints associated with the nature of the package managers, the tool may not be able to detect all the smells in the project. The following table shows the supported package managers and their associated smells, for static analysis:\n\n| Package Manager | No Source Code Repository | Invalid Source Code Repository URL | No Release Tag | Deprecated Dependency | Depends on a Fork | No Build Attestation | No/Invalid Code Signature |\n| --------------- | ------------------------- | ---------------------------------- | -------------- | --------------------- | ----------------- | -------------------- | ------------------------- |\n| Yarn Classic    | Yes                       | Yes                                | Yes            | Yes                   | Yes               | Yes                  | Yes                       |\n| Yarn Berry      | Yes                       | Yes                                | Yes            | Yes                   | Yes               | Yes                  | Yes                       |\n| Pnpm            | Yes                       | Yes                                | Yes            | Yes                   | Yes               | Yes                  | Yes                       |\n| Npm             | Yes                       | Yes                                | Yes            | Yes                   | Yes               | Yes                  | Yes                       |\n| Maven           | Yes                       | Yes                                | Yes            | No                    | Yes               | No                   | Yes                       |\n\nAll package managers support every smell in the differential analysis scenario.\n\n### Smell Check Options\n\nBy default, all supported checks for the given package manager are performed in static analysis.\nYou can specify individual checks using the following flags (note that if at least one flag\nis passed, instead of all checks being performed, only the flagged ones will be):\n\n- `--check-source-code`: Check for dependencies with no link to source code repositories\n- `--check-release-tags`: Check for dependencies with no tag/commit sha for release\n- `--check-deprecated`: Check for deprecated dependencies\n- `--check-forks`: Check for dependencies that are forks\n- `--check-provenance`: Check for dependencies with no build attestation\n- `--check-code-signature`: Check for dependencies with no/invalid code signature\n\n**Note**: The `--check-release-tags` and `--check-forks` flags require `--check-source-code` to be enabled, as release tags can only be checked if we can first verify the source code repository.\n\nAs an example of running specific checks:\n\n```bash\ndirty-waters -p MetaMask/metamask-extension -v v11.11.0 -pm yarn-berry --check-source-code --check-release-tags\n```\n\nThis run will only check for dependencies with no link to source code repositories and dependencies with no tag/commit sha for release.\n\nFor **differential analysis**, it is currently not possible to specify individual checks -- all checks will be performed.\n\n### Notes\n\n#### Inaccessible Tags\n\nSometimes, the release version specified in a lockfile/pom/similar is not necessarily the same\nas the tag used in the repository. This can happen for a variety of reasons. We have\ncompiled several tag formats which were deemed reasonable to lookup, if the exact tag\nspecified in the lockfile/pom/similar is not found. They come from a combination of [AROMA](https://dl.acm.org/doi/pdf/10.1145/3643764)'s\nwork and our own research on this subject.\nThese formats are the following:\n\n<details> <summary>Tag formats</summary>\n\n- `<tag>`\n- `v<tag>`\n- `r-<tag>`\n- `release-<tag>`\n- `parent-<tag>`\n- `<package_name>@<tag>`\n- `<package_name>-v<tag>`\n- `<package_name>_v<tag>`\n- `<package_name>-<tag>`\n- `<package_name>_<tag>`\n- `<repo_name>@<tag>`\n- `<repo_name>-v<tag>`\n- `<repo_name>_v<tag>`\n- `<repo_name>-<tag>`\n- `<repo_name>_<tag>`\n- `<project_name>@<tag>`\n- `<project_name>-v<tag>`\n- `<project_name>_v<tag>`\n- `<project_name>-<tag>`\n- `<project_name>_<tag>`\n- `release/<tag>`\n- `<tag>-release`\n- `v.<tag>`\n- `p1-p2-p3<tag>`\n\nAs examples of what `package_name`, `repo_name`, and `project_name` could be, `maven-surefire`\nis an interesting dependency:\n\n- `maven-surefire-common` is the package name\n- `maven-surefire` is the repo name (we remove the owner prefix)\n- `surefire` is the project name\n\nIn particular, there are many `maven-*` dependencies whose tags follow these last conventions.\n\n</details>\n\nNote than this does not mean that if `dirty-waters` does not find a tag, it doesn't exist:\nit means that it either doesn't exist, or that its format is not one of the above.\n\nThis list may be expanded in the future. If you feel that a relevant format is missing, please\nopen an issue and/or a pull request!\n\n## Academic Work\n\n- [Dirty-Waters: Detecting Software Supply Chain Smells](https://arxiv.org/abs/2410.16049)\n\n## Other issues not handled by dirty-waters\n\n- Missing dependencies: simply run mvn/pip/... install :)\n- Bloated dependencies: we recommend [DepClean](https://github.com/ASSERT-KTH/depclean) for Java, [depcheck](https://github.com/depcheck/depcheck) for NPM\n- Version constraint inconsistencies: we recommend [pipdeptree](https://github.com/tox-dev/pipdeptree) for Python\n\n## License\n\nMIT License.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Automatically detect software supply chain smells and issues",
    "version": "0.70.0",
    "project_urls": {
        "Bug Tracker": "https://github.com/chains-project/dirty-waters/issues",
        "Homepage": "https://github.com/chains-project/dirty-waters"
    },
    "split_keywords": [
        "software supply chain",
        " ssc",
        " dependencies",
        " npm"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a7bdc38e72bd55aa41829136cd2e5d14fa7d4b4d58853e52e8e59dca40279c56",
                "md5": "691e5fb41ea1c1c6069bcceb36ea8fbb",
                "sha256": "9661f967045b8c2ae192935ba15ce7f4176ad368059494fea13101304eec8136"
            },
            "downloads": -1,
            "filename": "dirty_waters-0.70.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "691e5fb41ea1c1c6069bcceb36ea8fbb",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 53806,
            "upload_time": "2025-03-11T16:26:46",
            "upload_time_iso_8601": "2025-03-11T16:26:46.200213Z",
            "url": "https://files.pythonhosted.org/packages/a7/bd/c38e72bd55aa41829136cd2e5d14fa7d4b4d58853e52e8e59dca40279c56/dirty_waters-0.70.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "aa19c3886cced6601a4eb3cfb753765662b3abcd5952cd67a2eb715fd24796d3",
                "md5": "a0f1c3368c46c1ddfc12ee8cf4369dc5",
                "sha256": "82b2332d3512458f2efd23e91851058dd4670c40373d171adb4ec6dbdd7dd1c8"
            },
            "downloads": -1,
            "filename": "dirty_waters-0.70.0.tar.gz",
            "has_sig": false,
            "md5_digest": "a0f1c3368c46c1ddfc12ee8cf4369dc5",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 48501,
            "upload_time": "2025-03-11T16:26:47",
            "upload_time_iso_8601": "2025-03-11T16:26:47.924457Z",
            "url": "https://files.pythonhosted.org/packages/aa/19/c3886cced6601a4eb3cfb753765662b3abcd5952cd67a2eb715fd24796d3/dirty_waters-0.70.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-03-11 16:26:47",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "chains-project",
    "github_project": "dirty-waters",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "attrs",
            "specs": [
                [
                    "==",
                    "25.1.0"
                ]
            ]
        },
        {
            "name": "cattrs",
            "specs": [
                [
                    "==",
                    "24.1.2"
                ]
            ]
        },
        {
            "name": "certifi",
            "specs": [
                [
                    "==",
                    "2025.1.31"
                ]
            ]
        },
        {
            "name": "charset-normalizer",
            "specs": [
                [
                    "==",
                    "3.4.1"
                ]
            ]
        },
        {
            "name": "exceptiongroup",
            "specs": [
                [
                    "==",
                    "1.2.2"
                ]
            ]
        },
        {
            "name": "GitPython",
            "specs": [
                [
                    "==",
                    "3.1.44"
                ]
            ]
        },
        {
            "name": "idna",
            "specs": [
                [
                    "==",
                    "3.10"
                ]
            ]
        },
        {
            "name": "markdown-it-py",
            "specs": [
                [
                    "==",
                    "3.0.0"
                ]
            ]
        },
        {
            "name": "numpy",
            "specs": [
                [
                    "==",
                    "2.2.3"
                ]
            ]
        },
        {
            "name": "pandas",
            "specs": [
                [
                    "==",
                    "2.2.3"
                ]
            ]
        },
        {
            "name": "platformdirs",
            "specs": [
                [
                    "==",
                    "4.3.6"
                ]
            ]
        },
        {
            "name": "pytest",
            "specs": [
                [
                    "==",
                    "8.3.5"
                ]
            ]
        },
        {
            "name": "python-dateutil",
            "specs": [
                [
                    "==",
                    "2.9.0.post0"
                ]
            ]
        },
        {
            "name": "pytz",
            "specs": [
                [
                    "==",
                    "2025.1"
                ]
            ]
        },
        {
            "name": "PyYAML",
            "specs": [
                [
                    "==",
                    "6.0.2"
                ]
            ]
        },
        {
            "name": "requests",
            "specs": [
                [
                    "==",
                    "2.32.3"
                ]
            ]
        },
        {
            "name": "requests-cache",
            "specs": [
                [
                    "==",
                    "1.2.1"
                ]
            ]
        },
        {
            "name": "six",
            "specs": [
                [
                    "==",
                    "1.17.0"
                ]
            ]
        },
        {
            "name": "tabulate",
            "specs": [
                [
                    "==",
                    "0.9.0"
                ]
            ]
        },
        {
            "name": "tqdm",
            "specs": [
                [
                    "==",
                    "4.67.1"
                ]
            ]
        },
        {
            "name": "typing_extensions",
            "specs": [
                [
                    "==",
                    "4.12.2"
                ]
            ]
        },
        {
            "name": "tzdata",
            "specs": [
                [
                    "==",
                    "2025.1"
                ]
            ]
        },
        {
            "name": "url-normalize",
            "specs": [
                [
                    "==",
                    "1.4.3"
                ]
            ]
        },
        {
            "name": "urllib3",
            "specs": [
                [
                    "==",
                    "2.3.0"
                ]
            ]
        },
        {
            "name": "xmltodict",
            "specs": [
                [
                    "==",
                    "0.14.2"
                ]
            ]
        }
    ],
    "lcname": "dirty-waters"
}
        
Elapsed time: 0.40134s