├── .devcontainer ├── Dockerfile └── devcontainer.json ├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .vscode └── tasks.json ├── CODE_OF_CONDUCT.md ├── CodeMaid.config ├── Directory.Build.props ├── Dockerfile ├── LICENSE.txt ├── NOTICE.txt ├── PRIVACY.md ├── Pipelines ├── core-pipeline.yml └── ossgadget-pr.yml ├── README.md ├── SECURITY.md ├── SUPPORT.md ├── cst_logo.svg ├── icon-128.png ├── src ├── .editorconfig ├── CryptoGatherer │ ├── App.config │ ├── CodeSnippet.cs │ ├── CryptoGatherer.csproj │ ├── CryptoGatherer.sln │ ├── CryptoPatterns │ │ ├── crypto-patterns-00048188.txt │ │ ├── crypto-patterns-0696f383.txt │ │ ├── crypto-patterns-204104ed.txt │ │ ├── crypto-patterns-253352df.txt │ │ ├── crypto-patterns-2990460a.txt │ │ ├── crypto-patterns-2ae5a9a4.txt │ │ ├── crypto-patterns-31457afb.txt │ │ ├── crypto-patterns-3ab6ea7d.txt │ │ ├── crypto-patterns-4efbde22.txt │ │ ├── crypto-patterns-54b3c1b9.txt │ │ ├── crypto-patterns-5911b5df.txt │ │ ├── crypto-patterns-59bd7a2f.txt │ │ ├── crypto-patterns-679db1d5.txt │ │ ├── crypto-patterns-6dc1c8bd.txt │ │ ├── crypto-patterns-709e2155.txt │ │ ├── crypto-patterns-7505dd8b.txt │ │ ├── crypto-patterns-7a427f26.txt │ │ ├── crypto-patterns-7be1b480.txt │ │ ├── crypto-patterns-8e2c4f7b.txt │ │ ├── crypto-patterns-9239f876.txt │ │ ├── crypto-patterns-936262ec.txt │ │ ├── crypto-patterns-9ba20cdf.txt │ │ ├── crypto-patterns-aac17dfe.txt │ │ ├── crypto-patterns-aace54b7.txt │ │ ├── crypto-patterns-b0b80721.txt │ │ ├── crypto-patterns-c28e57d3.txt │ │ ├── crypto-patterns-cb1dbe36.txt │ │ ├── crypto-patterns-d4a7b7e0.txt │ │ ├── crypto-patterns-d539e85b.txt │ │ ├── crypto-patterns-e30770f0.txt │ │ ├── crypto-patterns-e7afc0a2.txt │ │ ├── crypto-patterns-ebcbdaa5.txt │ │ ├── crypto-patterns-f60f4a2c.txt │ │ ├── crypto-patterns-f62148a3.txt │ │ ├── crypto-patterns-f739f081.txt │ │ ├── crypto-patterns-fa76663f.txt │ │ └── crypto-patterns-fe9bc0f7.txt │ ├── Form1.Designer.cs │ ├── Form1.cs │ ├── Form1.resx │ ├── ListViewColumnSorter.cs │ ├── Program.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ ├── Resources.resx │ │ ├── Settings.Designer.cs │ │ └── Settings.settings │ ├── README.md │ └── Types.cs ├── OSSGadget.sln ├── Shared.CLI │ ├── BaseTool.cs │ ├── ErrorCode.cs │ ├── Helpers │ │ ├── CliHelpers.cs │ │ ├── ConsoleHelper.cs │ │ ├── OutputBuilder │ │ │ ├── IOutputBuilder.cs │ │ │ ├── NoneOutputBuilder.cs │ │ │ ├── OutputBuilderFactory.cs │ │ │ ├── SarifOutputBuilder.cs │ │ │ └── StringOutputBuilder.cs │ │ ├── PackageDownloader.cs │ │ └── RepoSearch.cs │ ├── OSSGadget.cs │ ├── Options │ │ ├── BaseToolOptions.cs │ │ ├── CharacteristicToolOptions.cs │ │ ├── DefogToolOptions.cs │ │ ├── DetectBackdoorToolOptions.cs │ │ ├── DetectCryptographyToolOptions.cs │ │ ├── DiffToolOptions.cs │ │ ├── DownloadToolOptions.cs │ │ ├── FindDomainSquatsToolOptions.cs │ │ ├── FindSourceToolOptions.cs │ │ ├── FindSquatsToolOptions.cs │ │ ├── FreshToolOptions.cs │ │ ├── HealthToolOptions.cs │ │ ├── MetadataToolOptions.cs │ │ ├── ReproducibleToolOptions.cs │ │ └── RiskCalculatorToolOptions.cs │ ├── Resources │ │ ├── BackdoorRules │ │ │ ├── backdoor_signatures.json │ │ │ ├── code_execution.json │ │ │ ├── crypto_currency.json │ │ │ ├── data_exfiltration.json │ │ │ ├── dependency_confusion.json │ │ │ ├── ioc.json │ │ │ ├── lolbas.json │ │ │ ├── obfuscation.json │ │ │ ├── pastebin.json │ │ │ └── reverse_shell.json │ │ └── CryptographyRules │ │ │ ├── implementation-asymmetric.json │ │ │ ├── implementation-block-cipher.json │ │ │ ├── implementation-crypto-generic.json │ │ │ ├── implementation-hash.json │ │ │ ├── implementation-prng.json │ │ │ ├── implementation-signature.json │ │ │ ├── implementation-stream-cipher.json │ │ │ ├── implementation-symmetric.json │ │ │ └── reference-common.json │ ├── Shared.CLI.csproj │ └── Tools │ │ ├── CharacteristicTool.cs │ │ ├── DefoggerTool.cs │ │ ├── DetectBackdoorTool.cs │ │ ├── DetectCryptographyTool │ │ ├── DetectCryptographyTool.cs │ │ └── Issue.cs │ │ ├── DiffTool │ │ ├── Diff.cs │ │ └── DiffTool.cs │ │ ├── DownloadTool.cs │ │ ├── FindDomainSquatsTool.cs │ │ ├── FindSourceTool.cs │ │ ├── FindSquatsTool.cs │ │ ├── FreshTool.cs │ │ ├── HealthTool │ │ ├── BaseHealthAlgorithm.cs │ │ ├── GitHubHealthAlgorithm.cs │ │ ├── HealthMetrics.cs │ │ └── HealthTool.cs │ │ ├── MetadataTool.cs │ │ ├── ReproducibleTool │ │ ├── BuildHelperScripts │ │ │ ├── cargo │ │ │ │ └── autobuild.sh │ │ │ ├── cpan │ │ │ │ └── autobuild.sh │ │ │ ├── gem │ │ │ │ └── autobuild.sh │ │ │ ├── npm │ │ │ │ ├── @objectisundefined │ │ │ │ │ └── typo.build │ │ │ │ ├── autobuild.sh │ │ │ │ ├── bluebird.build │ │ │ │ └── bluebird.prebuild │ │ │ └── pypi │ │ │ │ └── autobuild.sh │ │ ├── Helpers │ │ │ ├── DataObjects.cs │ │ │ ├── IgnoreFilter.cs │ │ │ └── OssReproducibleHelpers.cs │ │ ├── ReproducibleTool.cs │ │ └── Strategies │ │ │ ├── AutoBuildProducesSamePackage.cs │ │ │ ├── BaseStrategy.cs │ │ │ ├── OryxBuildStrategy.cs │ │ │ ├── PackageContainedInSourceStrategy.cs │ │ │ ├── PackageIgnoreList.txt │ │ │ └── PackageMatchesSourceStrategy.cs │ │ └── RiskCalculatorTool.cs ├── Shared │ ├── AssemblyInfo.cs │ ├── Contracts │ │ ├── IBaseProjectManager.cs │ │ ├── IManagerPackageActions.cs │ │ ├── IManagerPackageVersionMetadata.cs │ │ ├── IPackageExistence.cs │ │ ├── IProjectManagerFactory.cs │ │ └── ITypedManager.cs │ ├── DefaultHttpClientFactory.cs │ ├── Exceptions │ │ └── InvalidProjectManagerException.cs │ ├── Extensions │ │ ├── PackageUrlExtension.cs │ │ └── UriExtension.cs │ ├── Helpers │ │ ├── ArchiveHelper.cs │ │ ├── Check.cs │ │ ├── EnvironmentHelper.cs │ │ ├── FileSystemHelper.cs │ │ ├── PackageUrlJsonConverter.cs │ │ └── StringExtensions.cs │ ├── Metadata │ │ ├── BaseMetadataSource.cs │ │ ├── DepsDevMetadataSource.cs │ │ ├── LibrariesIoMetadataSource.cs │ │ └── NativeMetadataSource.cs │ ├── Model │ │ ├── ArtifactUri.cs │ │ ├── Enums │ │ │ ├── JsonParsingOption.cs │ │ │ ├── MavenArtifactType.cs │ │ │ ├── PackageRemovalReason.cs │ │ │ └── PackageVersionRemovalReason.cs │ │ ├── Metadata │ │ │ ├── NuGetPackageVersionMetadata.cs │ │ │ └── NuGetV2PackageVersionMetadata.cs │ │ ├── PackageExistence │ │ │ ├── PackageExistence.cs │ │ │ └── PackageVersionExistence.cs │ │ ├── PackageMetadata.cs │ │ └── Repository.cs │ ├── OssGadgetJsonSerializer.cs │ ├── OssGadgetLib.cs │ ├── PackageActions │ │ ├── NoOpPackageActions.cs │ │ └── NuGetPackageActions.cs │ ├── PackageManagers │ │ ├── BaseNuGetProjectManager.cs │ │ ├── BaseProjectManager.cs │ │ ├── CPANProjectManager.cs │ │ ├── CRANProjectManager.cs │ │ ├── CargoProjectManager.cs │ │ ├── CocoapodsProjectManager.cs │ │ ├── ComposerProjectManager.cs │ │ ├── CondaProjectManager.cs │ │ ├── GemProjectManager.cs │ │ ├── GitHubProjectManager.cs │ │ ├── GolangProjectManager.cs │ │ ├── HackageProjectManager.cs │ │ ├── MavenProjectManager.cs │ │ ├── NPMProjectManager.cs │ │ ├── NuGetProjectManager.cs │ │ ├── NuGetV2ProjectManager.cs │ │ ├── ProjectManagerFactory.cs │ │ ├── PyPIProjectManager.cs │ │ ├── TypedManager.cs │ │ ├── URLProjectManager.cs │ │ ├── UbuntuProjectManager.cs │ │ └── VSMProjectManager.cs │ ├── Shared.Lib.csproj │ ├── Utilities │ │ ├── NuGetLogger.cs │ │ ├── OssUtilities.cs │ │ └── VersionComparer.cs │ └── nlog.config ├── oss-find-squats-lib │ ├── FindPackageSquatResult.cs │ ├── FindPackageSquats.cs │ ├── MutateExtension.cs │ ├── MutateOptions.cs │ ├── Mutators │ │ ├── AddCharacterMutator.cs │ │ ├── AddContainingCharacterMutator.cs │ │ ├── AsciiHomoglyphMutator.cs │ │ ├── BitFlipMutator.cs │ │ ├── CloseLettersMutator.cs │ │ ├── DoubleHitMutator.cs │ │ ├── DuplicatorMutator.cs │ │ ├── IMutator.cs │ │ ├── Mutation.cs │ │ ├── MutatorType.cs │ │ ├── NamespaceInNameMutator.cs │ │ ├── PrefixMutator.cs │ │ ├── RemoveNamespaceMutator.cs │ │ ├── RemoveSeparatedSectionMutator.cs │ │ ├── RemovedCharacterMutator.cs │ │ ├── ReplaceCharacterMutator.cs │ │ ├── SeparatorChangedMutator.cs │ │ ├── SeparatorRemovedMutator.cs │ │ ├── SubstitutionMutator.cs │ │ ├── SuffixMutator.cs │ │ ├── SwapOrderOfLettersMutator.cs │ │ ├── UnicodeHomoglyphMutators.cs │ │ └── VowelSwapMutator.cs │ ├── QwertyKeyboardHelper.cs │ └── oss-find-squats-lib.csproj ├── oss-gadget-cli │ ├── OssGadgetCli.cs │ └── oss-gadget-cli.csproj └── oss-tests │ ├── .editorconfig │ ├── ArchiveHelperTests.cs │ ├── DefoggerTests.cs │ ├── DetectCryptographyTests.cs │ ├── DownloadTests.cs │ ├── FindSourceTests.cs │ ├── FindSquatsTests.cs │ ├── GlobalUsing.cs │ ├── Helpers │ ├── FindSquatsHelper.cs │ ├── NuGetTestHelper.cs │ └── PackageActionsHelper.cs │ ├── MetadataTests.cs │ ├── PackageExistenceTests.cs │ ├── PackageUrlExtensionsTests.cs │ ├── ProjectManagerTests │ ├── BaseNuGetProjectManagerTests.cs │ ├── CargoProjectManagerTests.cs │ ├── CondaProjectManagerTests.cs │ ├── GolangProjectManagerTests.cs │ ├── MavenProjectManagerTests.cs │ ├── NPMProjectManagerTests.cs │ ├── NuGetProjectManagerV2Tests.cs │ ├── NuGetProjectManagerV3Tests.cs │ ├── ProjectManagerFactoryTests.cs │ └── PyPIProjectManagerTests.cs │ ├── Properties │ ├── Resources.Designer.cs │ └── Resources.resx │ ├── ReproducibleTests.cs │ ├── SharedTests.cs │ ├── StringExtensionsTests.cs │ ├── TestData │ ├── Base64Zip.zip │ ├── Cargo │ │ ├── api_rand_json │ │ ├── cargo_rss_rand.xml │ │ └── rand │ ├── Go │ │ ├── go_yaml_1.3.0_info │ │ ├── go_yaml_1.3.0_mod │ │ └── go_yaml_list │ ├── Maven │ │ ├── maven_ant_1.6.html │ │ ├── maven_ant_1.6.pom │ │ ├── maven_ant_all.html │ │ ├── maven_ant_metadata.xml │ │ ├── maven_core_1.0.0_alpha2-sources.jar │ │ ├── maven_core_1.0.0_alpha2.aar │ │ ├── maven_core_1.0.0_alpha2.html │ │ ├── maven_core_1.0.0_alpha2.pom │ │ ├── maven_core_metadata.xml │ │ ├── maven_cose_20230908-javadoc.jar │ │ ├── maven_cose_20230908.jar │ │ ├── maven_cose_20230908.pom │ │ ├── maven_cose_20230908_artifact_metadata.json │ │ ├── maven_cose_metadata.xml │ │ ├── maven_fluentui_listitem_0.0.8.html │ │ ├── maven_fluentui_listitem_0.0.8.pom │ │ ├── maven_fluentui_listitem_all.html │ │ └── maven_fluentui_listitem_metadata.xml │ ├── NPM │ │ ├── achievementify_client.json │ │ ├── angular_core.json │ │ ├── azure_packages.json │ │ ├── ds-modal.json │ │ ├── jdalton_packages.json │ │ ├── lodash.json │ │ ├── lodashjs.json │ │ ├── microsoft_packages.json │ │ ├── minimum_json.json │ │ ├── monorepolint.json │ │ ├── rly-cli.json │ │ ├── tslib.json │ │ └── unpublishedpackage.json │ ├── NuGet │ │ ├── nuget_registration.json │ │ ├── powershellgallery │ │ │ ├── powershell_gallery_v2.xml │ │ │ └── psreadline │ │ │ │ ├── psreadline.xml │ │ │ │ ├── psreadline_v2_4_1_beta.xml │ │ │ │ └── versions.json │ │ ├── razorengine │ │ │ ├── 4.2.3-beta1.json │ │ │ ├── 4.2.3-beta1.metadata.json │ │ │ ├── index.json │ │ │ ├── latest.metadata.json │ │ │ └── versions.json │ │ └── slipeserver.scripting │ │ │ ├── index.json │ │ │ ├── page │ │ │ ├── 0.1.0-ci-20220325-215611 │ │ │ │ └── 0.1.0-ci-20220807-160739.json │ │ │ └── 0.1.0-ci-20221013-182634 │ │ │ │ └── 0.1.0-ci-20221120-180516.json │ │ │ ├── slipeserver.scripting.0.1.0-ci-20220607-083949.json │ │ │ └── versions.json │ ├── PyPI │ │ ├── microsoft_pypi_profile.html │ │ ├── pandas.json │ │ ├── pandas_1.4.2.json │ │ ├── plotly.json │ │ ├── plotly_5.7.0.json │ │ ├── requests.json │ │ └── requests_2.27.1.json │ └── oss-defog.dll │ ├── VersionTests.cs │ └── oss-tests.csproj └── version.json /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.236.0/containers/dotnet/.devcontainer/base.Dockerfile 2 | 3 | # [Choice] .NET version: 6.0, 3.1, 6.0-bullseye, 3.1-bullseye, 6.0-focal, 3.1-focal 4 | ARG VARIANT="6.0-bullseye-slim" 5 | FROM mcr.microsoft.com/vscode/devcontainers/dotnet:0-${VARIANT} 6 | 7 | # [Choice] Node.js version: none, lts/*, 18, 16, 14 8 | ARG NODE_VERSION="none" 9 | RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi 10 | 11 | # [Optional] Uncomment this section to install additional OS packages. 12 | # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 13 | # && apt-get -y install --no-install-recommends 14 | 15 | # [Optional] Uncomment this line to install global node packages. 16 | # RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g " 2>&1 -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: 2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.236.0/containers/dotnet 3 | { 4 | "name": "C# (.NET)", 5 | "build": { 6 | "dockerfile": "Dockerfile", 7 | "args": { 8 | // Update 'VARIANT' to pick a .NET Core version: 3.1, 6.0 9 | // Append -bullseye or -focal to pin to an OS version. 10 | "VARIANT": "6.0-bullseye", 11 | // Options 12 | "NODE_VERSION": "none" 13 | } 14 | }, 15 | 16 | // Configure tool-specific properties. 17 | "customizations": { 18 | // Configure properties specific to VS Code. 19 | "vscode": { 20 | // Add the IDs of extensions you want installed when the container is created. 21 | "extensions": [ 22 | "ms-dotnettools.csharp" 23 | ] 24 | } 25 | }, 26 | 27 | "postCreateCommand": "cd \"${workspaceFolder}/src\" && dotnet restore", 28 | 29 | "remoteUser": "vscode" 30 | } 31 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | /.github/ 2 | /.vs/ 3 | /Pipelines/ 4 | /.gitattributes 5 | /.gitignore 6 | /version.json 7 | /CodeMaid.config 8 | /*.md 9 | /*.png 10 | /*.svg 11 | /*.txt 12 | .editorconfig 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Don't mess with .ar files 5 | *.ar binary 6 | 7 | # These are all shell scripts 8 | /src/oss-reproducible/BuildHelperScripts/** text eol=lf 9 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "dotnet build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "/property:GenerateFullPaths=true", 11 | "/consoleloggerparameters:NoSummary" 12 | ], 13 | "problemMatcher": "$msCompile", 14 | "options": { 15 | "cwd": "${workspaceFolder}/src" 16 | } 17 | }, 18 | { 19 | "label": "dotnet test", 20 | "command": "dotnet", 21 | "type": "process", 22 | "args": [ 23 | "test" 24 | ], 25 | "problemMatcher": "$msCompile", 26 | "options": { 27 | "cwd": "${workspaceFolder}/src" 28 | } 29 | } 30 | ] 31 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 3.7.115 6 | all 7 | 8 | 9 | 10 | 11 | 12 | true 13 | true 14 | Recommended 15 | 16 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/sdk:8.0-preview-cbl-mariner2.0 2 | COPY . /app/ 3 | WORKDIR /app/src 4 | RUN set -o errexit -o nounset \ 5 | && dotnet build -c Release \ 6 | && ln --symbolic /app/src/oss-characteristics/bin/Release/net6.0/oss-characteristic /usr/bin/oss-characteristic \ 7 | && ln --symbolic /app/src/oss-defog/bin/Release/net6.0/oss-defog /usr/bin/oss-defog \ 8 | && ln --symbolic /app/src/oss-detect-backdoor/bin/Release/net6.0/oss-detect-backdoor /usr/bin/oss-detect-backdoor \ 9 | && ln --symbolic /app/src/oss-detect-cryptography/bin/Release/net6.0/oss-detect-cryptography /usr/bin/oss-detect-cryptography \ 10 | && ln --symbolic /app/src/oss-diff/bin/Release/net6.0/oss-diff /usr/bin/oss-diff \ 11 | && ln --symbolic /app/src/oss-download/bin/Release/net6.0/oss-download /usr/bin/oss-download \ 12 | && ln --symbolic /app/src/oss-find-domain-squats/bin/Release/net6.0/oss-find-domain-squats /usr/bin/oss-find-domain-squats \ 13 | && ln --symbolic /app/src/oss-find-source/bin/Release/net6.0/oss-find-source /usr/bin/oss-find-source \ 14 | && ln --symbolic /app/src/oss-find-squats/bin/Release/net6.0/oss-find-squats /usr/bin/oss-find-squats \ 15 | && ln --symbolic /app/src/oss-health/bin/Release/net6.0/oss-health /usr/bin/oss-health \ 16 | && ln --symbolic /app/src/oss-metadata/bin/Release/net6.0/oss-metadata /usr/bin/oss-metadata \ 17 | && ln --symbolic /app/src/oss-risk-calculator/bin/Release/net6.0/oss-risk-calculator /usr/bin/oss-risk-calculator 18 | # home directory of root user 19 | WORKDIR /root 20 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) Microsoft Corporation. All rights reserved. 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PRIVACY.md: -------------------------------------------------------------------------------- 1 | # Privacy and Telemetry Notice 2 | 3 | ## Data Collection 4 | 5 | The OSS Gadget software itself does *not* collect information about your 6 | use of the software, and therefore does not send such information to any source, 7 | including to Microsoft. Nevertheless, our privacy statement is located at 8 | https://go.microsoft.com/fwlink/?LinkID=824704. 9 | 10 | However, OSS Gadget does make outbound network connections to various locations, 11 | including NPM (registry.npmjs.org), NuGet (api.nuget.org), and RubyGems (rubygems.org). 12 | These connections are generally unauthenticated and made directly to that service. As such, 13 | their privacy policy would apply. 14 | 15 | In addition, the health calculator (oss-health.exe) and metadata (oss-metadata) tools use API keys 16 | to query GitHub and libraries.io. Since this connection is authenticated, the 17 | [GitHub privacy policy](https://help.github.com/en/github/site-policy/github-privacy-statement) and 18 | [Libraries.io privacy policy](https://libraries.io/privacy) would apply. 19 | 20 | -------------------------------------------------------------------------------- /Pipelines/ossgadget-pr.yml: -------------------------------------------------------------------------------- 1 | name: OSSGadget_PR_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r) 2 | trigger: none 3 | pr: 4 | branches: 5 | include: 6 | - main 7 | 8 | resources: 9 | repositories: 10 | - repository: templates 11 | type: git 12 | name: SecurityEngineering/OSS-Tools-Pipeline-Templates 13 | ref: refs/tags/v2.0.1 14 | - repository: 1esPipelines 15 | type: git 16 | name: 1ESPipelineTemplates/1ESPipelineTemplates 17 | ref: refs/tags/release 18 | 19 | variables: 20 | BuildConfiguration: 'Release' 21 | dotnetVersion: '8.0.x' 22 | 23 | extends: 24 | template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines 25 | parameters: 26 | pool: 27 | name: MSSecurity-1ES-Build-Agents-Pool 28 | image: MSSecurity-1ES-Windows-2022 29 | os: windows 30 | stages: 31 | - stage: Test 32 | jobs: 33 | - template: dotnet-test-job.yml@templates 34 | parameters: 35 | jobName: 'dotnet_test_windows' 36 | dotnetVersions: ['6.0.x','7.0.x','8.0.x'] 37 | poolName: MSSecurity-1ES-Build-Agents-Pool 38 | poolImage: MSSecurity-1ES-Windows-2022 39 | poolOs: windows 40 | projectPath: 'src/oss-tests/oss-tests.csproj' 41 | 42 | - stage: Build 43 | jobs: 44 | - template: dotnet-build-job.yml@templates 45 | parameters: 46 | buildTool: 'dotnet' 47 | buildConfiguration: 'Release' 48 | dotnetVersion: '8.0.x' 49 | targetFramework: 'net8.0' 50 | projectPath: 'src/OSSGadget.sln' 51 | projectName: 'OSSGadget' 52 | poolName: MSSecurity-1ES-Build-Agents-Pool 53 | poolImage: MSSecurity-1ES-Windows-2022 54 | poolOs: windows 55 | artifactName: 'OSSGadget-archive' 56 | preBuild: 57 | - template: nbgv-set-version-steps.yml@templates 58 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | ## Getting Help 2 | 3 | This project uses GitHub issues to track bugs and take feature requests. Please 4 | search for existing issues before filing new ones to avoid duplicates. To 5 | open a new issue, click on [Issues](https://github.com/microsoft/OSSGadget/issues) 6 | and then [New issue](https://github.com/microsoft/OSSGadget/issues/new/choose). 7 | 8 | If you need help in how to use this project, please review our [Wiki](https://github.com/microsoft/OSSGadget/wiki) 9 | before opening an issue. 10 | 11 | ## Security Issues 12 | 13 | If you discover a security vulnerability in this project, please see [SECURITY.md](https://github.com/microsoft/OSSGadget/blob/main/SECURITY.md) for information on how to report it privately. 14 | 15 | ## Microsoft Support Policy 16 | 17 | Support for this project is limited to the resources listed above. 18 | -------------------------------------------------------------------------------- /cst_logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/OSSGadget/d2cc60070831192660c98974afbddb036d07a928/icon-128.png -------------------------------------------------------------------------------- /src/CryptoGatherer/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/CryptoGatherer/CryptoGatherer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30002.166 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CryptoGatherer", "CryptoGatherer.csproj", "{7EAEFAAE-5AC1-4BC1-BE06-63EEDF4808AD}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {7EAEFAAE-5AC1-4BC1-BE06-63EEDF4808AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {7EAEFAAE-5AC1-4BC1-BE06-63EEDF4808AD}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {7EAEFAAE-5AC1-4BC1-BE06-63EEDF4808AD}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {7EAEFAAE-5AC1-4BC1-BE06-63EEDF4808AD}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {61387D19-3DC4-4DB1-B186-3ADE4011363F} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /src/CryptoGatherer/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace CryptoGatherer 5 | { 6 | static class Program 7 | { 8 | /// 9 | /// The main entry point for the application. 10 | /// 11 | [STAThread] 12 | static void Main() 13 | { 14 | Application.EnableVisualStyles(); 15 | Application.SetCompatibleTextRenderingDefault(false); 16 | Application.Run(new Form1()); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/CryptoGatherer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("CryptoGatherer")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("CryptoGatherer")] 12 | [assembly: AssemblyCopyright("Copyright © 2020")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("7eaefaae-5ac1-4bc1-be06-63eedf4808ad")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] -------------------------------------------------------------------------------- /src/CryptoGatherer/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CryptoGatherer.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/CryptoGatherer/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/CryptoGatherer/README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project. 3 | 4 | # Getting Started 5 | TODO: Guide users through getting your code up and running on their own system. In this section you can talk about: 6 | 1. Installation process 7 | 2. Software dependencies 8 | 3. Latest releases 9 | 4. API references 10 | 11 | # Build and Test 12 | TODO: Describe and show how to build your code and run the tests. 13 | 14 | # Contribute 15 | TODO: Explain how other users and developers can contribute to make your code better. 16 | 17 | If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files: 18 | - [ASP.NET Core](https://github.com/aspnet/Home) 19 | - [Visual Studio Code](https://github.com/Microsoft/vscode) 20 | - [Chakra Core](https://github.com/Microsoft/ChakraCore) -------------------------------------------------------------------------------- /src/CryptoGatherer/Types.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CryptoGatherer 8 | { 9 | public enum CodeLanguage 10 | { 11 | Csharp, 12 | C_Cpp, 13 | Go, 14 | Java, 15 | JavaScript, 16 | PHP, 17 | Python, 18 | Ruby, 19 | Rust 20 | } 21 | 22 | public enum CryptoAlgorithm 23 | { 24 | Asymmetric_RSA, 25 | Hash_BCrypt, 26 | Hash_Blake, 27 | Hash_Blake2, 28 | Hash_Blake3, 29 | Hash_GOST, 30 | Hash_Grøstl, 31 | Hash_HAS_160, 32 | Hash_HAVAL, 33 | Hash_JH, 34 | Hash_Kupyna, 35 | Hash_MD2, 36 | Hash_MD4, 37 | Hash_MD5, 38 | Hash_MD6, 39 | Hash_RIPEMD, 40 | Hash_SHA_1, 41 | Hash_SHA_2_224, 42 | Hash_SHA_2_256, 43 | Hash_SHA_2_384, 44 | Hash_SHA_2_512, 45 | Hash_SHA3, 46 | Hash_Siphash, 47 | Hash_Skein, 48 | Hash_SM3, 49 | Hash_Snefru, 50 | Hash_SpectralHash, 51 | Hash_Streebog, 52 | Hash_Tiger, 53 | Hash_Whirlpool, 54 | KeyAgreement_Curve25519_X25519, 55 | PRNG, 56 | Symmetric_AES, 57 | Symmetric_Salsa20_ChaCha, 58 | SAFER, 59 | twofish, 60 | anubis, 61 | blowfish, 62 | camellia, 63 | cast5, 64 | DES, 65 | idea, 66 | kasumi, 67 | khazad, 68 | kseed, 69 | multi2, 70 | noekeon, 71 | rc2, 72 | rc5, 73 | rc6, 74 | serpent, 75 | skipjack, 76 | tea, 77 | xtea 78 | // bunch of values added from https://github.com/libtom/libtomcrypt/tree/develop/src/ciphers 79 | 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Shared.CLI/ErrorCode.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource; 4 | 5 | public enum ErrorCode 6 | { 7 | Ok, 8 | ProcessingException, 9 | NoTargets, 10 | ErrorParsingOptions 11 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Helpers/ConsoleHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Shared 4 | { 5 | using System; 6 | using System.IO; 7 | 8 | public class ConsoleHelper 9 | { 10 | public static StreamWriter GetCurrentWriteStream() 11 | { 12 | return streamWriter ?? new StreamWriter(Console.OpenStandardOutput()); 13 | } 14 | 15 | public static bool RedirectConsole(string outFile) 16 | { 17 | // switch Console Out to file 18 | if (!string.IsNullOrEmpty(outFile) && streamWriter == null) 19 | { 20 | fileStream = new FileStream(outFile, FileMode.OpenOrCreate, FileAccess.Write); 21 | streamWriter = new StreamWriter(fileStream); 22 | Console.SetOut(streamWriter); 23 | return true; 24 | } 25 | 26 | return false; 27 | } 28 | 29 | public static void RestoreConsole() 30 | { 31 | // switch back to Console 32 | StreamWriter standardOutput = new(Console.OpenStandardOutput()); 33 | standardOutput.AutoFlush = true; 34 | Console.SetOut(standardOutput); 35 | 36 | streamWriter?.Close(); 37 | fileStream?.Close(); 38 | 39 | streamWriter?.Dispose(); 40 | fileStream?.Dispose(); 41 | 42 | fileStream = null; 43 | streamWriter = null; 44 | } 45 | 46 | private static FileStream? fileStream; 47 | private static StreamWriter? streamWriter; 48 | } 49 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Helpers/OutputBuilder/IOutputBuilder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Shared 4 | { 5 | using System.Collections.Generic; 6 | 7 | /// 8 | /// Interface for implementing Output providers 9 | /// 10 | public interface IOutputBuilder 11 | { 12 | /// 13 | /// Append the format output by passing in compatible IEnumerable input object An incompatible 14 | /// object input will result in InvalidCast exception 15 | /// 16 | /// 17 | public void AppendOutput(IEnumerable output); 18 | 19 | /// 20 | /// Gets the format output in string representation 21 | /// 22 | /// 23 | public string GetOutput(); 24 | 25 | /// 26 | /// Print the format string representation to the currently selected output 27 | /// 28 | public void PrintOutput(); 29 | 30 | /// 31 | /// Write the output to the given file. Creating directory if needed. 32 | /// 33 | public void WriteOutput(string fileName); 34 | } 35 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Helpers/OutputBuilder/NoneOutputBuilder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Shared 4 | { 5 | using System.Collections.Generic; 6 | 7 | public class NoneOutputBuilder : IOutputBuilder 8 | { 9 | /// 10 | /// An output builder that doesn't do anything. 11 | /// 12 | /// An IEnumerable object 13 | public void AppendOutput(IEnumerable output) 14 | { 15 | } 16 | 17 | public string GetOutput() 18 | { 19 | return string.Empty; 20 | } 21 | 22 | /// 23 | /// Prints to the currently selected output 24 | /// 25 | public void PrintOutput() 26 | { 27 | } 28 | 29 | public void WriteOutput(string fileName) { } 30 | } 31 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Helpers/OutputBuilder/OutputBuilderFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Shared 4 | { 5 | using Microsoft.CodeAnalysis.Sarif; 6 | using System; 7 | 8 | /// 9 | /// Factory to build the outputBuilder based on the format specified 10 | /// 11 | public class OutputBuilderFactory 12 | { 13 | public enum OutputFormat 14 | { 15 | sarifv1, 16 | sarifv2, 17 | text, // no sarif, just text 18 | none 19 | }; 20 | 21 | public static IOutputBuilder CreateDefaultOutputBuilder() 22 | { 23 | return new StringOutputBuilder(); 24 | } 25 | 26 | public static IOutputBuilder CreateOutputBuilder(string format) 27 | { 28 | OutputFormat currentOutputFormat = GetOutputFormat(format); 29 | return CreateOutputBuilder(currentOutputFormat); 30 | } 31 | 32 | public static IOutputBuilder CreateOutputBuilder(OutputFormat format) 33 | { 34 | switch (format) 35 | { 36 | case OutputFormat.none: 37 | return new NoneOutputBuilder(); 38 | 39 | case OutputFormat.sarifv1: 40 | case OutputFormat.sarifv2: 41 | SarifVersion version = format == OutputFormat.sarifv1 ? SarifVersion.OneZeroZero : SarifVersion.Current; 42 | return new SarifOutputBuilder(version); 43 | 44 | case OutputFormat.text: 45 | default: 46 | return new StringOutputBuilder(); 47 | } 48 | } 49 | 50 | public static OutputFormat GetOutputFormat(string format) 51 | { 52 | OutputFormat currentOutputFormat = OutputFormat.text; 53 | if (!Enum.TryParse(format, true, out currentOutputFormat)) 54 | { 55 | throw new ArgumentOutOfRangeException("Invalid output format"); 56 | } 57 | return currentOutputFormat; 58 | } 59 | 60 | private OutputBuilderFactory() 61 | { 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Helpers/OutputBuilder/StringOutputBuilder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Shared 4 | { 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | 9 | public class StringOutputBuilder : IOutputBuilder 10 | { 11 | /// 12 | /// Append more text to the result An incompatible object input will result in ArgumentException 13 | /// exception 14 | /// 15 | /// An IEnumerable object 16 | public void AppendOutput(IEnumerable output) 17 | { 18 | lock (stringResults) 19 | { 20 | if (output is IEnumerable strings) 21 | { 22 | stringResults.AddRange(strings); 23 | } 24 | else 25 | { 26 | throw new ArgumentException("output must be of type IEnumerable when calling this OutputBuilder."); 27 | } 28 | } 29 | } 30 | 31 | public string GetOutput() 32 | { 33 | return string.Join(Environment.NewLine, stringResults); 34 | } 35 | 36 | /// 37 | /// Prints to the console 38 | /// 39 | public void PrintOutput() 40 | { 41 | foreach (string? result in stringResults) 42 | { 43 | Console.Out.WriteLine(result); 44 | } 45 | } 46 | 47 | /// 48 | /// Write the output to the given file. Creating directory if needed. 49 | /// 50 | public void WriteOutput(string fileName) 51 | { 52 | using FileStream fs = new(fileName, FileMode.Create, FileAccess.ReadWrite); 53 | using StreamWriter sw = new(fs); 54 | foreach (string result in stringResults) 55 | { 56 | sw.WriteLine(result); 57 | } 58 | } 59 | 60 | private readonly List stringResults = new(); 61 | } 62 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Options/BaseToolOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.OssGadget.Options; 4 | 5 | using CommandLine; 6 | using CommandLine.Text; 7 | using System.Collections.Generic; 8 | 9 | public class BaseToolOptions 10 | { 11 | } 12 | -------------------------------------------------------------------------------- /src/Shared.CLI/Options/DefogToolOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.OssGadget.Options; 4 | 5 | using CommandLine; 6 | using CommandLine.Text; 7 | using System.Collections.Generic; 8 | 9 | [Verb("defog", HelpText = "Identify hidden strings")] 10 | public class DefogToolOptions : BaseToolOptions 11 | { 12 | [Usage()] 13 | public static IEnumerable Examples 14 | { 15 | get 16 | { 17 | return new List() { 18 | new Example("Identify hidden strings", 19 | new DefogToolOptions { Targets = new List() {"[options]", "package-url..." } })}; 20 | } 21 | } 22 | 23 | [Option('d', "download-directory", Required = false, Default = ".", 24 | HelpText = "the directory to download the package to.")] 25 | public string DownloadDirectory { get; set; } = "."; 26 | 27 | [Option('c', "use-cache", Required = false, Default = false, 28 | HelpText = "do not download the package if it is already present in the destination directory.")] 29 | public bool UseCache { get; set; } 30 | 31 | [Option('f', "format", Required = false, Default = "text", 32 | HelpText = "specify the output format(text|sarifv1|sarifv2)")] 33 | public string Format { get; set; } = "text"; 34 | 35 | [Option("save-found-binaries-to", Required = false, Default = "", 36 | HelpText = "location to save defogged binaries")] 37 | public string SaveFoundBinariesLocation { get; set; } = string.Empty; 38 | 39 | [Option("save-archives-to", Required = false, Default = "", 40 | HelpText = "location to save defogged archives")] 41 | public string SaveFoundArchivesTo { get; set; } = string.Empty; 42 | 43 | [Option("save-blobs-to", Required = false, Default = "", 44 | HelpText = "location to save defogged archives")] 45 | public string SaveFoundBlobsTo { get; set; } = string.Empty; 46 | 47 | [Option("report-blobs", Required = false, Default = false, 48 | HelpText = "if blobs should be reported")] 49 | public bool ShouldSaveBlobs { get; set; } = false; 50 | 51 | [Option("minimum-hex-length", Required = false, Default = 0, 52 | HelpText = "location to save defogged archives")] 53 | public int MinimumHexLength { get; set; } = 0; 54 | 55 | [Option("minimum-base64-length", Required = false, Default = 0, 56 | HelpText = "location to save defogged archives")] 57 | public int MinimumBase64Length { get; set; } = 0; 58 | 59 | [Value(0, Required = true, 60 | HelpText = "PackgeURL(s) specifier to analyze (required, repeats OK)", Hidden = true)] // capture all targets to analyze 61 | public IEnumerable? Targets { get; set; } 62 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Options/DetectBackdoorToolOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.OssGadget.Options; 4 | 5 | using CommandLine; 6 | using CommandLine.Text; 7 | using System.Collections.Generic; 8 | 9 | [Verb("detect-backdoor", HelpText = "Identify potential malware or backdoors in the given package")] 10 | public class DetectBackdoorToolOptions : BaseToolOptions 11 | { 12 | [Usage()] 13 | public static IEnumerable Examples 14 | { 15 | get 16 | { 17 | return new List() { 18 | new Example("Identify potential malware or backdoors in the given package", 19 | new DetectBackdoorToolOptions { Targets = new List() {"[options]", "package-url..." } })}; 20 | } 21 | } 22 | 23 | [Option('d', "download-directory", Required = false, Default = ".", 24 | HelpText = "the directory to download the package to.")] 25 | public string DownloadDirectory { get; set; } = "."; 26 | 27 | [Option('f', "format", Required = false, Default = "text", 28 | HelpText = "specify the output format(text|sarifv1|sarifv2)")] 29 | public string Format { get; set; } = "text"; 30 | 31 | [Option('o', "output-file", Required = false, Default = "", 32 | HelpText = "send the command output to a file instead of stdout")] 33 | public string OutputFile { get; set; } = ""; 34 | 35 | [Value(0, Required = true, 36 | HelpText = "PackgeURL(s) specifier to analyze (required, repeats OK)", Hidden = true)] // capture all targets to analyze 37 | public IEnumerable? Targets { get; set; } 38 | 39 | [Option('c', "use-cache", Required = false, Default = false, 40 | HelpText = "do not download the package if it is already present in the destination directory.")] 41 | public bool UseCache { get; set; } 42 | 43 | [Option('b', "backtracking", Required = false, HelpText = "Use backtracking engine by default.")] 44 | public bool EnableBacktracking { get; set; } = false; 45 | 46 | [Option('s', "single-threaded", Required = false, HelpText = "Use single-threaded analysis")] 47 | public bool SingleThread { get; set; } = false; 48 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Options/DetectCryptographyToolOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.OssGadget.Options; 4 | 5 | using CommandLine; 6 | using CommandLine.Text; 7 | using System.Collections.Generic; 8 | 9 | [Verb("detect-cryptography", HelpText = "Identify potential malware or backdoors in the given package")] 10 | public class DetectCryptographyToolOptions : BaseToolOptions 11 | { 12 | [Usage()] 13 | public static IEnumerable Examples 14 | { 15 | get 16 | { 17 | return new List() { 18 | new Example("Identify potential malware or backdoors in the given package", 19 | new DetectCryptographyToolOptions { Targets = new List() {"[options]", "package-url..." } })}; 20 | } 21 | } 22 | 23 | [Value(0, Required = true, 24 | HelpText = "PackgeURL(s) specifier to analyze (required, repeats OK)", Hidden = true)] // capture all targets to analyze 25 | public IEnumerable? Targets { get; set; } 26 | 27 | [Option('c', "use-cache", Required = false, Default = false, 28 | HelpText = "do not download the package if it is already present in the destination directory.")] 29 | public bool UseCache { get; set; } 30 | 31 | [Option('d', "download-directory", Required = false, Default = ".", 32 | HelpText = "the directory to download the package to.")] 33 | public string DownloadDirectory { get; set; } = "."; 34 | 35 | [Option("disable-default-rules", Required = false, Default = false, 36 | HelpText = "Igonre default rules")] 37 | public bool DisableDefaultRules { get; set; } = false; 38 | 39 | [Option("custom-rule-directory", Required = false, Default = "", 40 | HelpText = "Location with custom rules")] 41 | public string CustomRuleDirectory { get; set; } = string.Empty; 42 | 43 | [Option("verbose", Required = false, Default = false, 44 | HelpText = "Increase verbosity")] 45 | public bool Verbose { get; set; } = false; 46 | 47 | [Option("output-file", Required = false, Default = "", 48 | HelpText = "the file to write output to")] 49 | public string OutputFile { get; set; } = string.Empty; 50 | 51 | [Option('f', "format", Required = false, Default = "text", 52 | HelpText = "specify the output format(text|sarifv1|sarifv2)")] 53 | public string Format { get; set; } = "text"; 54 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Options/DownloadToolOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | namespace Microsoft.CST.OpenSource.OssGadget.Options; 3 | 4 | using CommandLine; 5 | using CommandLine.Text; 6 | using System.Collections.Generic; 7 | 8 | [Verb("download", HelpText = "Download the given package")] 9 | public class DownloadToolOptions : BaseToolOptions 10 | { 11 | [Usage()] 12 | public static IEnumerable Examples 13 | { 14 | get 15 | { 16 | return new List() { 17 | new Example("Download the given package", 18 | new DownloadToolOptions { Targets = new List() {"[options]", "package-url..." } })}; 19 | } 20 | } 21 | 22 | [Option('x', "download-directory", Required = false, Default = ".", 23 | HelpText = "the directory to download the package to.")] 24 | public string DownloadDirectory { get; set; } = "."; 25 | 26 | [Option('m', "download-metadata-only", Required = false, Default = false, 27 | HelpText = "download only the package metadata, not the package.")] 28 | public bool DownloadMetadataOnly { get; set; } 29 | 30 | [Option('e', "extract", Required = false, Default = false, 31 | HelpText = "Extract the package contents")] 32 | public bool Extract { get; set; } 33 | 34 | [Value(0, Required = true, 35 | HelpText = "PackgeURL(s) specifier to analyze (required, repeats OK)", Hidden = true)] // capture all targets to analyze 36 | public IEnumerable? Targets { get; set; } 37 | 38 | [Option('c', "use-cache", Required = false, Default = false, 39 | HelpText = "do not download the package if it is already present in the destination directory.")] 40 | public bool UseCache { get; set; } 41 | } 42 | -------------------------------------------------------------------------------- /src/Shared.CLI/Options/FindDomainSquatsToolOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.OssGadget.Options; 4 | 5 | using CommandLine; 6 | using CommandLine.Text; 7 | using System.Collections.Generic; 8 | 9 | [Verb("find-domain-squats", HelpText = "Find Squat Candidates for the Given Packages")] 10 | public class FindDomainSquatsToolOptions : BaseToolOptions 11 | { 12 | [Usage()] 13 | public static IEnumerable Examples 14 | { 15 | get 16 | { 17 | return new List() { 18 | new Example("Find Squat Candidates for the Given Packages", 19 | new FindDomainSquatsToolOptions { Targets = new List() {"[options]", "domains" } })}; 20 | } 21 | } 22 | 23 | [Option('o', "output-file", Required = false, Default = "", 24 | HelpText = "send the command output to a file instead of stdout")] 25 | public string OutputFile { get; set; } = ""; 26 | 27 | [Option('f', "format", Required = false, Default = "text", 28 | HelpText = "specify the output format(text|sarifv1|sarifv2)")] 29 | public string Format { get; set; } = "text"; 30 | 31 | [Option('q', "quiet", Required = false, Default = false, 32 | HelpText = "Suppress console output.")] 33 | public bool Quiet { get; set; } = false; 34 | 35 | [Option('s', "sleep-delay", Required = false, Default = 0, HelpText = "Number of ms to sleep between checks.")] 36 | public int SleepDelay { get; set; } 37 | 38 | [Option('u', "unregistered", Required = false, Default = false, HelpText = "Don't show registered domains.")] 39 | public bool Unregistered { get; set; } 40 | 41 | [Option('r', "registered", Required = false, Default = false, HelpText = "Don't show unregistered domains.")] 42 | public bool Registered { get; set; } 43 | 44 | [Value(0, Required = true, 45 | HelpText = "Domain(s) specifier to analyze (required, repeats OK)", Hidden = true)] // capture all targets to analyze 46 | public IEnumerable? Targets { get; set; } 47 | } 48 | -------------------------------------------------------------------------------- /src/Shared.CLI/Options/FindSourceToolOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.OssGadget.Options; 4 | 5 | using CommandLine; 6 | using CommandLine.Text; 7 | using System.Collections.Generic; 8 | 9 | [Verb("find-source", HelpText = "Find the source code repository for the given package")] 10 | public class FindSourceToolOptions : BaseToolOptions 11 | { 12 | [Usage()] 13 | public static IEnumerable Examples 14 | { 15 | get 16 | { 17 | return new List() { 18 | new Example("Find the source code repository for the given package", new FindSourceToolOptions { Targets = new List() {"[options]", "package-url..." } })}; 19 | } 20 | } 21 | 22 | [Option('f', "format", Required = false, Default = "text", 23 | HelpText = "specify the output format(text|sarifv1|sarifv2)")] 24 | public string Format { get; set; } = "text"; 25 | 26 | [Option('o', "output-file", Required = false, Default = "", 27 | HelpText = "send the command output to a file instead of stdout")] 28 | public string OutputFile { get; set; } = ""; 29 | 30 | [Option('S', "single", Required = false, Default = false, 31 | HelpText = "Show only top possibility of the package source repositories. When using text format the *only* output will be the URL or empty string if error or not found.")] 32 | public bool Single { get; set; } 33 | 34 | [Value(0, Required = true, 35 | HelpText = "PackgeURL(s) specifier to analyze (required, repeats OK)", Hidden = true)] // capture all targets to analyze 36 | public IEnumerable? Targets { get; set; } 37 | } 38 | -------------------------------------------------------------------------------- /src/Shared.CLI/Options/FindSquatsToolOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.OssGadget.Options; 4 | 5 | using CommandLine; 6 | using CommandLine.Text; 7 | using System.Collections.Generic; 8 | 9 | [Verb("find-squats", HelpText = "Find Squat Candidates for the Given Packages")] 10 | public class FindSquatsToolOptions : BaseToolOptions 11 | { 12 | [Usage()] 13 | public static IEnumerable Examples 14 | { 15 | get 16 | { 17 | return new List() { 18 | new Example("Find Squat Candidates for the Given Packages", 19 | new FindSquatsToolOptions { Targets = new List() {"[options]", "package-urls..." } })}; 20 | } 21 | } 22 | 23 | [Option('o', "output-file", Required = false, Default = "", 24 | HelpText = "send the command output to a file instead of stdout")] 25 | public string OutputFile { get; set; } = ""; 26 | 27 | [Option('f', "format", Required = false, Default = "text", 28 | HelpText = "specify the output format(text|sarifv1|sarifv2)")] 29 | public string Format { get; set; } = "text"; 30 | 31 | [Option('q', "quiet", Required = false, Default = false, 32 | HelpText = "Suppress console output.")] 33 | public bool Quiet { get; set; } = false; 34 | 35 | [Option('s', "sleep-delay", Required = false, Default = 0, HelpText = "Number of ms to sleep between checks.")] 36 | public int SleepDelay { get; set; } 37 | 38 | [Value(0, Required = true, 39 | HelpText = "PackgeURL(s) specifier to analyze (required, repeats OK)", Hidden = true)] // capture all targets to analyze 40 | public IEnumerable? Targets { get; set; } 41 | 42 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Options/FreshToolOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.OssGadget.Options; 4 | 5 | using CommandLine; 6 | using CommandLine.Text; 7 | using System.Collections.Generic; 8 | 9 | [Verb("fresh", HelpText = "Find the source code repository for the given package")] 10 | public class FreshToolOptions : BaseToolOptions 11 | { 12 | [Usage()] 13 | public static IEnumerable Examples 14 | { 15 | get 16 | { 17 | return new List() { 18 | new Example("Find the source code repository for the given package", new FreshToolOptions { Targets = new List() {"[options]", "package-url..." } })}; 19 | } 20 | } 21 | 22 | [Option('f', "format", Required = false, Default = "text", 23 | HelpText = "specify the output format(text|sarifv1|sarifv2)")] 24 | public string Format { get; set; } = "text"; 25 | 26 | [Option('o', "output-file", Required = false, Default = "", 27 | HelpText = "send the command output to a file instead of stdout")] 28 | public string OutputFile { get; set; } = ""; 29 | 30 | [Option('m', "max-age-maintained", Required = false, Default = 30 * 18, 31 | HelpText = "maximum age of versions for still-maintained projects, 0 to disable")] 32 | public int MaxAgeMaintained { get; set; } 33 | 34 | [Option('u', "max-age-unmaintained", Required = false, Default = 30 * 48, 35 | HelpText = "maximum age of versions for unmaintained projects, 0 to disable")] 36 | public int MaxAgeUnmaintained { get; set; } 37 | 38 | [Option('v', "max-out-of-date-versions", Required = false, Default = 6, 39 | HelpText = "maximum number of versions out of date, 0 to disable")] 40 | public int MaxOutOfDateVersions { get; set; } 41 | 42 | [Option('r', "filter", Required = false, Default = null, 43 | HelpText = "filter versions by regular expression")] 44 | public string? Filter { get; set; } 45 | 46 | [Value(0, Required = true, 47 | HelpText = "PackgeURL(s) specifier to analyze (required, repeats OK)", Hidden = true)] // capture all targets to analyze 48 | public IEnumerable? Targets { get; set; } 49 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Options/HealthToolOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.OssGadget.Options; 4 | 5 | using CommandLine; 6 | using CommandLine.Text; 7 | using System.Collections.Generic; 8 | 9 | [Verb("health", HelpText = "Calculate a health score based on package metadata")] 10 | public class HealthToolOptions : BaseToolOptions 11 | { 12 | [Usage()] 13 | public static IEnumerable Examples 14 | { 15 | get 16 | { 17 | return new List() { 18 | new Example("Calculate a health score based on package metadata", 19 | new HealthToolOptions() { Targets = new List() {"[options]", "package-url..." } })}; 20 | } 21 | } 22 | 23 | [Option('f', "format", Required = false, Default = "text", 24 | HelpText = "specify the output format(text|sarifv1|sarifv2)")] 25 | public string? Format { get; set; } 26 | 27 | [Option('o', "output-file", Required = false, Default = "", 28 | HelpText = "send the command output to a file instead of stdout")] 29 | public string OutputFile { get; set; } = ""; 30 | 31 | [Value(0, Required = true, 32 | HelpText = "PackgeURL(s) specifier to analyze (required, repeats OK)", Hidden = true)] // capture all targets to analyze 33 | public IEnumerable? Targets { get; set; } 34 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Options/MetadataToolOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.OssGadget.Options; 4 | 5 | using CommandLine; 6 | using CommandLine.Text; 7 | using System; 8 | using System.Collections.Generic; 9 | 10 | [Verb("metadata", HelpText = "Find the normalized metadata for the given package. Not all package ecosystems are supported.")] 11 | public class MetadataToolOptions : BaseToolOptions 12 | { 13 | [Usage()] 14 | public static IEnumerable Examples 15 | { 16 | get 17 | { 18 | return new List() { 19 | new Example("Find the normalized metadata for the given package. Not all package ecosystems are supported.", 20 | new MetadataToolOptions { Targets = new List() {"[options]", "package-url..." } })}; 21 | } 22 | } 23 | [Option('s', "data-source", Required = false, Default="deps.dev", 24 | HelpText = "The data source to use (deps.dev, libraries.io, or native)")] 25 | public string DataSource { get; set; } = "deps.dev"; 26 | 27 | [Option('j', "jmes-path", Required = false, Default = null, 28 | HelpText = "The JMESPath expression to use to filter the data")] 29 | public string? JmesPathExpression { get; set; } 30 | 31 | [Option('c', "useCache", Required = false, Default = false, 32 | HelpText = "Should metadata use the cache, and get cached?")] 33 | public bool UseCache { get; set; } = false; 34 | 35 | [Option("list-supported", Required = false, Default = false, 36 | HelpText = "List the supported package ecosystems")] 37 | public bool ListSupported { get; set; } = false; 38 | 39 | [Value(0, Required = false, 40 | HelpText = "PackgeURL(s) specifier to analyze (required, repeats OK)", Hidden = true)] // capture all targets to analyze 41 | public IEnumerable Targets { get => targets; set => targets = value; } 42 | 43 | private IEnumerable targets = Array.Empty(); 44 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Options/ReproducibleToolOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.OssGadget.Options; 4 | 5 | using CommandLine; 6 | using CommandLine.Text; 7 | using System.Collections.Generic; 8 | 9 | [Verb("reproducible", HelpText = "Estimate semantic equivalency of the given package and source code")] 10 | public class ReproducibleToolOptions : BaseToolOptions 11 | { 12 | [Usage()] 13 | public static IEnumerable Examples 14 | { 15 | get 16 | { 17 | return new List() { 18 | new Example("Estimate semantic equivalency of the given package and source code", new ReproducibleToolOptions { Targets = new List() {"[options]", "package-url..." } }) 19 | }; 20 | } 21 | } 22 | 23 | [Value(0, Required = true, HelpText = "PackgeURL(s) specifier to analyze (required, repeats OK)", Hidden = true)] // capture all targets to analyze 24 | public IEnumerable? Targets { get; set; } 25 | 26 | [Option('a', "all-strategies", Required = false, Default = false, 27 | HelpText = "Execute all strategies, even after a successful one is identified.")] 28 | public bool AllStrategies { get; set; } 29 | 30 | [Option("specific-strategies", Required = false, 31 | HelpText = "Execute specific strategies, comma-separated.")] 32 | public string? SpecificStrategies { get; set; } 33 | 34 | [Option('s', "source-ref", Required = false, Default = "", 35 | HelpText = "If a source version cannot be identified, use the specified git reference (tag, commit, etc.).")] 36 | public string OverrideSourceReference { get; set; } = ""; 37 | 38 | [Option("diff-technique", Required = false, Default = DiffTechnique.Normalized, HelpText = "Configure diff technique.")] 39 | public DiffTechnique DiffTechnique { get; set; } = DiffTechnique.Normalized; 40 | 41 | [Option('o', "output-file", Required = false, Default = "", HelpText = "Send the command output to a file instead of standard output")] 42 | public string OutputFile { get; set; } = ""; 43 | 44 | [Option('d', "show-differences", Required = false, Default = false, 45 | HelpText = "Output the differences between the package and the reference content.")] 46 | public bool ShowDifferences { get; set; } 47 | 48 | [Option("show-all-differences", Required = false, Default = false, 49 | HelpText = "Show all differences (default: capped at 20), implies --show-differences")] 50 | public bool ShowAllDifferences { get; set; } 51 | 52 | [Option('l', "leave-intermediate", Required = false, Default = false, 53 | HelpText = "Do not clean up intermediate files (useful for debugging).")] 54 | public bool LeaveIntermediateFiles { get; set; } 55 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Options/RiskCalculatorToolOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.OssGadget.Options; 4 | 5 | using CommandLine; 6 | using CommandLine.Text; 7 | using System.Collections.Generic; 8 | 9 | [Verb("risk", HelpText = "Calculate a risk metric for the given package")] 10 | public class RiskCalculatorToolOptions : BaseToolOptions 11 | { 12 | [Usage()] 13 | public static IEnumerable Examples 14 | { 15 | get 16 | { 17 | return new List() { 18 | new Example("Calculate a risk metric for the given package", 19 | new RiskCalculatorToolOptions { Targets = new List() {"[options]", "package-url..." } })}; 20 | } 21 | } 22 | 23 | [Option('d', "download-directory", Required = false, Default = null, 24 | HelpText = "the directory to download the package to.")] 25 | public string DownloadDirectory { get; set; } = "."; 26 | 27 | [Option('r', "external-risk", Required = false, Default = 0, 28 | HelpText = "include additional risk in final calculation.")] 29 | public int ExternalRisk { get; set; } 30 | 31 | [Option('f', "format", Required = false, Default = "text", 32 | HelpText = "specify the output format(text|sarifv1|sarifv2)")] 33 | public string Format { get; set; } = "text"; 34 | 35 | [Option('o', "output-file", Required = false, Default = "", 36 | HelpText = "send the command output to a file instead of stdout")] 37 | public string OutputFile { get; set; } = ""; 38 | 39 | [Option('n', "no-health", Required = false, Default = false, 40 | HelpText = "do not check project health")] 41 | public bool NoHealth { get; set; } 42 | 43 | [Option(Default = false, HelpText = "Verbose output")] 44 | public bool Verbose { get; set; } 45 | 46 | [Value(0, Required = true, 47 | HelpText = "PackgeURL(s) specifier to analyze (required, repeats OK)", Hidden = true)] // capture all targets to analyze 48 | public IEnumerable? Targets { get; set; } 49 | 50 | [Option('c', "use-cache", Required = false, Default = false, 51 | HelpText = "do not download the package if it is already present in the destination directory.")] 52 | public bool UseCache { get; set; } 53 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Resources/BackdoorRules/backdoor_signatures.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Backdoor: CFDUID", 4 | "id": "BD000200", 5 | "description": "Backdoor: CFDUID", 6 | "tags": [ 7 | "Security.Backdoor.Signature.CFDUID" 8 | ], 9 | "severity": "critical", 10 | "patterns": [ 11 | { 12 | "pattern": "___cfduid", 13 | "type": "string", 14 | "scopes": [ "code", "comment" ], 15 | "modifiers": [ "i" ], 16 | "confidence": "high" 17 | } 18 | ] 19 | }, 20 | { 21 | "name": "Backdoor: ZAUTHSS", 22 | "id": "BD000201", 23 | "description": "Backdoor: ZAUTHSS", 24 | "tags": [ 25 | "Security.Backdoor.Signature.ZAUTHSS" 26 | ], 27 | "severity": "critical", 28 | "patterns": [ 29 | { 30 | "pattern": "ZAUTHSS", 31 | "type": "string", 32 | "scopes": [ "code", "comment" ], 33 | "modifiers": [ "i" ], 34 | "confidence": "high" 35 | } 36 | ] 37 | }, 38 | { 39 | "name": "Backdoor: gohack.xyz", 40 | "id": "BD000202", 41 | "description": "Backdoor: gohack.xyz", 42 | "tags": [ 43 | "Security.Backdoor.Signature.gohackxyz" 44 | ], 45 | "severity": "important", 46 | "patterns": [ 47 | { 48 | "pattern": "gohack.xyz", 49 | "type": "string", 50 | "scopes": [ "code", "comment" ], 51 | "modifiers": [ "i" ], 52 | "confidence": "high" 53 | } 54 | ] 55 | }, 56 | { 57 | "name": "Backdoor: Hyperion", 58 | "id": "BD000203", 59 | "description": "Backdoor: Hyperion", 60 | "tags": [ 61 | "Security.Backdoor.Signature.Hyperion" 62 | ], 63 | "severity": "important", 64 | "patterns": [ 65 | { 66 | "pattern": "billythegoat356", 67 | "type": "string", 68 | "scopes": [ "code", "comment" ], 69 | "modifiers": [ "i" ], 70 | "confidence": "high" 71 | } 72 | ] 73 | } 74 | ] -------------------------------------------------------------------------------- /src/Shared.CLI/Resources/BackdoorRules/crypto_currency.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Backdoor: Crypto Currency", 4 | "id": "BD000400", 5 | "description": "Backdoor: Crypto Currency", 6 | "tags": [ 7 | "Security.Backdoor.CryptoCurrency" 8 | ], 9 | "severity": "moderate", 10 | "patterns": [ 11 | { 12 | "pattern": "\b(p2pool|miner|nxt|zcash|tether|ether|btc|monero|markleroot|xmr|(bit|lite|name|peer|doge|grid|prim|vert|tit|pot)coin)\b", 13 | "type": "string", 14 | "scopes": [ "code", "comment" ], 15 | "modifiers": [ "i" ], 16 | "confidence": "high" 17 | } 18 | ] 19 | } 20 | ] -------------------------------------------------------------------------------- /src/Shared.CLI/Resources/BackdoorRules/dependency_confusion.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Dependency Confusion: Attack Pattern (Dependency)", 4 | "id": "BD001001", 5 | "description": "Dependency Confusion: Attack Pattern (Dependency)", 6 | "tags": [ 7 | "Security.DependencyConfusion.AttackPattern.Dependency" 8 | ], 9 | "severity": "critical", 10 | "applies_to": ["package.json"], 11 | "patterns": [ 12 | { 13 | "pattern": "daemonsec637", 14 | "type": "string", 15 | "scopes": [ "code", "comment" ], 16 | "modifiers": [ "i" ], 17 | "confidence": "high" 18 | }, 19 | { 20 | "pattern": "infosecgirl", 21 | "type": "string", 22 | "scopes": [ "code", "comment" ], 23 | "modifiers": [ "i" ], 24 | "confidence": "high" 25 | }, 26 | { 27 | "pattern": "bountyrecon/most-secure-package", 28 | "type": "string", 29 | "scopes": [ "code", "comment" ], 30 | "modifiers": [ "i" ], 31 | "confidence": "high" 32 | } 33 | ] 34 | }, 35 | { 36 | "name": "Dependency Confusion: Attack Pattern (Suspicious Hostname)", 37 | "id": "BD001002", 38 | "description": "Dependency Confusion: Attack Pattern (Suspicious Hostname)", 39 | "tags": [ 40 | "Security.DependencyConfusion.AttackPattern.SuspiciousHostname" 41 | ], 42 | "applies_to": ["javascript", "package.json"], 43 | "severity": "critical", 44 | "patterns": [ 45 | { 46 | "pattern": ".{1,45}(pipedream\\.net|ceye\\.io|burpcollaborator\\.net|interact\\.sh|requestbin\\.net|nmnfbb\\.com)", 47 | "type": "regex", 48 | "scopes": [ "code", "comment" ], 49 | "modifiers": [ "i" ], 50 | "confidence": "high" 51 | } 52 | ] 53 | }, 54 | { 55 | "name": "Dependency Confusion: Attack Pattern (Exfiltration over DNS)", 56 | "id": "BD001003", 57 | "description": "Dependency Confusion: Attack Pattern (Exfiltration over DNS)", 58 | "tags": [ 59 | "Security.DependencyConfusion.AttackPattern.ExfiltrationOverDNS" 60 | ], 61 | "applies_to": ["javascript", "package.json"], 62 | "severity": "critical", 63 | "patterns": [ 64 | { 65 | "pattern": "resolve4\\((.+){2}.*", 66 | "type": "regex", 67 | "scopes": [ "code" ], 68 | "modifiers": [ "i" ], 69 | "confidence": "high" 70 | } 71 | ] 72 | } 73 | ] -------------------------------------------------------------------------------- /src/Shared.CLI/Resources/BackdoorRules/ioc.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Backdoor: IOC (Common Commands)", 4 | "id": "BD000900", 5 | "description": "Backdoor: Reverse Shell", 6 | "applies_to": [ "powershell" ], 7 | "tags": [ 8 | "Security.Backdoor.ReverseShell" 9 | ], 10 | "severity": "important", 11 | "patterns": [ 12 | { 13 | "pattern": "(\\-bxor|cpassword|getnetworkcredential|securestringtobstr|shellexecute|processtartinfo|activexobject|regsvr32|mimikatz|new-scheduledtask|loadlibrary|ptrtostructure|getdelegateforfunctionpointer|unsafenativemethods|structuretoptr|virtualprotect)", 14 | "type": "regexword", 15 | "scopes": [ "code" ], 16 | "modifiers": [ "i" ], 17 | "confidence": "medium" 18 | } 19 | ] 20 | } 21 | ] -------------------------------------------------------------------------------- /src/Shared.CLI/Resources/BackdoorRules/lolbas.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "LOLBAS: Windows Indicator", 4 | "id": "BD000600", 5 | "description": "Backdoor: LOLBAS: Windows Indicator", 6 | "tags": [ 7 | "Security.Backdoor.LOLBAS.Windows" 8 | ], 9 | "severity": "moderate", 10 | "patterns": [ 11 | { 12 | "pattern": "\\s(advpack\\.dll|appvlp|at|atbroker|bash|bginfo|bitsadmin|cdb|certutil|cl_invocation\\.ps1|cl_mutexverifiers\\.ps1|cmd|cmdkey|cmstp|comsvcs\\.dll|control|csc|cscript|csi|devtoolslauncher|dfsvc|diskshadow|dnscmd|dnx|dotnet|dxcap|esentutl|eventvwr|excel|expand|extexport|extrac32|findstr|forfiles|ftp|gfxdownloadwrapper|gpscript|hh|ie4uinit|ieadvpack\\.dll|ieaframe\\.dll|ic|infdefaultinstall|installutil|jsc|makecab|manage-bde\\.wsf|mavinject|mftrace|microsoft\\.workflow\\.compiler|mmc|msbuild|msconfig|msdeploy|msdt|mshta|mshtml\\.dll|msc|msxsl|netsh|odbcconf|pcalua|pcwrun|pcwutl\\.dll|pester\\.bat|powerpnt|presentationhost|pubprn\\.vbs|rcsi|reg|regasm|regedit|register-cimprovider|regsvcs|regsvr32|rpcping|rundll32|runonce|runscripthelper|sc|schtasks|scriptrunner|setupapi\\.dll|shdocvw\\.dll|shell32\\.dll|slmgr\\.vbs|sqldumper|sqlps|sqltoolsps|squirrel|syncappvpublishingserver|syncappvpublishingserver\\.vbs|syssetup\\.dll|te|tracker|tttracer|update|url\\.dll|verclsid|vsjitdebugger|wab|winrm\\.vbs|winword|wmic|wscript|wsl|wsreset|xwizard|zipfldr\\.dll)\\s", 13 | "type": "regex", 14 | "scopes": [ "code" ], 15 | "modifiers": [ "i" ], 16 | "confidence": "low" 17 | } 18 | ] 19 | }, 20 | { 21 | "name": "LOLBAS: Linux Indicator", 22 | "id": "BD000610", 23 | "description": "Backdoor: LOLBAS: Linux Indicator", 24 | "tags": [ 25 | "Security.Backdoor.LOLBAS.Linux" 26 | ], 27 | "severity": "moderate", 28 | "patterns": [ 29 | { 30 | "pattern": "\\s(apt|apt\\-get|aria2c|arp|ash|awk|base64|bash|bpftrace|busybox|cat|chmod|chown|cp|cpan|cpulimit|crontab|csh|curl|cut|dash|dd|diff|dmesg|dmsetup|dnf|docker|dpkg|easy_install|ed|emacs|env|expand|expect|facter|find|finger|flock|fmt|ftp|gawk|gdb|gimp|git|grep|head|iftop|ionice|ip|irb|jjs|journalctl|jrunscript|ksh|ld\\.so|ldconfig|logsave|ltrace|lua|mail|mawk|mount|mtr|mv|mysql|nano|nawk|nc|nice|nl|nmap|node|od|openssl|perl|pg|php|pic|pico|pip|puppet|readelf|red|rlogin|rlwrap|rpm|rpmquery|rsync|ruby|run\\-mailcap|run\\-parts|rvim|scp|screen|script|sed|service|setarch|sftp|shuf|smbclient|socat|sort|sqlite3|ssh|start\\-stop\\-daemon|stdbuf|strace|systemctl|tail|tar|taskset|tclsh|tcpdump|tee|telnet|tftp|time|timeout|tmux|top|ul|unexpand|uniq|unshare|vi|vim|watch|wget|whois|wish|xargs|xxd|yum|zsh|zypper)\\s", 31 | "type": "regex", 32 | "scopes": [ "code" ], 33 | "modifiers": [ "i" ], 34 | "confidence": "low" 35 | } 36 | ] 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /src/Shared.CLI/Resources/BackdoorRules/pastebin.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Backdoor: Pastebin", 4 | "id": "BD000500", 5 | "description": "Backdoor: Pastebin", 6 | "tags": [ 7 | "Security.Backdoor.Pastebin" 8 | ], 9 | "severity": "moderate", 10 | "patterns": [ 11 | { 12 | "pattern": "pastebin|zerobin|ghostbin|hastebin|klgrth\\.io", 13 | "type": "regexword", 14 | "scopes": [ "code", "comment" ], 15 | "modifiers": [ "i" ], 16 | "confidence": "high" 17 | } 18 | ] 19 | } 20 | ] -------------------------------------------------------------------------------- /src/Shared.CLI/Resources/BackdoorRules/reverse_shell.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Backdoor: Reverse Shell", 4 | "id": "BD000300", 5 | "description": "Backdoor: Reverse Shell", 6 | "tags": [ 7 | "Security.Backdoor.ReverseShell" 8 | ], 9 | "severity": "moderate", 10 | "patterns": [ 11 | { 12 | "pattern": "(shell\\.now\\.sh|tcp\\.ngrok\\.io|reverse shell|reverse-shell\\.sh)", 13 | "type": "regexword", 14 | "scopes": [ "code", "comment" ], 15 | "modifiers": [ "i" ], 16 | "confidence": "high" 17 | } 18 | ] 19 | }, 20 | { 21 | "name": "Backdoor: Reverse Shell", 22 | "id": "BD000301", 23 | "description": "Backdoor: Reverse Shell", 24 | "tags": [ 25 | "Security.Backdoor.ReverseShell" 26 | ], 27 | "severity": "moderate", 28 | "applies_to": ["package.json"], 29 | "patterns": [ 30 | { 31 | "pattern": "ncat.*-e /bin/(ba)?sh", 32 | "type": "regex", 33 | "scopes": [ "code", "comment" ], 34 | "modifiers": [ "i" ], 35 | "confidence": "high" 36 | } 37 | ] 38 | } 39 | ] -------------------------------------------------------------------------------- /src/Shared.CLI/Resources/CryptographyRules/implementation-asymmetric.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "OAEP", 4 | "id": "DS802020", 5 | "description": "An implementation bcrypt-pbkdf.", 6 | "recommendation": "", 7 | "tags": [ 8 | "Cryptography.Implementation.BCryptPBKDF" 9 | ], 10 | "severity": "important", 11 | "_comment": "", 12 | "rule_info": "", 13 | "patterns": [ 14 | ] 15 | } 16 | ] -------------------------------------------------------------------------------- /src/Shared.CLI/Resources/CryptographyRules/implementation-block-cipher.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Implementation of AES", 4 | "id": "DS802040", 5 | "description": "An implementation AES.", 6 | "recommendation": "", 7 | "tags": [ 8 | "Cryptography.Implementation.BlockCipher.AES" 9 | ], 10 | "severity": "important", 11 | "_comment": "", 12 | "rule_info": "", 13 | "patterns": [ 14 | { 15 | "pattern": "c66363a5|51f4a750|766df6ad", 16 | "type": "regex", 17 | "modifiers": [ "i" ], 18 | "scopes": [ 19 | "code" 20 | ], 21 | "_comment": "Magic constant for AES (hex)" 22 | }, 23 | { 24 | "pattern": "3328402341|1374988112|1986918061", 25 | "type": "regex", 26 | "modifiers": [], 27 | "scopes": [ 28 | "code" 29 | ], 30 | "_comment": "Magic constant for AES (decimal)" 31 | } 32 | ] 33 | }, 34 | { 35 | "name": "DES", 36 | "id": "DS802042", 37 | "description": "DES", 38 | "recommendation": "", 39 | "tags": [ 40 | "Cryptography.Implementation.BlockCipher.DES" 41 | ], 42 | "severity": "important", 43 | "_comment": "", 44 | "rule_info": "", 45 | "patterns": [ 46 | { 47 | "pattern": "14,\\s{0,3}4,\\s{0,3}13,\\s{0,3}1,\\s{0,3}2,\\s{0,3}15", 48 | "type": "regex", 49 | "modifiers": [], 50 | "scopes": [ 51 | "code" 52 | ], 53 | "_comment": "DES S1 structure" 54 | }, 55 | { 56 | "pattern": "0x7fef7fe0", 57 | "type": "regex", 58 | "modifiers": [], 59 | "scopes": [ 60 | "code" 61 | ], 62 | "_comment": "DES S2 structure" 63 | } 64 | ] 65 | }, 66 | { 67 | "name": "Implementation of SM4", 68 | "id": "DS802050", 69 | "description": "An implementation SM4", 70 | "recommendation": "", 71 | "tags": [ 72 | "Cryptography.Implementation.BlockCipher.SM4" 73 | ], 74 | "severity": "important", 75 | "_comment": "", 76 | "rule_info": "", 77 | "patterns": [ 78 | { 79 | "pattern": "d6.{0,10}90.{0,10}e9.{0,10}fe.{0,10}cc.{0,10}e1.{0,10}3d", 80 | "type": "regex", 81 | "modifiers": [ "i" ], 82 | "scopes": [ 83 | "all" 84 | ], 85 | "_comment": "Magic Constant for SM4" 86 | } 87 | ] 88 | } 89 | ] -------------------------------------------------------------------------------- /src/Shared.CLI/Resources/CryptographyRules/implementation-crypto-generic.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Cryptographic Terms", 4 | "id": "DS802030", 5 | "description": "Cryptographic Terms", 6 | "recommendation": "", 7 | "tags": [ 8 | "Cryptography.GenericImplementation.CryptographicTerms" 9 | ], 10 | "severity": "moderate", 11 | "_comment": "", 12 | "rule_info": "", 13 | "patterns": [ 14 | { 15 | "pattern": "(roundkey|keyround|mixcolumns|s-?box|key\\s*schedule|(linear congruential)|(substitution box)|publickeymodulus|publickeyexponent)", 16 | "type": "regex", 17 | "scopes": [ "all" ], 18 | "modifiers": [ "i" ], 19 | "_comment": "Terms that are often used with crypto implementations" 20 | } 21 | ] 22 | }, 23 | { 24 | "name": "Cryptographic Terms (Hashing)", 25 | "id": "DS802031", 26 | "description": "Cryptographic Terms (Hashing)", 27 | "recommendation": "", 28 | "tags": [ 29 | "Cryptography.GenericImplementation.CryptographicTerms.Hashing" 30 | ], 31 | "severity": "moderate", 32 | "_comment": "", 33 | "rule_info": "", 34 | "patterns": [ 35 | { 36 | "pattern": "hash.digest", 37 | "type": "regex", 38 | "scopes": [ "all" ], 39 | "modifiers": [ "i" ], 40 | "_comment": "Suggests a call to a cryptographic hash function." 41 | } 42 | ] 43 | } 44 | ] -------------------------------------------------------------------------------- /src/Shared.CLI/Resources/CryptographyRules/implementation-hash.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/OSSGadget/d2cc60070831192660c98974afbddb036d07a928/src/Shared.CLI/Resources/CryptographyRules/implementation-hash.json -------------------------------------------------------------------------------- /src/Shared.CLI/Resources/CryptographyRules/implementation-prng.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Use of random.org", 4 | "id": "DS802020", 5 | "description": "Use of random.org", 6 | "recommendation": "", 7 | "tags": [ 8 | "Cryptography.Implementation.PRNG.RandomOrg" 9 | ], 10 | "severity": "important", 11 | "_comment": "", 12 | "rule_info": "", 13 | "patterns": [ 14 | { 15 | "pattern": "api.random.org", 16 | "type": "string", 17 | "modifiers": [ "i" ], 18 | "scopes": [ 19 | "code" 20 | ], 21 | "_comment": "Random.org API" 22 | } 23 | ] 24 | }, 25 | { 26 | "name": "LCG-looking construct", 27 | "id": "DS802021", 28 | "description": "LCG-looking construct", 29 | "recommendation": "", 30 | "tags": [ 31 | "Cryptography.Implementation.PRNG.LCG" 32 | ], 33 | "severity": "important", 34 | "_comment": "", 35 | "rule_info": "", 36 | "patterns": [ 37 | { 38 | "pattern": "=.{0,10}\\S+\\s{0,10}\\*\\s{0,10}\\S+\\s{0,10}\\+\\s{0,10}\\S+\\s{0,10}\\)\\s{0,10}\\%\\s{0,10}\\S{1,10}", 39 | "type": "regex", 40 | "modifiers": [ "i" ], 41 | "scopes": [ 42 | "code" 43 | ], 44 | "_comment": "x = (a * b + c) % d" 45 | }, 46 | { 47 | "pattern": "=.{0,10}\\S+\\s{0,10}\\*\\s{0,10}\\S+\\s{0,10}\\)\\s{0,10}\\%\\s{0,10}\\S{1,10}", 48 | "type": "regex", 49 | "modifiers": [ "i" ], 50 | "scopes": [ 51 | "code" 52 | ], 53 | "_comment": "x = (a * b) % d" 54 | }, 55 | { 56 | "pattern": "1013904223|18851643", 57 | "type": "regex", 58 | "modifiers": [ "i" ], 59 | "scopes": [ 60 | "code" 61 | ], 62 | "_comment": "https://github.com/francoislaberge/arbitrary/blob/master/src/Generator.js" 63 | } 64 | ] 65 | }, 66 | { 67 | "name": "LCG-looking construct", 68 | "id": "DS802022", 69 | "description": "LCG-looking construct", 70 | "recommendation": "", 71 | "tags": [ 72 | "Cryptography.Implementation.PRNG.LCG" 73 | ], 74 | "severity": "important", 75 | "_comment": "", 76 | "rule_info": "", 77 | "patterns": [ 78 | { 79 | "pattern": "1013904223|18851643", 80 | "type": "regex", 81 | "modifiers": [ "i" ], 82 | "scopes": [ 83 | "code" 84 | ], 85 | "_comment": "https://github.com/francoislaberge/arbitrary/blob/master/src/Generator.js" 86 | } 87 | ] 88 | } 89 | ] -------------------------------------------------------------------------------- /src/Shared.CLI/Resources/CryptographyRules/implementation-signature.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Implementation of Ed25519", 4 | "id": "DS802300", 5 | "description": "Implementation of Ed25519", 6 | "recommendation": "", 7 | "tags": [ 8 | "Cryptography.Implementation.Ed25519" 9 | ], 10 | "severity": "important", 11 | "_comment": "", 12 | "rule_info": "", 13 | "patterns": [ 14 | { 15 | "pattern": "78a3.{0,10}1359.{0,10}4dca", 16 | "type": "regex", 17 | "modifiers": [ "i" ], 18 | "scopes": [ 19 | "code" 20 | ], 21 | "_comment": "Ed25519 D variable" 22 | } 23 | ] 24 | } 25 | ] -------------------------------------------------------------------------------- /src/Shared.CLI/Resources/CryptographyRules/implementation-stream-cipher.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Implementation of Salsa20/ChaCha", 4 | "id": "DS802043", 5 | "description": "ChaCha", 6 | "recommendation": "", 7 | "tags": [ 8 | "Cryptography.Implementation.StreamCipher.ChaCha", 9 | "Cryptography.Implementation.StreamCipher.Salsa20" 10 | ], 11 | "severity": "important", 12 | "_comment": "", 13 | "rule_info": "https://en.wikipedia.org/wiki/Salsa20", 14 | "patterns": [ 15 | { 16 | "pattern": "61707865|3320646e", 17 | "type": "regex", 18 | "modifiers": [ "i" ], 19 | "scopes": [ 20 | "code" 21 | ], 22 | "_comment": "ChaCha constants (hex)" 23 | }, 24 | { 25 | "pattern": "1634760805|857760878", 26 | "type": "regex", 27 | "modifiers": [], 28 | "scopes": [ 29 | "code" 30 | ], 31 | "_comment": "ChaCha constants (decimal)" 32 | } 33 | ] 34 | } 35 | ] -------------------------------------------------------------------------------- /src/Shared.CLI/Resources/CryptographyRules/implementation-symmetric.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Skip32", 4 | "id": "DS802041", 5 | "description": "Skip32", 6 | "recommendation": "", 7 | "tags": [ 8 | "Cryptography.Implementation.PRNG.Skip32" 9 | ], 10 | "severity": "important", 11 | "_comment": "", 12 | "rule_info": "", 13 | "patterns": [ 14 | { 15 | "pattern": "a3.{0,10}d7.{0,10}09.{0,10}83.{0,10}f8.{0,10}48.{0,10}f6", 16 | "type": "regex", 17 | "modifiers": [ "i" ], 18 | "scopes": [ 19 | "code" 20 | ], 21 | "_comment": "https://wiki.postgresql.org/wiki/Skip32_(crypt_32_bits)" 22 | } 23 | ] 24 | }, 25 | 26 | { 27 | "name": "ChaCha", 28 | "id": "DS802043", 29 | "description": "ChaCha", 30 | "recommendation": "", 31 | "tags": [ 32 | "Cryptography.Implementation.ChaCha" 33 | ], 34 | "severity": "important", 35 | "_comment": "", 36 | "rule_info": "", 37 | "patterns": [ 38 | { 39 | "pattern": "61707865|6b206574", 40 | "type": "regex", 41 | "modifiers": [], 42 | "scopes": [ 43 | "code" 44 | ], 45 | "_comment": "ChaCha" 46 | } 47 | ] 48 | } 49 | ] -------------------------------------------------------------------------------- /src/Shared.CLI/Tools/DetectCryptographyTool/Issue.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.OssGadget.Tools 4 | { 5 | using Microsoft.ApplicationInspector.RulesEngine; 6 | 7 | public record Issue 8 | { 9 | public Boundary Boundary { get; } 10 | public Location StartLocation { get; } 11 | public Location EndLocation { get; } 12 | public Rule Rule { get; } 13 | 14 | public Issue(Boundary Boundary, Location StartLocation, Location EndLocation, Rule Rule) 15 | { 16 | this.Boundary = Boundary; 17 | this.StartLocation = StartLocation; 18 | this.EndLocation = EndLocation; 19 | this.Rule = Rule; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Tools/DiffTool/Diff.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.CST.OpenSource.OssGadget.Tools 7 | { 8 | public class Diff 9 | { 10 | public enum LineType 11 | { 12 | None, 13 | Added, 14 | Removed, 15 | Context 16 | } 17 | public int startLine1 { get; set; } = -1; 18 | public int endLine1 { get { return startLine1 == -1 ? -1 : Math.Max(startLine1, startLine1 + text1.Count - 1); } } 19 | public int startLine2 { get; set; } = -1; 20 | public int endLine2 { get { return startLine2 == -1 ? -1 : Math.Max(startLine2, startLine2 + text2.Count - 1); } } 21 | public List beforeContext { get; private set; } = new List(); 22 | public List text1 { get; private set; } = new List(); 23 | public List text2 { get; private set; } = new List(); 24 | public List afterContext { get; private set; } = new List(); 25 | public LineType lastLineType { get; private set; } = LineType.None; 26 | 27 | public void AddBeforeContext(string context) 28 | { 29 | beforeContext.Add(context); 30 | lastLineType = LineType.Context; 31 | } 32 | public void AddAfterContext(string context) 33 | { 34 | afterContext.Add(context); 35 | lastLineType = LineType.Context; 36 | } 37 | public void AddText1(string content) 38 | { 39 | text1.Add(content); 40 | lastLineType = LineType.Removed; 41 | } 42 | public void AddText2(string content) 43 | { 44 | text2.Add(content); 45 | lastLineType = LineType.Added; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Shared.CLI/Tools/HealthTool/BaseHealthAlgorithm.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | using Microsoft.CST.OpenSource.Helpers; 4 | using System.Threading.Tasks; 5 | 6 | namespace Microsoft.CST.OpenSource.OssGadget.Tools.HealthTool 7 | { 8 | /// 9 | /// Abstract base class for health algorithms 10 | /// 11 | internal abstract class BaseHealthAlgorithm 12 | { 13 | public BaseHealthAlgorithm() 14 | { 15 | EnvironmentHelper.OverrideEnvironmentVariables(this); 16 | } 17 | 18 | public static double Clamp(double value, double min = 0, double max = 100) 19 | { 20 | return (value < min) ? min : (value > max) ? max : value; 21 | } 22 | 23 | /// 24 | /// Wrapper for Github calls for each component of the overall health 25 | /// 26 | /// 27 | public abstract Task GetHealth(); 28 | 29 | /// 30 | /// Logger for each of the subclasses 31 | /// 32 | protected static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Shared.CLI/Tools/ReproducibleTool/BuildHelperScripts/cargo/autobuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PREBUILD_SCRIPT="$1" 4 | BUILD_SCRIPT="$2" 5 | POSTBUILD_SCRIPT="$3" 6 | 7 | if [ ! -z "$PREBUILD_SCRIPT" -a -f "/build-helpers/$PREBUILD_SCRIPT" ]; then 8 | echo "Executing pre-build script: [$PREBUILD_SCRIPT]" 9 | source "/build-helpers/$PREBUILD_SCRIPT" 10 | else 11 | echo "No custom pre-build script found." 12 | fi 13 | 14 | if [ ! -z "$BUILD_SCRIPT" -a -f "/build-helpers/$BUILD_SCRIPT" ]; then 15 | echo "Executing build script: [$BUILD_SCRIPT]" 16 | source "/build-helpers/$BUILD_SCRIPT" 17 | else 18 | echo "No custom build script found. Using auto-builder." 19 | mkdir -p /build-output/work 20 | cargo package --color never -v --target-dir /build-output/workmc 21 | ls -lR /build-output 22 | fi 23 | 24 | if [ ! -z "$POSTBUILD_SCRIPT" -a -f "/build-helpers/$POSTBUILD_SCRIPT" ]; then 25 | echo "Executing post-build script: [$POSTBUILD_SCRIPT]" 26 | source "/build-helpers/$POSTBUILD_SCRIPT" 27 | else 28 | 29 | mv /build-output/work/package/*.crate /build-output/output.archive 30 | fi 31 | 32 | echo "Autobuild complete." 33 | -------------------------------------------------------------------------------- /src/Shared.CLI/Tools/ReproducibleTool/BuildHelperScripts/cpan/autobuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PREBUILD_SCRIPT="$1" 4 | BUILD_SCRIPT="$2" 5 | POSTBUILD_SCRIPT="$3" 6 | 7 | if [ ! -z "$PREBUILD_SCRIPT" -a -f "/build-helpers/$PREBUILD_SCRIPT" ]; then 8 | echo "Executing pre-build script: [$PREBUILD_SCRIPT]" 9 | source "/build-helpers/$PREBUILD_SCRIPT" 10 | else 11 | echo "No custom pre-build script found." 12 | fi 13 | 14 | if [ ! -z "$BUILD_SCRIPT" -a -f "/build-helpers/$BUILD_SCRIPT" ]; then 15 | pwd 16 | echo "Executing build script: [$BUILD_SCRIPT]" 17 | source "/build-helpers/$BUILD_SCRIPT" 18 | else 19 | echo "No custom build script found. Using auto-builder." 20 | 21 | echo "Executing cpan build scripts" 22 | [ -f Build.PL ] && perl Build.PL 23 | [ -f Makefile.PL ] && perl Makefile.PL 24 | make manifest 25 | make 26 | make dist 27 | fi 28 | 29 | if [ ! -z "$POSTBUILD_SCRIPT" -a -f "/build-helpers/$POSTBUILD_SCRIPT" ]; then 30 | echo "Executing post-build script: [$POSTBUILD_SCRIPT]" 31 | source "/build-helpers/$POSTBUILD_SCRIPT" 32 | else 33 | cp *.tar.gz /build-output/output.archive 34 | fi 35 | 36 | echo "Autobuild complete." 37 | -------------------------------------------------------------------------------- /src/Shared.CLI/Tools/ReproducibleTool/BuildHelperScripts/gem/autobuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PREBUILD_SCRIPT="$1" 4 | BUILD_SCRIPT="$2" 5 | POSTBUILD_SCRIPT="$3" 6 | 7 | if [ ! -z "$PREBUILD_SCRIPT" -a -f "/build-helpers/$PREBUILD_SCRIPT" ]; then 8 | echo "Executing pre-build script: [$PREBUILD_SCRIPT]" 9 | source "/build-helpers/$PREBUILD_SCRIPT" 10 | else 11 | echo "No custom pre-build script found." 12 | fi 13 | 14 | if [ ! -z "$BUILD_SCRIPT" -a -f "/build-helpers/$BUILD_SCRIPT" ]; then 15 | pwd 16 | echo "Executing build script: [$BUILD_SCRIPT]" 17 | source "/build-helpers/$BUILD_SCRIPT" 18 | else 19 | echo "No custom build script found. Using auto-builder." 20 | 21 | echo "Executing gem build scripts" 22 | gem build --output /build-output/output.archive 23 | fi 24 | 25 | if [ ! -z "$POSTBUILD_SCRIPT" -a -f "/build-helpers/$POSTBUILD_SCRIPT" ]; then 26 | echo "Executing post-build script: [$POSTBUILD_SCRIPT]" 27 | source "/build-helpers/$POSTBUILD_SCRIPT" 28 | fi 29 | 30 | echo "Autobuild complete." 31 | -------------------------------------------------------------------------------- /src/Shared.CLI/Tools/ReproducibleTool/BuildHelperScripts/npm/@objectisundefined/typo.build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | yarn 4 | yarn run build -------------------------------------------------------------------------------- /src/Shared.CLI/Tools/ReproducibleTool/BuildHelperScripts/npm/autobuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PREBUILD_SCRIPT="$1" 4 | BUILD_SCRIPT="$2" 5 | POSTBUILD_SCRIPT="$3" 6 | 7 | if [ ! -z "$PREBUILD_SCRIPT" -a -f "/build-helpers/$PREBUILD_SCRIPT" ]; then 8 | echo "Executing pre-build script: [$PREBUILD_SCRIPT]" 9 | source "/build-helpers/$PREBUILD_SCRIPT" 10 | else 11 | echo "No custom pre-build script found." 12 | fi 13 | 14 | if [ ! -z "$BUILD_SCRIPT" -a -f "/build-helpers/$BUILD_SCRIPT" ]; then 15 | echo "Executing build script: [$BUILD_SCRIPT]" 16 | source "/build-helpers/$BUILD_SCRIPT" 17 | else 18 | echo "No custom build script found. Using auto-builder." 19 | echo "Executing 'npm install'" 20 | npm install 21 | 22 | echo "Executing npm scripts" 23 | # Note, we expect most of these to fail gracefully 24 | npm run preprepare 25 | npm run prepare 26 | npm run postprepare 27 | 28 | npm run prepack 29 | npm run pack 30 | npm run postpack 31 | 32 | npm run build 33 | npm pack 34 | npm run prepublish 35 | fi 36 | 37 | if [ ! -z "$POSTBUILD_SCRIPT" -a -f "/build-helpers/$POSTBUILD_SCRIPT" ]; then 38 | echo "Executing post-build script: [$POSTBUILD_SCRIPT]" 39 | source "/build-helpers/$POSTBUILD_SCRIPT" 40 | else 41 | echo "No custom post-build script found. Using default packer." 42 | echo "Running 'npm pack'" 43 | npm pack --json > /build-output/output.json 44 | cp *.tgz /build-output/output.archive 45 | fi 46 | 47 | echo "Autobuild complete." 48 | -------------------------------------------------------------------------------- /src/Shared.CLI/Tools/ReproducibleTool/BuildHelperScripts/npm/bluebird.build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | npm install 4 | npm run prepublish release -------------------------------------------------------------------------------- /src/Shared.CLI/Tools/ReproducibleTool/BuildHelperScripts/npm/bluebird.prebuild: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Requires Yarn to be installed 4 | npm -g i yarn 5 | -------------------------------------------------------------------------------- /src/Shared.CLI/Tools/ReproducibleTool/BuildHelperScripts/pypi/autobuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PREBUILD_SCRIPT="$1" 4 | BUILD_SCRIPT="$2" 5 | POSTBUILD_SCRIPT="$3" 6 | 7 | if [ ! -z "$PREBUILD_SCRIPT" -a -f "/build-helpers/$PREBUILD_SCRIPT" ]; then 8 | echo "Executing pre-build script: [$PREBUILD_SCRIPT]" 9 | source "/build-helpers/$PREBUILD_SCRIPT" 10 | else 11 | echo "No custom pre-build script found." 12 | fi 13 | 14 | if [ ! -z "$BUILD_SCRIPT" -a -f "/build-helpers/$BUILD_SCRIPT" ]; then 15 | pwd 16 | echo "Executing build script: [$BUILD_SCRIPT]" 17 | source "/build-helpers/$BUILD_SCRIPT" 18 | else 19 | echo "No custom build script found. Using auto-builder." 20 | 21 | echo "Executing Python build scripts" 22 | python -m pip install --upgrade build 23 | python -mbuild 24 | fi 25 | 26 | if [ ! -z "$POSTBUILD_SCRIPT" -a -f "/build-helpers/$POSTBUILD_SCRIPT" ]; then 27 | echo "Executing post-build script: [$POSTBUILD_SCRIPT]" 28 | source "/build-helpers/$POSTBUILD_SCRIPT" 29 | else 30 | tar cvfz /build-output/output.archive dist/* 31 | fi 32 | 33 | echo "Autobuild complete." -------------------------------------------------------------------------------- /src/Shared.CLI/Tools/ReproducibleTool/Helpers/DataObjects.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | using System.Collections.Generic; 4 | 5 | namespace Microsoft.CST.OpenSource.Reproducibility 6 | { 7 | public class ReproducibleToolResult 8 | { 9 | public string? PackageUrl { get; set; } 10 | 11 | public bool IsReproducible 12 | { 13 | get 14 | { 15 | if (Results == null) 16 | { 17 | return false; 18 | } 19 | 20 | foreach (StrategyResult? result in Results) 21 | { 22 | if (result.IsSuccess && !result.IsError) 23 | { 24 | return true; 25 | } 26 | } 27 | return false; 28 | } 29 | } 30 | 31 | public List? Results { get; set; } 32 | } 33 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Tools/ReproducibleTool/Strategies/PackageContainedInSourceStrategy.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | using NLog; 4 | using System.IO; 5 | using System.Linq; 6 | 7 | namespace Microsoft.CST.OpenSource.Reproducibility 8 | { 9 | internal class PackageContainedInSourceStrategy : BaseStrategy 10 | { 11 | public override StrategyPriority PRIORITY => StrategyPriority.Medium; 12 | 13 | public PackageContainedInSourceStrategy(StrategyOptions options) : base(options) 14 | { 15 | } 16 | 17 | public override bool StrategyApplies() 18 | { 19 | return GenericStrategyApplies(new[] { Options.SourceDirectory, Options.PackageDirectory }); 20 | } 21 | 22 | public override StrategyResult? Execute() 23 | { 24 | Logger.Debug("Executing {0} reproducibility strategy.", GetType().Name); 25 | if (!StrategyApplies()) 26 | { 27 | Logger.Debug("Strategy does not apply, so cannot execute."); 28 | return null; 29 | } 30 | 31 | StrategyResult? strategyResult = new StrategyResult() 32 | { 33 | Strategy = GetType() 34 | }; 35 | 36 | if (Options.IncludeDiffoscope) 37 | { 38 | string? diffoscopeTempDir = Path.Join(Options.TemporaryDirectory, "diffoscope"); 39 | string? diffoscopeResults = GenerateDiffoscope(diffoscopeTempDir, Options.SourceDirectory!, Options.PackageDirectory!); 40 | strategyResult.Diffoscope = diffoscopeResults; 41 | } 42 | 43 | System.Collections.Generic.IEnumerable? diffResults = OssReproducibleHelpers.DirectoryDifference(Options.PackageDirectory!, Options.SourceDirectory!, Options.DiffTechnique); 44 | int diffResultsOriginalCount = diffResults.Count(); 45 | diffResults = diffResults.Where(d => !IgnoreFilter.IsIgnored(Options.PackageUrl, GetType().Name, d.Filename)); 46 | strategyResult.NumIgnoredFiles += (diffResultsOriginalCount - diffResults.Count()); 47 | strategyResult.AddDifferencesToStrategyResult(diffResults); 48 | 49 | return strategyResult; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/Shared.CLI/Tools/ReproducibleTool/Strategies/PackageIgnoreList.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file contains ignore patterns for different strategies 3 | # The format of each line is: 4 | # A:B:C 5 | # where: 6 | # A => the Package URL type (e.g. npm, pypi), or '*', meaning all types 7 | # B => the strategy name (just the class name, like 'AutoBuildProducesSamePackage') 8 | # C => the regex that matches the files to ignore 9 | # 10 | # 11 | # All files 12 | *:*:^.*/\.git/.*$ 13 | *:*:^.*\.txt$ 14 | *:*:^.*\.md$ 15 | *:*:^.*\.rst$ 16 | *:*:^.*changelog(\.[a-z]+)?$ 17 | 18 | # NPM 19 | # Oryx performs a full build, which puts a lot of content in node_modules, which isn't useful. 20 | npm:OryxBuildStrategy:^.*/node_modules/.*$ 21 | 22 | # RubyGems 23 | gem:*:^.*metadata\.gz/metadata$ 24 | gem:*:^.*checksums\.yaml\.gz/checksums\.yaml$ 25 | 26 | # PyPI 27 | pypi:*:(^|.*/)METADATA$ 28 | pypi:*:(^|.*/)RECORD$ 29 | pypi:*:(^|.*/)WHEEL$ 30 | pypi:*:(^|.*/)PKG-INFO$ 31 | pypi:*:(^|.*/)LICENSE$ 32 | 33 | # CPAN 34 | cpan:*:(^|.*/)META\.json$ 35 | cpan:*:(^|.*/)META\.yml$ 36 | cpan:*:(^|.*/)MANIFEST$ 37 | -------------------------------------------------------------------------------- /src/Shared/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | using System.Runtime.CompilerServices; 4 | 5 | [assembly: InternalsVisibleTo("oss-tests")] 6 | [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] -------------------------------------------------------------------------------- /src/Shared/Contracts/IManagerPackageVersionMetadata.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Contracts; 4 | 5 | /// 6 | /// An interface representing the metadata returned from a project manager's API for a package version's metadata, won't contain extra or calculated properties. 7 | /// 8 | public interface IManagerPackageVersionMetadata 9 | { 10 | /// 11 | /// The name of the package. 12 | /// 13 | string Name { get; } 14 | 15 | /// 16 | /// The version of the package. 17 | /// 18 | string Version { get; } 19 | } -------------------------------------------------------------------------------- /src/Shared/Contracts/IPackageExistence.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Contracts; 4 | 5 | /// 6 | /// An interface representing the existence of a package/version. 7 | /// 8 | public interface IPackageExistence 9 | { 10 | /// 11 | /// Gets if the package/version currently exists. 12 | /// 13 | bool Exists { get; } 14 | } -------------------------------------------------------------------------------- /src/Shared/Contracts/IProjectManagerFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Contracts; 4 | 5 | using PackageManagers; 6 | using PackageUrl; 7 | using System; 8 | 9 | public interface IProjectManagerFactory 10 | { 11 | /// 12 | /// Creates an appropriate project manager for a given its . 13 | /// 14 | /// The for the package to create the project manager for. 15 | /// The new destination directory, if provided. 16 | /// The to wait before the request times out. 17 | /// The implementation of for this 's type. 18 | IBaseProjectManager? CreateProjectManager(PackageURL purl, string destinationDirectory = ".", TimeSpan? timeout = null); 19 | } -------------------------------------------------------------------------------- /src/Shared/Contracts/ITypedManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Contracts; 4 | 5 | using Model; 6 | using PackageUrl; 7 | using Polly.Retry; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Net; 11 | using System.Net.Http; 12 | using System.Threading.Tasks; 13 | 14 | public interface ITypedManager : IBaseProjectManager where TArtifactUriType : Enum 15 | { 16 | /// 17 | /// Gets the relevant URI(s) to download the files related to a . 18 | /// 19 | /// The to get the URI(s) for. 20 | /// A list of the relevant . 21 | /// Returns the expected URIs for resources. Does not validate that the URIs resolve at the moment of enumeration. 22 | [Obsolete(message: $"Deprecated in favor of {nameof(GetArtifactDownloadUrisAsync)}.")] 23 | IEnumerable> GetArtifactDownloadUris(PackageURL purl); 24 | 25 | /// 26 | /// Gets the relevant URI(s) to download the files related to a . 27 | /// 28 | /// The to get the URI(s) for. 29 | /// If the data should be retrieved from the cache. Defaults to true. 30 | /// A list of the relevant . 31 | /// Returns the expected URIs for resources. Does not validate that the URIs resolve at the moment of enumeration. 32 | IAsyncEnumerable> GetArtifactDownloadUrisAsync(PackageURL purl, bool useCache = true); 33 | 34 | /// 35 | /// Gets all s associated with an owner. 36 | /// 37 | /// The username of the owner. 38 | /// If the data should be retrieved from the cache. Defaults to true. 39 | /// A list of the s from this owner. 40 | IAsyncEnumerable GetPackagesFromOwnerAsync(string owner, bool useCache = true); 41 | 42 | /// 43 | /// Check to see if the exists. 44 | /// 45 | /// The to check if exists. 46 | /// An optional to use with the http request. 47 | /// If the request returns . 48 | Task UriExistsAsync(Uri artifactUri, AsyncRetryPolicy? policy = null); 49 | } -------------------------------------------------------------------------------- /src/Shared/DefaultHttpClientFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource 4 | { 5 | using Microsoft.CST.OpenSource.Helpers; 6 | using System; 7 | using System.Net.Http; 8 | 9 | /// 10 | /// This is the HttpClientFactory that will be used if one is not specified. This factory lazily constructs a single HttpClient and presents it for reuse to reduce resource usage. 11 | /// 12 | public sealed class DefaultHttpClientFactory : IHttpClientFactory 13 | { 14 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0044:Add readonly modifier", Justification = "Modified through reflection.")] 15 | public string ENV_HTTPCLIENT_USER_AGENT { get; set; } = "microsoft_oss_gadget (https://github.com/microsoft/OSSGadget)"; 16 | 17 | public DefaultHttpClientFactory(string? userAgent = null) 18 | { 19 | EnvironmentHelper.OverrideEnvironmentVariables(this); 20 | 21 | _httpClientLazy = new(() => 22 | { 23 | HttpClient cli = new(handler); 24 | cli.DefaultRequestHeaders.UserAgent.ParseAdd(userAgent ?? ENV_HTTPCLIENT_USER_AGENT); 25 | return cli; 26 | }); 27 | } 28 | 29 | private static readonly SocketsHttpHandler handler = new() 30 | { 31 | AllowAutoRedirect = true, 32 | UseCookies = false, 33 | MaxAutomaticRedirections = 5, 34 | PooledConnectionIdleTimeout = TimeSpan.FromSeconds(30), 35 | PooledConnectionLifetime = TimeSpan.FromSeconds(30), 36 | AutomaticDecompression = System.Net.DecompressionMethods.All, 37 | SslOptions = new System.Net.Security.SslClientAuthenticationOptions() { 38 | CertificateRevocationCheckMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.Online 39 | } 40 | }; 41 | 42 | private readonly Lazy _httpClientLazy; 43 | 44 | /// 45 | /// Returns the singleton HttpClient for this factory. 46 | /// 47 | /// 48 | /// 49 | public HttpClient CreateClient(string name) => _httpClientLazy.Value; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Shared/Exceptions/InvalidProjectManagerException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Exceptions 4 | { 5 | using PackageUrl; 6 | using System; 7 | 8 | /// 9 | /// Exception thrown when the PackageURL has an invalid manager.. 10 | /// 11 | public class InvalidProjectManagerException : Exception 12 | { 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// 16 | public InvalidProjectManagerException(PackageURL packageUrl) 17 | : base($"The package URL: {packageUrl} has an invalid Project Manager.") 18 | { 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/Shared/Extensions/UriExtension.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Extensions; 4 | 5 | using System; 6 | using System.IO; 7 | 8 | public static class UriExtension 9 | { 10 | private static readonly string[] SpecialExtensions = { ".tar.gz", ".tar.bz2" }; 11 | 12 | /// 13 | /// Gets the extension from a . 14 | /// 15 | /// The to get the extension from. 16 | /// The extension from the , or an empty string if it doesn't have one. 17 | public static string GetExtension(this Uri uri) 18 | { 19 | string absolutePath = uri.AbsolutePath; 20 | 21 | foreach (string specialExtension in SpecialExtensions) 22 | { 23 | if (absolutePath.EndsWith(specialExtension)) 24 | { 25 | return specialExtension; 26 | } 27 | } 28 | 29 | return Path.GetExtension(absolutePath); 30 | } 31 | } -------------------------------------------------------------------------------- /src/Shared/Helpers/EnvironmentHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Helpers 4 | { 5 | using System; 6 | using System.Reflection; 7 | 8 | public class EnvironmentHelper 9 | { 10 | public static NLog.ILogger Logger { get; set; } = NLog.LogManager.GetCurrentClassLogger(); 11 | 12 | /// 13 | /// Overrides instance members of the starting with ENV_ with the values of the respective environment variables, if set. 14 | /// Allows users to easily override fields like API endpoint roots. Only strings are supported. 15 | /// 16 | /// Examine this object (using reflection) 17 | public static void OverrideEnvironmentVariables(object targetObject) 18 | { 19 | foreach (PropertyInfo propertyInfo in targetObject.GetType().GetProperties()) 20 | { 21 | if (propertyInfo.PropertyType == typeof(string) && 22 | propertyInfo.Name.StartsWith("ENV_") && 23 | propertyInfo.Name.Length > 4) 24 | { 25 | string? bareName = propertyInfo.Name[4..]; 26 | 27 | string? value = Environment.GetEnvironmentVariable(bareName); 28 | if (value != null) 29 | { 30 | Logger.Debug("Assiging value of {0} to {1}", bareName, propertyInfo.Name); 31 | propertyInfo.SetValue(targetObject, value); 32 | } 33 | } 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Shared/Helpers/FileSystemHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Helpers 4 | { 5 | using NLog; 6 | using System; 7 | using System.IO; 8 | using System.Threading; 9 | 10 | public static class FileSystemHelper 11 | { 12 | static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); 13 | 14 | /// 15 | /// Attempt to delete a directory and its contents with retries. 16 | /// 17 | /// The directory to delete. 18 | /// If true, also delete all the contents of the directory. 19 | /// Number of attempts. Minimum 1. 20 | /// Delay between attempts. Minimum 1. 21 | /// If the directory was deleted. 22 | public static bool RetryDeleteDirectory(string path, bool recursive = true, int attempts = 5, int millisecondsDelay = 10) 23 | { 24 | if (path == null) 25 | return false; 26 | if (attempts < 1) 27 | attempts = 1; 28 | if (millisecondsDelay < 1) 29 | millisecondsDelay = 1; 30 | 31 | for (int i = 0; i < attempts; i++) 32 | { 33 | try 34 | { 35 | if (Directory.Exists(path)) 36 | { 37 | Directory.Delete(path, recursive); 38 | } 39 | if (!Directory.Exists(path)) 40 | { 41 | return true; 42 | } 43 | } 44 | catch(Exception ex) when (ex is IOException) 45 | { 46 | Thread.Sleep(millisecondsDelay); 47 | Logger.Debug("Error deleting [{0}], sleeping for {1} seconds.", path, millisecondsDelay); 48 | } 49 | } 50 | 51 | return false; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Shared/Helpers/PackageUrlJsonConverter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Helpers; 4 | 5 | using PackageUrl; 6 | using System; 7 | using System.Text.Json; 8 | using System.Text.Json.Serialization; 9 | 10 | public class PackageUrlJsonConverter : JsonConverter 11 | { 12 | /// 13 | /// Read the as a string back to the object. 14 | /// 15 | /// The to get the json string. 16 | /// The Type to convert to. 17 | /// The custom options for the converter. 18 | /// The from the json text. 19 | public override PackageURL Read( 20 | ref Utf8JsonReader reader, 21 | Type typeToConvert, 22 | JsonSerializerOptions options) => new(reader.GetString()); 23 | 24 | /// 25 | /// Write the as a string instead of converting it to a json object itself. 26 | /// 27 | /// The to write the json string. 28 | /// The to write. 29 | /// The custom options for the converter. 30 | public override void Write( 31 | Utf8JsonWriter writer, 32 | PackageURL packageUrl, 33 | JsonSerializerOptions options) => 34 | writer.WriteStringValue(packageUrl.ToString()); 35 | } -------------------------------------------------------------------------------- /src/Shared/Metadata/BaseMetadataSource.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource; 4 | 5 | using Helpers; 6 | using System.Threading.Tasks; 7 | using System.Text.Json; 8 | using PackageUrl; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using System.Net.Http; 11 | using System; 12 | using Polly; 13 | using System.Net; 14 | using Polly.Retry; 15 | using Polly.Contrib.WaitAndRetry; 16 | 17 | public abstract class BaseMetadataSource 18 | { 19 | protected static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); 20 | 21 | protected HttpClient HttpClient; 22 | 23 | public BaseMetadataSource() 24 | { 25 | EnvironmentHelper.OverrideEnvironmentVariables(this); 26 | ServiceProvider serviceProvider = new ServiceCollection() 27 | .AddHttpClient() 28 | .BuildServiceProvider(); 29 | 30 | var clientFactory = serviceProvider.GetService() ?? throw new InvalidOperationException(); 31 | HttpClient = clientFactory.CreateClient(); 32 | } 33 | 34 | public async Task GetMetadataForPackageUrlAsync(PackageURL packageUrl, bool useCache = false) 35 | { 36 | return await GetMetadataAsync(packageUrl.Type, packageUrl.Namespace, packageUrl.Name, packageUrl.Version, useCache); 37 | } 38 | public abstract Task GetMetadataAsync(string packageType, string packageNamespace, string packageName, string packageVersion, bool useCache = false); 39 | 40 | /// 41 | /// Loads a URL and returns the JSON document, using a retry policy. 42 | /// 43 | /// The to load. 44 | /// An optional to use with the http request. 45 | /// The resultant JsonDocument, or an exception on failure. 46 | public async Task GetJsonWithRetry(string uri, AsyncRetryPolicy? policy = null) 47 | { 48 | policy ??= Policy 49 | .Handle() 50 | .OrResult(r => (int)r.StatusCode >= 500 || r.StatusCode == HttpStatusCode.TooManyRequests) 51 | .WaitAndRetryAsync(Backoff.DecorrelatedJitterBackoffV2(TimeSpan.FromSeconds(15), retryCount: 5)); 52 | 53 | var result = await policy.ExecuteAsync(() => HttpClient.GetAsync(uri, HttpCompletionOption.ResponseContentRead)); 54 | return await JsonDocument.ParseAsync(await result.Content.ReadAsStreamAsync()); 55 | } 56 | } -------------------------------------------------------------------------------- /src/Shared/Metadata/DepsDevMetadataSource.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource; 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using System.Text.Json; 8 | using System.Linq; 9 | using System.Collections.Generic; 10 | using Microsoft.CST.OpenSource.PackageManagers; 11 | 12 | public class DepsDevMetadataSource : BaseMetadataSource 13 | { 14 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0044:Add readonly modifier", 15 | Justification = "Modified through reflection.")] 16 | public string ENV_DEPS_DEV_ENDPOINT { get; set; } = "https://deps.dev/_"; 17 | 18 | public static readonly List VALID_TYPES = new List() { 19 | "npm", 20 | "go", 21 | "maven", 22 | "pypi", 23 | "cargo" 24 | }; 25 | 26 | public override async Task GetMetadataAsync(string packageType, string packageNamespace, string packageName, string packageVersion, bool useCache = false) 27 | { 28 | var packageTypeEnc = string.Equals(packageType, "golang") ? "go" : packageType; 29 | if (!VALID_TYPES.Contains(packageTypeEnc, StringComparer.InvariantCultureIgnoreCase)) 30 | { 31 | Logger.Warn("Unable to get metadata for [{} {}]. Package type [{}] is not supported. Try another data provider.", packageNamespace, packageName, packageType); 32 | } 33 | var packageNamespaceEnc = packageNamespace?.Replace("@", "%40").Replace("/", "%2F"); 34 | var packageNameEnc = packageName.Replace("@", "%40").Replace("/", "%2F"); 35 | 36 | var fullPackageName = string.IsNullOrWhiteSpace(packageNamespaceEnc) ? 37 | $"{packageNameEnc}" : 38 | $"{packageNamespaceEnc}%2F{packageNameEnc}"; 39 | 40 | // The missing slash in the next line is not a bug. 41 | var url = $"{ENV_DEPS_DEV_ENDPOINT}/s/{packageTypeEnc}/p/{fullPackageName}/v/{packageVersion}"; 42 | try 43 | { 44 | return await BaseProjectManager.GetJsonCache(HttpClient, url, useCache); 45 | } 46 | catch(Exception ex) 47 | { 48 | Logger.Warn("Error loading package: {0}", ex.Message); 49 | return null; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/Shared/Metadata/NativeMetadataSource.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource; 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using System.Text.Json; 8 | using PackageUrl; 9 | using System.Linq; 10 | using System.Collections.Generic; 11 | using Microsoft.CST.OpenSource.PackageManagers; 12 | using System.Reflection; 13 | 14 | public class NativeMetadataSource : BaseMetadataSource 15 | { 16 | public static readonly List VALID_TYPES = new List(); 17 | 18 | static NativeMetadataSource() 19 | { 20 | // Dynamically gather the list of valid types based on whether subtypes of 21 | // BaseProjectManager implement GetMetadataAsync. 22 | var projectManagers = typeof(BaseMetadataSource).Assembly.GetTypes() 23 | .Where(t => t.IsSubclassOf(typeof(BaseProjectManager))); 24 | 25 | foreach (var projectManager in projectManagers.Where(d => d != null)) 26 | { 27 | MethodInfo? method = projectManager.GetMethod("GetMetadataAsync"); 28 | if (method != null) 29 | { 30 | var type = projectManager.GetField("Type", BindingFlags.Public | BindingFlags.Static)?.GetValue(null) as string; 31 | if (type != null) 32 | { 33 | VALID_TYPES.Add(type); 34 | } 35 | } 36 | } 37 | VALID_TYPES.Sort(); 38 | } 39 | 40 | public override async Task GetMetadataAsync(string packageType, string packageNamespace, string packageName, string packageVersion, bool useCache = false) 41 | { 42 | var packageUrl = new PackageURL(packageType, packageNamespace, packageName, packageVersion, null, null); 43 | 44 | var packageManager = ProjectManagerFactory.ConstructPackageManager(packageUrl); 45 | if (packageManager != null) 46 | { 47 | try 48 | { 49 | var metadata = await packageManager.GetMetadataAsync(packageUrl); 50 | if (metadata != null) 51 | { 52 | try 53 | { 54 | return JsonDocument.Parse(metadata); 55 | } 56 | catch(Exception ex) 57 | { 58 | Logger.Warn(ex, "Error parsing metadata: {0}", ex.Message); 59 | return JsonSerializer.SerializeToDocument(new Dictionary() { 60 | { "content", metadata } 61 | }); 62 | } 63 | } 64 | } 65 | catch(Exception ex) 66 | { 67 | Logger.Warn(ex, "Error retrieving metadata: {0}", ex.Message); 68 | } 69 | } 70 | return null; 71 | } 72 | } -------------------------------------------------------------------------------- /src/Shared/Model/ArtifactUri.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Model; 4 | 5 | using Extensions; 6 | using System; 7 | using System.IO; 8 | 9 | /// 10 | /// A record to represent the type, uri, extension and optionally the upload time for an artifact associated with a package version. 11 | /// 12 | /// The enum to represent the artifact type. 13 | public record ArtifactUri where T : Enum 14 | { 15 | /// 16 | /// Initializes a new instance of . 17 | /// 18 | /// The type of artifact for this . 19 | /// The this artifact can be found at. 20 | /// The for when this artifact was uploaded to the repository. 21 | public ArtifactUri(T type, Uri uri, DateTime? uploadTime = null) 22 | { 23 | Type = type; 24 | Uri = uri; 25 | UploadTime = uploadTime; 26 | } 27 | 28 | /// 29 | /// Initializes a new instance of . 30 | /// 31 | /// The type of artifact for this . 32 | /// The string of the uri this artifact can be found at. 33 | public ArtifactUri(T type, string uri, DateTime? uploadTime = null) : this(type, new Uri(uri), uploadTime) { } 34 | 35 | /// 36 | /// The enum representing the artifact type for the project manager associated with this artifact. 37 | /// 38 | public T Type { get; } 39 | 40 | /// 41 | /// The for where this artifact can be found online. 42 | /// 43 | public Uri Uri { get; } 44 | 45 | /// 46 | /// The for when this artifact was uploaded to the repository. 47 | /// 48 | public DateTime? UploadTime { get; } 49 | 50 | /// 51 | /// The file extension for this artifact file. Including the '.' at the beginning. 52 | /// 53 | /// If the file has no extension, it will just be an empty string. 54 | public string Extension => Uri.GetExtension(); 55 | } 56 | -------------------------------------------------------------------------------- /src/Shared/Model/Enums/JsonParsingOption.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Model.Enums; 4 | 5 | /// 6 | /// Special cases used for json parsing. 7 | /// 8 | public enum JsonParsingOption 9 | { 10 | /// 11 | /// No specific option. 12 | /// 13 | None = 0, 14 | 15 | /// 16 | /// Used in Cargo only right now as their files aren't formatted correctly for json. 17 | /// https://raw.githubusercontent.com/rust-lang/crates.io-index/master/ra/nd/rand 18 | /// 19 | NotInArrayNotCsv, 20 | } -------------------------------------------------------------------------------- /src/Shared/Model/Enums/MavenArtifactType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | using System; 4 | using System.ComponentModel; 5 | 6 | namespace Microsoft.CST.OpenSource.Model.Enums; 7 | 8 | /// 9 | /// Maven upstream repositories supported by OSSGadget. 10 | /// 11 | public enum MavenArtifactType 12 | { 13 | [Description(".aar")] 14 | Aar, 15 | 16 | [Description("-client.jar")] 17 | ClientJar, 18 | 19 | [Description(".ear")] 20 | Ear, 21 | 22 | [Description("-javadoc.jar")] 23 | JavadocJar, 24 | 25 | [Description(".pom")] 26 | Pom, 27 | 28 | [Description(".rar")] 29 | Rar, 30 | 31 | [Description("-sources.jar")] 32 | SourcesJar, 33 | 34 | [Description("-tests.jar")] 35 | TestsJar, 36 | 37 | [Description("-tests-sources.jar")] 38 | TestSourcesJar, 39 | 40 | [Description(".war")] 41 | War, 42 | 43 | [Description(".jar")] 44 | Jar, 45 | 46 | Unknown, 47 | } 48 | 49 | /// 50 | /// Extension methods for . 51 | /// 52 | public static class MavenArtifactTypeExtensions 53 | { 54 | public static string GetTypeNameExtension(this MavenArtifactType type) 55 | { 56 | var fieldInfo = type.GetType().GetField(type.ToString()); 57 | var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); 58 | 59 | return attributes.Length > 0 ? attributes[0].Description : string.Empty; 60 | } 61 | } -------------------------------------------------------------------------------- /src/Shared/Model/Enums/PackageRemovalReason.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Model.Enums; 4 | 5 | /// 6 | /// Enum for information about when a package no longer exists on a package manager. 7 | /// 8 | public enum PackageRemovalReason 9 | { 10 | /// 11 | /// When the package was unpublished from the repository/registry by someone. 12 | /// 13 | PackageUnpublished, 14 | 15 | /// 16 | /// When the package/version was removed from the repository/registry by the package manager's administrators. 17 | /// 18 | RemovedByRepository, 19 | } -------------------------------------------------------------------------------- /src/Shared/Model/Enums/PackageVersionRemovalReason.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Model.Enums; 4 | 5 | /// 6 | /// Enum for information about when a package version no longer exists on a package manager. 7 | /// 8 | public enum PackageVersionRemovalReason 9 | { 10 | /// 11 | /// When the version was unpublished from the repository/registry by someone. 12 | /// 13 | VersionUnpublished, 14 | 15 | /// 16 | /// When the package was unpublished from the repository/registry by someone. 17 | /// 18 | PackageUnpublished, 19 | 20 | /// 21 | /// When the package/version was removed from the repository/registry by the package manager's administrators. 22 | /// 23 | RemovedByRepository, 24 | } -------------------------------------------------------------------------------- /src/Shared/Model/Metadata/NuGetV2PackageVersionMetadata.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. 2 | 3 | 4 | using System; 5 | using System.Xml.Serialization; 6 | using Microsoft.CST.OpenSource.Contracts; 7 | 8 | namespace Microsoft.CST.OpenSource.Model.Metadata 9 | { 10 | /// 11 | /// A class to represent Package Metadata for an XML-based package version. 12 | /// 13 | [XmlRoot(ElementName = "entry", Namespace = "http://www.w3.org/2005/Atom")] 14 | public class NuGetV2PackageVersionMetadata : IManagerPackageVersionMetadata 15 | { 16 | [XmlElement(ElementName = "id", Namespace = "http://www.w3.org/2005/Atom")] 17 | public string Id { get; set; } 18 | 19 | [XmlElement(ElementName = "title", Namespace = "http://www.w3.org/2005/Atom")] 20 | public string Title { get; set; } 21 | 22 | [XmlElement(ElementName = "updated", Namespace = "http://www.w3.org/2005/Atom")] 23 | public DateTime Updated { get; set; } 24 | 25 | [XmlElement(ElementName = "author", Namespace = "http://www.w3.org/2005/Atom")] 26 | public Author Author { get; set; } 27 | 28 | [XmlElement(ElementName = "content", Namespace = "http://www.w3.org/2005/Atom")] 29 | public Content Content { get; set; } 30 | 31 | [XmlElement(ElementName = "properties", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata")] 32 | public Properties Properties { get; set; } 33 | 34 | [XmlIgnore] 35 | public string Name => Properties?.Id; 36 | 37 | [XmlIgnore] 38 | public string Version => Properties?.Version; 39 | } 40 | 41 | public class Author 42 | { 43 | [XmlElement(ElementName = "name", Namespace = "http://www.w3.org/2005/Atom")] 44 | public string Name { get; set; } 45 | } 46 | 47 | public class Content 48 | { 49 | [XmlAttribute(AttributeName = "type")] 50 | public string Type { get; set; } 51 | 52 | [XmlAttribute(AttributeName = "src")] 53 | public string Source { get; set; } 54 | } 55 | 56 | [XmlType(Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")] 57 | public class Properties 58 | { 59 | public string Id { get; set; } 60 | 61 | public string Version { get; set; } 62 | 63 | public string Authors { get; set; } 64 | 65 | public string Description { get; set; } 66 | 67 | public int DownloadCount { get; set; } 68 | 69 | public string GalleryDetailsUrl { get; set; } 70 | 71 | public string ProjectUrl { get; set; } 72 | 73 | public DateTime Published { get; set; } 74 | 75 | public string Tags { get; set; } 76 | 77 | public string Owners { get; set; } 78 | } 79 | } -------------------------------------------------------------------------------- /src/Shared/Model/PackageExistence/PackageExistence.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Model.PackageExistence; 4 | 5 | using Contracts; 6 | using Enums; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | 11 | /// 12 | /// Represents a package that currently exists. 13 | /// 14 | public record PackageExists : IPackageExistence 15 | { 16 | public bool Exists => true; 17 | } 18 | 19 | /// 20 | /// Represents a package that never existed. 21 | /// 22 | public record PackageNotFound : IPackageExistence 23 | { 24 | public bool Exists => false; 25 | } 26 | 27 | /// 28 | /// Represents a package that was removed, and why. 29 | /// 30 | /// The reasons (if any) for why a package was removed. 31 | public record PackageRemoved(IReadOnlySet RemovalReasons) : PackageNotFound 32 | { 33 | 34 | protected override bool PrintMembers(StringBuilder stringBuilder) 35 | { 36 | if (base.PrintMembers(stringBuilder)) 37 | { 38 | stringBuilder.Append(", "); 39 | } 40 | 41 | string reasons = string.Join(',', this.RemovalReasons.Select(r => r.ToString())); 42 | 43 | stringBuilder.Append($"RemovalReasons = [{reasons}]"); 44 | return true; 45 | } 46 | } -------------------------------------------------------------------------------- /src/Shared/Model/PackageExistence/PackageVersionExistence.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Model.PackageExistence; 4 | 5 | using Contracts; 6 | using Enums; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | 11 | /// 12 | /// Represents a package version that currently exists. 13 | /// 14 | public record PackageVersionExists : IPackageExistence 15 | { 16 | public bool Exists => true; 17 | } 18 | 19 | /// 20 | /// Represents a package version that never existed. 21 | /// 22 | public record PackageVersionNotFound : IPackageExistence 23 | { 24 | public bool Exists => false; 25 | } 26 | 27 | /// 28 | /// Represents a package version that was removed, and why. 29 | /// 30 | /// The reasons (if any) for why a package was removed. 31 | public record PackageVersionRemoved(IReadOnlySet RemovalReasons) : PackageVersionNotFound 32 | { 33 | protected override bool PrintMembers(StringBuilder stringBuilder) 34 | { 35 | if (base.PrintMembers(stringBuilder)) 36 | { 37 | stringBuilder.Append(", "); 38 | } 39 | 40 | string reasons = string.Join(',', this.RemovalReasons.Select(r => r.ToString())); 41 | 42 | stringBuilder.Append($"RemovalReasons = [{reasons}]"); 43 | return true; 44 | } 45 | } -------------------------------------------------------------------------------- /src/Shared/OssGadgetJsonSerializer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource; 4 | 5 | using Helpers; 6 | using System.Text.Json; 7 | 8 | public class OssGadgetJsonSerializer 9 | { 10 | // Custom json serialization converter for PackageURLs 11 | public static readonly JsonSerializerOptions Options = new() 12 | { 13 | Converters = 14 | { 15 | new PackageUrlJsonConverter() 16 | } 17 | }; 18 | } -------------------------------------------------------------------------------- /src/Shared/OssGadgetLib.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource 4 | { 5 | using Helpers; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Http; 8 | using PackageManagers; 9 | using System; 10 | using System.Net.Http; 11 | 12 | public abstract class OssGadgetLib 13 | { 14 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0044:Add readonly modifier", Justification = "Modified through reflection.")] 15 | public string ENV_HTTPCLIENT_USER_AGENT { get; set; }= "OSSDL"; 16 | 17 | /// 18 | /// The to be used by classes that implement . 19 | /// 20 | protected ProjectManagerFactory ProjectManagerFactory { get; } 21 | 22 | /// 23 | /// The for this class. 24 | /// 25 | protected NLog.ILogger Logger { get; set; } = NLog.LogManager.GetCurrentClassLogger(); 26 | 27 | /// 28 | /// The directory to save files to. 29 | /// Defaults to the directory the code is running in. 30 | /// 31 | protected string Directory { get; } 32 | 33 | protected OssGadgetLib(ProjectManagerFactory projectManagerFactory, string directory = ".") 34 | { 35 | ProjectManagerFactory = Check.NotNull(nameof(projectManagerFactory), projectManagerFactory); 36 | Directory = directory; 37 | } 38 | 39 | protected OssGadgetLib(string directory = ".") : this(new ProjectManagerFactory(), directory) 40 | { 41 | } 42 | 43 | protected static IHttpClientFactory GetDefaultClientFactory() 44 | { 45 | ServiceProvider serviceProvider = new ServiceCollection() 46 | .AddHttpClient() 47 | .BuildServiceProvider(); 48 | 49 | // Get the IHttpClientFactory 50 | return serviceProvider.GetService() ?? throw new InvalidOperationException(); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/Shared/PackageActions/NoOpPackageActions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.PackageActions; 4 | 5 | using Contracts; 6 | using PackageUrl; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | 12 | public class NoOpPackageActions : IManagerPackageActions 13 | { 14 | public Task DownloadAsync( 15 | PackageURL packageUrl, 16 | string topLevelDirectory, 17 | string targetPath, 18 | bool doExtract, 19 | bool cached = false, 20 | CancellationToken cancellationToken = default) => Task.FromResult(null); 21 | 22 | public Task DoesPackageExistAsync( 23 | PackageURL packageUrl, 24 | bool useCache = true, 25 | CancellationToken cancellationToken = default) => Task.FromResult(false); 26 | 27 | public Task> GetAllVersionsAsync( 28 | PackageURL packageUrl, 29 | bool includePrerelease = true, 30 | bool useCache = true, 31 | CancellationToken cancellationToken = default) => Task.FromResult(Enumerable.Empty()); 32 | 33 | public Task GetLatestVersionAsync( 34 | PackageURL packageUrl, 35 | bool includePrerelease = false, 36 | bool useCache = true, 37 | CancellationToken cancellationToken = default) => Task.FromResult(null); 38 | 39 | public Task GetMetadataAsync( 40 | PackageURL packageUrl, 41 | bool useCache = true, 42 | CancellationToken cancellationToken = default) => Task.FromResult(null); 43 | 44 | public Task GetHasReservedNamespaceAsync(PackageURL packageUrl, bool useCache = true, CancellationToken cancellationToken = default) => Task.FromResult(false); 45 | } -------------------------------------------------------------------------------- /src/Shared/Utilities/NuGetLogger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Utilities; 4 | 5 | using NLog; 6 | using NuGet.Common; 7 | using System.Threading.Tasks; 8 | using NuGetLogLevel = NuGet.Common.LogLevel; 9 | using NLogLevel = NLog.LogLevel; 10 | 11 | public class NuGetLogger : LoggerBase 12 | { 13 | private readonly Logger _logger; 14 | 15 | /// 16 | /// Create a new instance of the . 17 | /// This is a wrapper class to use a in place of a 18 | /// 19 | /// The to map to. 20 | public NuGetLogger(Logger logger) 21 | { 22 | _logger = logger; 23 | } 24 | 25 | public override void Log(ILogMessage message) => this._logger.Log(LogLevelConverter(message.Level), message); 26 | 27 | public override Task LogAsync(ILogMessage message) 28 | { 29 | this._logger.Log(LogLevelConverter(message.Level), message); 30 | return Task.CompletedTask; 31 | } 32 | 33 | /// 34 | /// Converts from the to the . 35 | /// 36 | /// The to convert. 37 | /// An equivalent . 38 | private static NLogLevel LogLevelConverter(NuGetLogLevel level) 39 | { 40 | return level switch 41 | { 42 | NuGetLogLevel.Debug => NLogLevel.Debug, 43 | NuGetLogLevel.Verbose => NLogLevel.Trace, 44 | NuGetLogLevel.Information => NLogLevel.Info, 45 | NuGetLogLevel.Minimal => NLogLevel.Warn, 46 | NuGetLogLevel.Warning => NLogLevel.Warn, 47 | NuGetLogLevel.Error => NLogLevel.Error, 48 | _ => NLogLevel.Debug // Should never hit this, as we cover all 6 of the log levels. 49 | }; 50 | } 51 | } -------------------------------------------------------------------------------- /src/Shared/Utilities/VersionComparer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | namespace Microsoft.CST.OpenSource.Utilities 3 | { 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | public class VersionComparer : IComparer> 8 | { 9 | 10 | /// 11 | /// Convert a version (string) to a list of version parts. 12 | /// Just splits into "numbers" and "non-numbers". 13 | /// 14 | /// The version to parse. 15 | /// A list of the version parts. 16 | public static List Parse(string version) 17 | { 18 | List parts = new(); 19 | bool inNumber = false; 20 | string curStr = string.Empty; 21 | 22 | for (int i = 0; i < version.Length; i++) 23 | { 24 | char ch = version[i]; 25 | if (char.IsNumber(ch) ^ inNumber) 26 | { 27 | if (curStr != "") 28 | { 29 | parts.Add(curStr); 30 | } 31 | curStr = ""; 32 | } 33 | 34 | curStr += ch; 35 | if (i == version.Length - 1) 36 | { 37 | parts.Add(curStr); 38 | } 39 | inNumber = char.IsNumber(ch); 40 | } 41 | return parts; 42 | } 43 | 44 | /// 45 | /// Compares two lists of strings, using natural numbers where possible. 46 | /// 47 | /// 48 | /// 49 | /// 50 | public int Compare(List? x, List? y) 51 | { 52 | if (x != null && y != null) 53 | { 54 | int minLength = Math.Min(x.Count, y.Count); 55 | for (int i = 0; i < minLength; i++) 56 | { 57 | if (int.TryParse(x[i], out int xInt) && 58 | int.TryParse(y[i], out int yInt)) 59 | { 60 | if (xInt > yInt) return -1; 61 | if (yInt > xInt) return 1; 62 | } 63 | else 64 | { 65 | int compValue = x[i].CompareTo(y[i]); 66 | if (compValue != 0) return compValue; 67 | } 68 | } 69 | 70 | // If we get here, the values are equal 71 | if (x.Count > y.Count) return -1; 72 | if (x.Count < y.Count) return 1; 73 | return 0; 74 | } 75 | if (x == null) return 1; 76 | if (y == null) return -1; 77 | return 0; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Shared/nlog.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 6 | 7 | 16 | 17 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/oss-find-squats-lib/FindPackageSquats.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats 4 | { 5 | using Contracts; 6 | using ExtensionMethods; 7 | using Microsoft.CST.OpenSource; 8 | using Microsoft.CST.OpenSource.Exceptions; 9 | using Microsoft.CST.OpenSource.Helpers; 10 | using Microsoft.CST.OpenSource.PackageManagers; 11 | using Mutators; 12 | using PackageUrl; 13 | using System.Collections.Generic; 14 | using System.Linq; 15 | 16 | public class FindPackageSquats : OssGadgetLib 17 | { 18 | /// 19 | /// The to find squats for. 20 | /// 21 | public PackageURL PackageUrl { get; } 22 | 23 | public IBaseProjectManager? ProjectManager { get; } 24 | 25 | public FindPackageSquats(ProjectManagerFactory projectManagerFactory, PackageURL packageUrl) 26 | : base(projectManagerFactory) 27 | { 28 | PackageUrl = packageUrl; 29 | ProjectManager = projectManagerFactory.CreateProjectManager(packageUrl); 30 | if (ProjectManager is null) 31 | { 32 | Logger.Trace($"Could not generate valid ProjectManager from { packageUrl }."); 33 | throw new InvalidProjectManagerException(packageUrl); 34 | } 35 | } 36 | 37 | public IDictionary>? GenerateSquatCandidates(IEnumerable? mutators = null, 38 | MutateOptions? options = null) 39 | { 40 | if (ProjectManager is null) 41 | { 42 | Check.NotNull(nameof(ProjectManager), ProjectManager); 43 | } 44 | else 45 | { 46 | if (mutators != null) 47 | { 48 | return ProjectManager.EnumerateSquatCandidates(PackageUrl, mutators, options); 49 | } 50 | return ProjectManager.EnumerateSquatCandidates(PackageUrl, options); 51 | } 52 | return null; 53 | } 54 | 55 | public IAsyncEnumerable FindExistingSquatsAsync(IDictionary>? candidateMutations, MutateOptions? options = null) 56 | { 57 | return ProjectManager?.EnumerateExistingSquatsAsync(PackageUrl, candidateMutations, options) ?? AsyncEnumerable.Empty(); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/MutateOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats 4 | { 5 | using Mutators; 6 | using System.Collections.Generic; 7 | 8 | /// 9 | /// Options to provide to MutateExtension.EnumerateSquats 10 | /// 11 | public class MutateOptions 12 | { 13 | /// 14 | /// Number of milliseconds to sleep between requests to the project manager. 15 | /// 16 | public int SleepDelay { get; set; } 17 | 18 | /// 19 | /// If the cache should be used when checking if mutations exist. 20 | /// 21 | public bool UseCache { get; set; } = true; 22 | 23 | /// 24 | /// Mutators that should be excluded. 25 | /// 26 | public IEnumerable? ExcludedMutators { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/oss-find-squats-lib/Mutators/AddCharacterMutator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats.Mutators 4 | { 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | /// 9 | /// Generates mutations for adding a character in the string. 10 | /// 11 | public class AddCharacterMutator : IMutator 12 | { 13 | public MutatorType Kind { get; } = MutatorType.AddCharacter; 14 | 15 | private readonly List _characters = new() 16 | { 17 | '1','2','3','4','5','6','7','8','9','0','-','q','w','e','r','t','y','u','i','o','p','a','s','d','f','g','h','j','k','l','z','x','c','v','b','n','m','.', 18 | }; 19 | 20 | /// 21 | /// Initializes a instance. 22 | /// Optionally takes in a additional characters to be added, or a list of overriding characters to be added to replace the default list with. 23 | /// 24 | /// An optional parameter for extra characters to be added. 25 | /// An optional parameter for list of characters to be added to replace the default list with. 26 | public AddCharacterMutator(char[]? additionalChars = null, char[]? overrideChars = null, char[]? skipChars = null) 27 | { 28 | if (overrideChars != null) 29 | { 30 | _characters = overrideChars.ToList(); 31 | } 32 | if (additionalChars != null) 33 | { 34 | _characters.AddRange(additionalChars); 35 | } 36 | if (skipChars != null) 37 | { 38 | _characters.RemoveAll(skipChars.Contains); 39 | } 40 | } 41 | 42 | public IEnumerable Generate(string arg) 43 | { 44 | for (int i = 0; i < arg.Length+1; i++) 45 | { 46 | // Can't add a character before an @ for a scoped package. 47 | if (i == 0 && arg[i] == '@') 48 | { 49 | continue; 50 | } 51 | 52 | foreach (var c in _characters) 53 | { 54 | yield return new Mutation( 55 | mutated: $"{arg[..i]}{c}{arg[(i)..]}", 56 | original: arg, 57 | mutator: Kind, 58 | reason: $"Character Added: {c}"); 59 | } 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/Mutators/AddContainingCharacterMutator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats.Mutators 4 | { 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | /// 9 | /// Generates mutations for adding a character in the string, where the character being added already exists in the string. 10 | /// 11 | /// requests -> reuquests. But won't generate something like requests -> regquests 12 | public class AddContainingCharacterMutator : IMutator 13 | { 14 | public MutatorType Kind { get; } = MutatorType.AddContainingCharacter; 15 | 16 | public IEnumerable Generate(string arg) 17 | { 18 | var chars = arg.Distinct().ToArray(); 19 | for (int i = 0; i < arg.Length+1; i++) 20 | { 21 | // Can't add a character before an @ for a scoped package. 22 | if (i == 0 && arg[i] == '@') 23 | { 24 | continue; 25 | } 26 | 27 | foreach (var c in chars) 28 | { 29 | yield return new Mutation( 30 | mutated: $"{arg[..i]}{c}{arg[i..]}", 31 | original: arg, 32 | mutator: Kind, 33 | reason: $"Containing Character Added: {c}"); 34 | } 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/Mutators/AsciiHomoglyphMutator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats.Mutators 4 | { 5 | using Microsoft.CST.OpenSource.Helpers; 6 | using System.Collections.Generic; 7 | 8 | /// 9 | /// Generates ASCII homoglyphs. 10 | /// Similar looking letters were swapped out for others. eg. m -> n or r -> n. 11 | /// 12 | public class AsciiHomoglyphMutator : IMutator 13 | { 14 | public MutatorType Kind { get; } = MutatorType.AsciiHomoglyph; 15 | 16 | private static readonly Dictionary homoglyphs = new() 17 | { 18 | ['a'] = "eoq4", 19 | ['b'] = "dhp", 20 | ['c'] = "o", 21 | ['d'] = "bpq", 22 | ['e'] = "ao", 23 | ['f'] = "t", 24 | ['g'] = "pq", 25 | ['h'] = "b", 26 | ['i'] = "lj", 27 | ['j'] = "il", 28 | ['l'] = "ij1", 29 | ['m'] = "n", 30 | ['n'] = "rmu", 31 | ['o'] = "cea0", 32 | ['p'] = "bdqg", 33 | ['q'] = "adpg", 34 | ['r'] = "n", 35 | ['t'] = "f", 36 | ['u'] = "n", 37 | ['0'] = "o", 38 | ['1'] = "l", 39 | ['4'] = "a" 40 | }; 41 | 42 | public IEnumerable Generate(string arg) 43 | { 44 | // assumption is that attacker is making just one change 45 | for (int i = 0; i < arg.Length; i++) 46 | { 47 | if (homoglyphs.ContainsKey(arg[i])) 48 | { 49 | foreach (char c in homoglyphs[arg[i]]) 50 | { 51 | yield return new Mutation( 52 | mutated: arg.ReplaceCharAtPosition(c, i), 53 | original: arg, 54 | mutator: Kind, 55 | reason: $"Ascii Homoglpyh: {arg[i]} => {c}"); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/Mutators/BitFlipMutator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats.Mutators 4 | { 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | /// 10 | /// Generates mutations for a flipped bit. 11 | /// 12 | public class BitFlipMutator : IMutator 13 | { 14 | public MutatorType Kind { get; } = MutatorType.BitFlip; 15 | 16 | public IEnumerable Generate(string arg) 17 | { 18 | byte[]? byteArray = Encoding.UTF8.GetBytes(arg); 19 | for (int i = 0; i < byteArray.Length; i++) 20 | { 21 | for (int j = 0; j < 8; j++) 22 | { 23 | byte mask = (byte)(1 << j); 24 | byteArray[i] = (byte)(byteArray[i] ^ mask); 25 | string? newString = Encoding.UTF8.GetString(byteArray); 26 | bool valid = true; 27 | 28 | for (int k = 0; k < newString.Length && valid; k++) 29 | { 30 | if (!Uri.IsWellFormedUriString(newString, UriKind.Relative)) 31 | { 32 | valid = false; 33 | } 34 | } 35 | if (valid) 36 | { 37 | yield return new Mutation( 38 | mutated: newString, 39 | original: arg, 40 | mutator: Kind, 41 | reason: $"Bit Flips: Byte {i}, Bit {j}"); 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/Mutators/DuplicatorMutator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats.Mutators 4 | { 5 | using System.Collections.Generic; 6 | 7 | /// 8 | /// Generates mutations for if a character was duplicated in the string. Or duplicated and replaced. 9 | /// 10 | public class DuplicatorMutator : IMutator 11 | { 12 | public MutatorType Kind { get; } = MutatorType.Duplicator; 13 | 14 | public IEnumerable Generate(string arg) 15 | { 16 | for (int i = 0; i < arg.Length; i++) 17 | { 18 | yield return new Mutation( 19 | mutated: string.Concat(arg[..i], arg[i], arg[i..]), 20 | original: arg, 21 | mutator: Kind, 22 | reason: $"Letter Duplicated: {arg[i]}"); 23 | } 24 | 25 | for (int i = 0; i < arg.Length - 2; i++) 26 | { 27 | if (!string.Concat(arg[..(i + 1)], arg[i], arg[(i + 2)..]).Equals(arg)) 28 | { 29 | yield return new Mutation( 30 | mutated: string.Concat(arg[..(i + 1)], arg[i], arg[(i + 2)..]), 31 | original: arg, 32 | mutator: Kind, 33 | reason: $"Letter Duplicated and Replaced: {arg[i]}"); 34 | } 35 | } 36 | 37 | if (!string.Concat(arg[..arg.Length], arg[^1]).Equals(arg)) 38 | { 39 | yield return new Mutation( 40 | mutated: string.Concat(arg[..arg.Length], arg[^1]), 41 | original: arg, 42 | mutator: Kind, 43 | reason: "Letter Duplicated and Replaced"); 44 | } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/Mutators/Mutation.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats.Mutators 4 | { 5 | using PackageUrl; 6 | 7 | /// 8 | /// A record of the mutation generated by an . 9 | /// 10 | public record Mutation 11 | { 12 | /// 13 | /// Construct a Mutation. 14 | /// 15 | /// The mutated string. 16 | /// The original string. 17 | /// A human readable explanation of the change made to the original string. 18 | /// The of the mutator which generated this. 19 | public Mutation(string mutated, string original, string reason, MutatorType mutator) 20 | { 21 | Mutated = mutated; 22 | Original = original; 23 | Reason = reason; 24 | Mutator = mutator; 25 | } 26 | 27 | /// 28 | /// The mutated string. 29 | /// 30 | public string Mutated { get; } 31 | 32 | /// 33 | /// The original string. 34 | /// 35 | public string Original { get; } 36 | 37 | /// 38 | /// A human readable explanation of the change made to the original . 39 | /// 40 | public string Reason { get; } 41 | 42 | /// 43 | /// The of the which generated this. 44 | /// 45 | public MutatorType Mutator { get; } 46 | } 47 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/Mutators/NamespaceInNameMutator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats.Mutators 4 | { 5 | using Extensions; 6 | using PackageUrl; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | 10 | /// 11 | /// Generates mutations for moving the namespace to the name. 12 | /// 13 | public class NamespaceInNameMutator : IMutator 14 | { 15 | public MutatorType Kind { get; } = MutatorType.NamespaceInName; 16 | 17 | public HashSet Separators { get; set; } = SeparatorRemovedMutator.DefaultSeparators.ToHashSet(); 18 | 19 | public IEnumerable Generate(string arg) 20 | { 21 | PackageURL purl = new(arg); 22 | 23 | string namespaceStr = purl.Namespace.Replace("@", string.Empty).Replace("%40", string.Empty); 24 | 25 | foreach (var separator in Separators) 26 | { 27 | yield return new Mutation( 28 | mutated: purl.CreateWithNewNames($"{namespaceStr}{separator}{purl.Name}", null).ToString(), 29 | original: arg, 30 | mutator: Kind, 31 | reason: $"Namespace '{namespaceStr}' added to name with the separator: {separator}"); 32 | } 33 | 34 | yield return new Mutation( 35 | mutated: purl.CreateWithNewNames($"{namespaceStr}{purl.Name}", null).ToString(), 36 | original: arg, 37 | mutator: Kind, 38 | reason: $"Namespace '{namespaceStr}' added to name with no separator"); 39 | } 40 | 41 | public IEnumerable Generate(PackageURL arg) 42 | { 43 | if (!arg.HasNamespace()) 44 | { 45 | yield break; 46 | } 47 | 48 | foreach (Mutation mutation in Generate(arg.ToString())) 49 | { 50 | yield return mutation; 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/Mutators/RemoveNamespaceMutator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats.Mutators 4 | { 5 | using Extensions; 6 | using PackageUrl; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | 10 | /// 11 | /// Generates mutations for removing the namespace. 12 | /// 13 | public class RemoveNamespaceMutator : IMutator 14 | { 15 | public MutatorType Kind { get; } = MutatorType.RemovedNamespace; 16 | 17 | public IEnumerable Generate(string arg) 18 | { 19 | PackageURL purl = new(arg); 20 | 21 | yield return new Mutation( 22 | mutated: purl.CreateWithNewNames(purl.Name, null).ToString(), // Just the package name, no namespace. 23 | original: arg, 24 | mutator: Kind, 25 | reason: $"Namespace removed: {purl.Namespace}"); // The package's namespace that was removed. 26 | } 27 | 28 | public IEnumerable Generate(PackageURL arg) 29 | { 30 | if (!arg.HasNamespace()) 31 | { 32 | yield break; 33 | } 34 | 35 | yield return this.Generate(arg.ToString()).Single(); // Should only ever have one mutation. 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/Mutators/RemoveSeparatedSectionMutator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats.Mutators 4 | { 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | /// 10 | /// Generates mutations for if a name with a separator(s) had one removed. 11 | /// 12 | public class RemoveSeparatedSectionMutator : IMutator 13 | { 14 | public MutatorType Kind { get; } = MutatorType.RemoveSeparatedSection; 15 | 16 | public HashSet Separators { get; set; } = SeparatorRemovedMutator.DefaultSeparators.ToHashSet(); 17 | 18 | public RemoveSeparatedSectionMutator(char[]? additionalSeparators = null, char[]? overrideSeparators = null, char[]? skipSeparators = null) 19 | { 20 | if (overrideSeparators != null) 21 | { 22 | Separators = new HashSet(overrideSeparators); 23 | } 24 | if (additionalSeparators != null) 25 | { 26 | Separators.UnionWith(additionalSeparators); 27 | } 28 | if (skipSeparators != null) 29 | { 30 | Separators.ExceptWith(skipSeparators); 31 | } 32 | } 33 | 34 | /// 35 | /// Generates mutations by removing each separated section. 36 | /// For example: foo-bar-js generates bar-js, foo-js, and foo-bar. 37 | /// 38 | /// String to mutate 39 | /// The generated mutations. 40 | public IEnumerable Generate(string arg) 41 | { 42 | foreach (char separator in Separators) 43 | { 44 | string[] splits = arg.Split(separator, StringSplitOptions.RemoveEmptyEntries); 45 | 46 | if (splits.Length >= 2) 47 | { 48 | for (int i = 0; i < splits.Length; i++) 49 | { 50 | yield return new Mutation( 51 | mutated: $"{string.Join(separator, splits[..i])}{string.Join(separator, splits[(i + 1)..])}", 52 | original: arg, 53 | mutator: Kind, 54 | reason: $"Separated Section Removed: {i} ('{arg[i]}')"); 55 | } 56 | } 57 | } 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/Mutators/RemovedCharacterMutator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats.Mutators 4 | { 5 | using System.Collections.Generic; 6 | 7 | /// 8 | /// Generates mutations for removing a character in the string. 9 | /// 10 | public class RemovedCharacterMutator : IMutator 11 | { 12 | public MutatorType Kind { get; } = MutatorType.RemovedCharacter; 13 | 14 | public IEnumerable Generate(string arg) 15 | { 16 | for (int i = 0; i < arg.Length; i++) 17 | { 18 | // Don't want to remove an @ for scoped npm package as part of mutations. It's ultimately pointless to do so. 19 | if (i == 0 && arg[i] == '@') 20 | { 21 | continue; 22 | } 23 | yield return new Mutation( 24 | mutated: $"{arg[..i]}{arg[(i + 1)..]}", 25 | original: arg, 26 | mutator: Kind, 27 | reason: $"Character Removed: {i} ('{arg[i]}')"); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/Mutators/SeparatorRemovedMutator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats.Mutators 4 | { 5 | using System.Collections.Generic; 6 | using System.Collections.Immutable; 7 | using System.Linq; 8 | 9 | /// 10 | /// Generates mutations where all separators are removed. 11 | /// The default separators are '.', '-', '_'. 12 | /// 13 | public class SeparatorRemovedMutator : IMutator 14 | { 15 | public MutatorType Kind { get; } = MutatorType.SeparatorRemoved; 16 | 17 | public HashSet Separators { get; set; } = DefaultSeparators.ToHashSet(); 18 | 19 | public static ImmutableHashSet DefaultSeparators { get => ImmutableHashSet.Create(new[] { '.', '-', '_' }); } 20 | 21 | /// 22 | /// Initializes a instance. 23 | /// Optionally takes in a additional separators, or a list of overriding separators to 24 | /// replace the default list with. 25 | /// 26 | /// An optional parameter for extra separators. 27 | /// An optional parameter for list of separators to replace the 28 | /// default list with. 29 | public SeparatorRemovedMutator(char[]? additionalSeparators = null, char[]? overrideSeparators = null) 30 | { 31 | if (overrideSeparators != null) 32 | { 33 | Separators = new HashSet(overrideSeparators); 34 | } 35 | if (additionalSeparators != null) 36 | { 37 | Separators = new HashSet(Separators.Concat(additionalSeparators)); 38 | } 39 | } 40 | 41 | /// 42 | /// Generates mutations by removing each separator. 43 | /// For example: foo-js generates foojs. 44 | /// 45 | /// String to mutate 46 | /// The generated mutations. 47 | public IEnumerable Generate(string target) 48 | { 49 | foreach (char separator in Separators) 50 | { 51 | if (target.Contains(separator)) 52 | { 53 | yield return new Mutation( 54 | mutated: target.Replace(separator.ToString(), string.Empty), 55 | original: target, 56 | mutator: Kind, 57 | reason: $"Separator Removed {separator}"); 58 | } 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/Mutators/SubstitutionMutator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats.Mutators 4 | { 5 | using System.Collections.Generic; 6 | 7 | /// 8 | /// Generates mutations for if a known substitution exists. 9 | /// e.g. js -> javascript and vice versa. 10 | /// 11 | /// 12 | /// Currently has no substitutions by default, has to be populated in the constructor. 13 | /// 14 | public class SubstitutionMutator : IMutator 15 | { 16 | public MutatorType Kind { get; } = MutatorType.Substitution; 17 | 18 | /// 19 | /// A list of the original strings and their equivalent substitutions. 20 | /// They get replaced in both directions. 21 | /// e.g. "js" -> "javascript" and "javascript" -> "js". 22 | /// 23 | private readonly IList<(string Original, string Substitution)> _substitutions; 24 | 25 | public SubstitutionMutator(IList<(string Original, string Substitution)>? substitutions = null) 26 | { 27 | _substitutions = substitutions ?? new List<(string Original, string Substitution)>(); 28 | } 29 | 30 | public IEnumerable Generate(string arg) 31 | { 32 | foreach ((string original, string substitution) in _substitutions) 33 | { 34 | if (arg.Contains(original)) 35 | { 36 | yield return new Mutation( 37 | mutated: arg.Replace(original, substitution), 38 | original: arg, 39 | mutator: Kind, 40 | reason: $"String Substituted: {original} => {substitution}"); 41 | } 42 | 43 | if (arg.Contains(substitution)) 44 | { 45 | yield return new Mutation( 46 | mutated: arg.Replace(substitution, original), 47 | original: arg, 48 | mutator: Kind, 49 | reason: $"String Substituted: {substitution} => {original}"); 50 | } 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/Mutators/SuffixMutator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats.Mutators 4 | { 5 | using Helpers; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | /// 10 | /// Generates mutations for if a suffix was added to, or removed from the string. 11 | /// By default, we check for these prefixes: "s", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "ng", "-ng", ".", "x", "-", "_". 12 | /// 13 | public class SuffixMutator : IMutator 14 | { 15 | public MutatorType Kind { get; } = MutatorType.Suffix; 16 | 17 | private readonly List _suffixes = new() { "s", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "ng", "-ng", ".", "x", "-", "_" }; 18 | 19 | /// 20 | /// Initializes a instance. 21 | /// Optionally takes in a additional suffixes, or a list of overriding suffixes to replace the default list with. 22 | /// 23 | /// An optional parameter for extra suffixes. 24 | /// An optional parameter for list of suffixes to replace the default list with. 25 | public SuffixMutator(string[]? additionalSuffixes = null, string[]? overrideSuffixes = null, string[]? skipSuffixes = null) 26 | { 27 | if (overrideSuffixes != null) 28 | { 29 | _suffixes = overrideSuffixes.ToList(); 30 | } 31 | if (additionalSuffixes != null) 32 | { 33 | _suffixes.AddRange(additionalSuffixes); 34 | } 35 | if (skipSuffixes != null) 36 | { 37 | _suffixes.RemoveAll(skipSuffixes.Contains); 38 | } 39 | } 40 | 41 | public IEnumerable Generate(string arg) 42 | { 43 | var addedSuffixes = _suffixes.Select(s => new Mutation( 44 | mutated: string.Concat(arg, s), 45 | original: arg, 46 | mutator: Kind, 47 | reason: $"Suffix Added: {s}")); 48 | 49 | var removedSuffixes = _suffixes.Where(arg.EndsWith).Select(s => new Mutation( 50 | mutated: arg.ReplaceAtEnd(s, string.Empty), 51 | original: arg, 52 | mutator: Kind, 53 | reason: $"Suffix Removed: {s}")); 54 | 55 | return addedSuffixes.Concat(removedSuffixes); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/Mutators/SwapOrderOfLettersMutator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats.Mutators 4 | { 5 | using System.Collections.Generic; 6 | 7 | /// 8 | /// Generates mutations for if a letter was swapped with an adjacent letter. 9 | /// 10 | public class SwapOrderOfLettersMutator : IMutator 11 | { 12 | public MutatorType Kind { get; } = MutatorType.SwapOrderOfLetters; 13 | 14 | public IEnumerable Generate(string arg) 15 | { 16 | for (int i = 0; i < arg.Length - 1; i++) 17 | { 18 | // Don't want to swap the same character for the same character, foo -> foo. 19 | if (arg[i + 1] == arg[i]) 20 | { 21 | continue; 22 | } 23 | 24 | yield return new Mutation( 25 | mutated: string.Concat(arg[..i], arg[i + 1], arg[i], arg.Substring(i + 2, arg.Length - (i + 2))), 26 | original: arg, 27 | mutator: Kind, 28 | reason: "Letters Swapped"); 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/Mutators/VowelSwapMutator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.FindSquats.Mutators 4 | { 5 | using Microsoft.CST.OpenSource.Helpers; 6 | using System.Collections.Generic; 7 | 8 | /// 9 | /// Generates mutations for swapping a vowel for another. 10 | /// 11 | public class VowelSwapMutator : IMutator 12 | { 13 | public MutatorType Kind { get; } = MutatorType.VowelSwap; 14 | 15 | private readonly HashSet _vowels = new() { 'a', 'e', 'i', 'o', 'u', 'y' }; 16 | 17 | public IEnumerable Generate(string arg) 18 | { 19 | for (int i = 0; i < arg.Length; i++) 20 | { 21 | if (_vowels.Contains(char.ToLower(arg[i]))) 22 | { 23 | // Then the character at index 'i' is a vowel. 24 | foreach (char vowel in _vowels) 25 | { 26 | if (vowel != char.ToLower(arg[i])) 27 | { 28 | // Only do something if the vowel isn't the same. 29 | // TODO: I think this doesn't maintain casing. 30 | yield return new Mutation( 31 | mutated: arg.ReplaceCharAtPosition(vowel, i), 32 | original: arg, 33 | mutator: Kind, 34 | reason: $"Swap Vowel: {arg[i]} => {vowel}"); 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/oss-find-squats-lib/oss-find-squats-lib.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0;net8.0 5 | Microsoft.CST.OpenSource.FindSquats 6 | OSS Gadget - Package Typosquatting Detector Library 7 | GitHub 8 | https://github.com/Microsoft/OSSGadget 9 | Debug;Release 10 | oss-find-squats-lib 11 | 10.0 12 | enable 13 | © Microsoft Corporation. All rights reserved. 14 | Microsoft 15 | Microsoft 16 | false 17 | false 18 | Microsoft.CST.OSSGadget.FindSquats 19 | 0.0.0 20 | https://github.com/Microsoft/OSSGadget 21 | Security Scanner 22 | LICENSE.txt 23 | icon-128.png 24 | true 25 | snupkg 26 | true 27 | win-x64;osx-x64;linux-x64 28 | false 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/oss-gadget-cli/oss-gadget-cli.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | Microsoft.CST.OpenSource.OSSGadget.CLI 7 | enable 8 | enable 9 | ossgadget 10 | Microsoft.CST.OpenSource.OSSGadget.CLI.OssGadgetCli 11 | win-x64;linux-x64;osx-x64 12 | OSS Gadget Command Line Interface 13 | 0.0.0 14 | 0.0.0 15 | Microsoft 16 | Microsoft 17 | © Microsoft Corporation. All rights reserved. 18 | OSS Gadget is a collection of tools that can help analyze open source projects. This is the command line interface. 19 | true 20 | ossgadget 21 | Microsoft.CST.OSSGadget.CLI 22 | Security Analysis 23 | MIT 24 | icon-128.png 25 | https://github.com/Microsoft/OSSGadget 26 | true 27 | snupkg 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/oss-tests/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{cs,vb}] 2 | dotnet_diagnostic.IDE0008.severity = none -------------------------------------------------------------------------------- /src/oss-tests/ArchiveHelperTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Tests; 4 | 5 | using OpenSource.Helpers; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Threading.Tasks; 10 | 11 | public class ArchiveHelperTests 12 | { 13 | /// 14 | /// Unit test that ExtractArchiveAsync works successfully. 15 | /// 16 | [Fact] 17 | public async Task ExtractArchiveSucceeds() 18 | { 19 | // Get the Base64Zip.zip file from our TestData resources. 20 | FileStream? zip = new(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? string.Empty, "TestData", "Base64Zip.zip"), FileMode.Open); 21 | 22 | // Create a list of the files we expect to be in the zip file. 23 | string[] expectedFiles = {"Base64", "Hex", "oss-defog.dll"}; 24 | 25 | // Create a new temporary directory 26 | string? targetDirectoryName = null; 27 | while (targetDirectoryName == null || Directory.Exists(targetDirectoryName)) 28 | { 29 | targetDirectoryName = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); 30 | } 31 | 32 | try 33 | { 34 | // Extract the zip file to the target directory. 35 | string? path = await ArchiveHelper.ExtractArchiveAsync( 36 | targetDirectoryName, 37 | "Base64Zip", 38 | zip); 39 | 40 | // Assert that the directory we extracted the zip archive to exists. 41 | Directory.Exists(path).Should().BeTrue(); 42 | 43 | // Check that the extracted files from the zip archive match the ones we expected. 44 | string?[] files = Directory.EnumerateFiles(Path.Combine(path, "Base64Zip")).Select(Path.GetFileName).ToArray(); 45 | files.Should().BeEquivalentTo(expectedFiles); 46 | } 47 | finally 48 | { 49 | // Delete the temp directory that was created. 50 | FileSystemHelper.RetryDeleteDirectory(targetDirectoryName); 51 | 52 | // Close the stream that was used to read the zip file. 53 | zip.Close(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/oss-tests/GlobalUsing.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; 2 | global using FluentAssertions; -------------------------------------------------------------------------------- /src/oss-tests/MetadataTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Tests; 4 | 5 | using System.Threading.Tasks; 6 | using DevLab.JmesPath; 7 | using Microsoft.CST.OpenSource; 8 | using PackageUrl; 9 | using System.Text.Json; 10 | 11 | public class MetadataTests 12 | { 13 | [Theory] 14 | [InlineData("deps.dev", "pkg:npm/blake3", "package.name", "blake3")] 15 | [InlineData("deps.dev", "pkg:npm/blake3@3.0.0", "package.name", "blake3")] 16 | [InlineData("libraries.io", "pkg:npm/blake3@3.0.0", "name", "blake3")] 17 | public async Task Check_Metadata(string dataSource, string purlString, string jmesPathExpr, string targetResult) 18 | { 19 | BaseMetadataSource? metadataSource = null; 20 | if (string.Equals(dataSource, "deps.dev", StringComparison.InvariantCultureIgnoreCase)) 21 | metadataSource = new DepsDevMetadataSource(); 22 | else if (string.Equals(dataSource, "libraries.io", StringComparison.InvariantCultureIgnoreCase)) 23 | metadataSource = new LibrariesIoMetadataSource(); 24 | else 25 | Assert.Fail("Unknown data source: " + dataSource); 26 | 27 | PackageURL purl = new(purlString); 28 | JsonDocument? metadata = await metadataSource.GetMetadataForPackageUrlAsync(purl, false); 29 | if (metadata == null) 30 | Assert.Fail($"Unable to load metadata for package: {purlString}"); 31 | 32 | var jmesPath = new JmesPath(); 33 | var result = jmesPath.Transform(System.Text.Json.JsonSerializer.Serialize(metadata), jmesPathExpr); 34 | if (result == null) 35 | Assert.Fail($"Unable to evaluate JMESPath expression: {jmesPathExpr}"); 36 | 37 | var resultString = result.ToString().Trim('"'); 38 | Assert.Equal(targetResult, resultString); 39 | } 40 | } -------------------------------------------------------------------------------- /src/oss-tests/PackageExistenceTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Tests; 4 | 5 | using Contracts; 6 | using FluentAssertions; 7 | using Model.Enums; 8 | using Model.PackageExistence; 9 | using System.Collections.Generic; 10 | 11 | public class PackageExistenceTests 12 | { 13 | /// 14 | /// PackageRemoved should inherit type PackageNotFound as well. 15 | /// 16 | [Fact] 17 | public void PackageExistence_Removed_Is_NotFound() 18 | { 19 | IPackageExistence packageExistenceRemoved = new PackageRemoved(new HashSet(new[] 20 | { 21 | PackageRemovalReason.PackageUnpublished 22 | })); 23 | 24 | packageExistenceRemoved.Should().BeAssignableTo() 25 | .Subject.Exists.Should().Be(false); 26 | 27 | packageExistenceRemoved.Exists.Should().Be(false); 28 | 29 | if (packageExistenceRemoved is not PackageNotFound) 30 | { 31 | Assert.Fail(); 32 | } 33 | } 34 | 35 | /// 36 | /// PackageVersionRemoved should inherit type PackageVersionNotFound as well. 37 | /// 38 | [Fact] 39 | public void PackageVersionExistence_Removed_Is_NotFound() 40 | { 41 | IPackageExistence packageVersionExistenceRemoved = new PackageVersionRemoved(new HashSet(new[] 42 | { 43 | PackageVersionRemovalReason.VersionUnpublished 44 | })); 45 | 46 | packageVersionExistenceRemoved.Should().BeAssignableTo() 47 | .Subject.Exists.Should().Be(false); 48 | 49 | packageVersionExistenceRemoved.Exists.Should().Be(false); 50 | 51 | if (packageVersionExistenceRemoved is not PackageVersionNotFound) 52 | { 53 | Assert.Fail(); 54 | } 55 | } 56 | 57 | [Fact] 58 | public void PackageExistence_NotFound() 59 | { 60 | IPackageExistence packageExistenceRemoved = new PackageNotFound(); 61 | 62 | packageExistenceRemoved.Exists.Should().Be(false); 63 | } 64 | } -------------------------------------------------------------------------------- /src/oss-tests/PackageUrlExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Tests; 4 | 5 | using Extensions; 6 | using PackageUrl; 7 | public class PackageUrlExtensionsTests 8 | { 9 | [Theory] 10 | [InlineData("pkg:npm/lodash@4.17.15", "pkg-npm-lodash@4.17.15")] 11 | [InlineData("pkg:nuget/newtonsoft.json", "pkg-nuget-newtonsoft.json")] 12 | [InlineData("pkg:nuget/PSReadLine@2.2.0?repository_url=https://www.powershellgallery.com/api/v2", "pkg-nuget-PSReadLine@2.2.0")] 13 | public void ToStringFilenameSucceeds(string packageUrlString, string filename) 14 | { 15 | PackageURL packageUrl = new(packageUrlString); 16 | Assert.Equal(filename, packageUrl.ToStringFilename()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/oss-tests/ProjectManagerTests/BaseNuGetProjectManagerTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Tests.ProjectManagerTests 4 | { 5 | using Microsoft.CST.OpenSource.PackageManagers; 6 | using Moq; 7 | using PackageUrl; 8 | using System; 9 | using System.Net.Http; 10 | using Xunit; 11 | 12 | public class BaseNuGetProjectManagerTests 13 | { 14 | [Theory] 15 | [InlineData( 16 | "pkg:nuget/TestPackage?repository_url=https://www.powershellgallery.com/api/v2", 17 | typeof(NuGetV2ProjectManager))] 18 | [InlineData( 19 | "pkg:nuget/TestPackage?repository_url=https://api.nuget.org/v3/index.json", 20 | typeof(NuGetProjectManager))] 21 | [InlineData( 22 | "pkg:nuget/TestPackage?repository_url=https://example.com", 23 | typeof(NuGetProjectManager))] 24 | [InlineData( 25 | "pkg:nuget/TestPackage", 26 | typeof(NuGetProjectManager))] 27 | public void Create_ReturnsExpectedManagerType(string purlString, Type expectedType) 28 | { 29 | // Arrange 30 | Mock mockHttpClientFactory = new(); 31 | PackageURL packageUrl = new(purlString); 32 | 33 | // Act 34 | BaseNuGetProjectManager result = BaseNuGetProjectManager.Create(".", mockHttpClientFactory.Object, TimeSpan.Zero, packageUrl); 35 | 36 | // Assert 37 | Assert.IsType(expectedType, result); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/oss-tests/ProjectManagerTests/CondaProjectManagerTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Tests.ProjectManagerTests; 4 | 5 | using Microsoft.CST.OpenSource.Model; 6 | using Microsoft.CST.OpenSource.PackageActions; 7 | using Microsoft.CST.OpenSource.PackageManagers; 8 | using Moq; 9 | using PackageUrl; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Net.Http; 13 | using System.Threading.Tasks; 14 | 15 | public class CondaProjectManagerTests 16 | { 17 | private readonly Mock _projectManager; 18 | private readonly IHttpClientFactory _httpFactory; 19 | 20 | public CondaProjectManagerTests() 21 | { 22 | Mock mockFactory = new(); 23 | _httpFactory = mockFactory.Object; 24 | 25 | _projectManager = new Mock(".", new NoOpPackageActions(), _httpFactory, null) { CallBase = true }; 26 | } 27 | 28 | [Theory] 29 | [InlineData( 30 | "pkg:conda/absl-py@0.4.1?build=py36_0&channel=main&subdir=linux-64&type=tar.bz2", 31 | CondaProjectManager.CondaArtifactType.TarBz2, 32 | "https://repo.anaconda.com/pkgs/main/linux-64/absl-py-0.4.1-py36_0.tar.bz2")] 33 | [InlineData( 34 | "pkg:conda/absl-py@0.4.1?build=py36_0&channel=main&subdir=linux-64&type=conda", 35 | CondaProjectManager.CondaArtifactType.Conda, 36 | "https://repo.anaconda.com/pkgs/main/linux-64/absl-py-0.4.1-py36_0.conda")] 37 | public async Task GetArtifactDownloadUrisSucceeds_Async(string purlString, CondaProjectManager.CondaArtifactType artifactType, string expectedUri) 38 | { 39 | PackageURL purl = new(purlString); 40 | List> uris = await _projectManager.Object.GetArtifactDownloadUrisAsync(purl).ToListAsync(); 41 | 42 | ArtifactUri artifactUri = uris.First(); 43 | artifactUri.Uri.Should().Be(expectedUri); 44 | artifactUri.Type.Should().Be(artifactType); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/oss-tests/ReproducibleTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Tests; 4 | 5 | using OssGadget.Options; 6 | using Microsoft.CST.OpenSource.Reproducibility; 7 | using System.Text.Json; 8 | 9 | public class ReproducibleTest 10 | { 11 | [Theory] 12 | [InlineData("pkg:npm/left-pad@1.3.0", true)] 13 | [InlineData("pkg:npm/non-existent1267461827467@12421", false)] 14 | public async Task CheckReproducibility(string packageUrl, bool? expectedToBeReproducible) 15 | { 16 | string? outputFilename = Guid.NewGuid().ToString() + ".json"; 17 | var options = new ReproducibleToolOptions() 18 | { 19 | AllStrategies = true, OutputFile = outputFilename, Targets = new[] { packageUrl } 20 | }; 21 | await new ReproducibleTool().RunAsync(options); 22 | 23 | bool outputFileExists = File.Exists(outputFilename); 24 | 25 | if (expectedToBeReproducible != null) 26 | { 27 | Assert.True(outputFileExists, "Output file does not exist."); 28 | string? result = File.ReadAllText(outputFilename); 29 | 30 | List? jsonResults = JsonSerializer.Deserialize>(result); 31 | Assert.NotNull(jsonResults); // "Output file was not parseable." 32 | 33 | Assert.Equal(expectedToBeReproducible == true, jsonResults.First().IsReproducible); 34 | } 35 | else 36 | { 37 | if (outputFileExists) 38 | { 39 | File.Delete(outputFilename); 40 | } 41 | Assert.True(!outputFileExists, "File was produced but should have been an error."); 42 | } 43 | 44 | // Cleanup 45 | if (File.Exists(outputFilename)) 46 | { 47 | File.Delete(outputFilename); 48 | } 49 | 50 | } 51 | 52 | 53 | [Theory] 54 | [InlineData("/foo/bar/quux.c", "quux.c", "quux.c")] 55 | [InlineData("/foo/bar/quux.c", "baz.c", null)] 56 | [InlineData("/foo/bar/quux.c", "baz/quux.c,bar/quux.c", "bar/quux.c")] 57 | public async Task CheckGetClosestMatch(string filename, string targets, string expectedTarget) 58 | { 59 | IEnumerable? results = OssReproducibleHelpers.GetClosestFileMatch(filename, targets.Split(',')); 60 | Assert.NotNull(results); 61 | 62 | if (expectedTarget == null) 63 | { 64 | Assert.False(results.Any()); 65 | } 66 | else 67 | { 68 | Assert.True(results.Any()); 69 | Assert.Equal(expectedTarget, results.First()); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/oss-tests/SharedTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Tests; 4 | 5 | using Contracts; 6 | using Microsoft.CST.OpenSource.Utilities; 7 | using Model; 8 | using PackageManagers; 9 | using PackageUrl; 10 | using System; 11 | 12 | public class SharedTests 13 | { 14 | 15 | [Theory] 16 | [InlineData("1.2.3")] 17 | [InlineData("v1.2.3")] 18 | [InlineData("v123.456.abc.789")] 19 | [InlineData(".123")] 20 | [InlineData("5")] 21 | [InlineData("1.2.3-release1")] 22 | public async Task VersionParseSucceeds(string versionString) 23 | { 24 | System.Collections.Generic.List? result = VersionComparer.Parse(versionString); 25 | Assert.Equal(string.Join("", result), versionString); 26 | } 27 | 28 | [Theory] 29 | [InlineData("pkg:npm/lodash@4.17.15")] 30 | public async Task MetadataToFromJsonSucceeds(string packageUrlString) 31 | { 32 | PackageURL packageUrl = new(packageUrlString); 33 | IBaseProjectManager? projectManager = ProjectManagerFactory.ConstructPackageManager(packageUrl); 34 | 35 | if (projectManager == null) 36 | { 37 | throw new NullReferenceException("The project manager is null."); 38 | } 39 | 40 | PackageMetadata metadata = await projectManager.GetPackageMetadataAsync(packageUrl, useCache: false); 41 | 42 | Assert.Equal("lodash", metadata.Name); 43 | Assert.Equal("Lodash modular utilities.", metadata.Description); 44 | Assert.Equal("4.17.15", metadata.PackageVersion); 45 | 46 | string? metadataJson = metadata.ToString(); 47 | 48 | Assert.Contains("Lodash modular utilities.", metadataJson); 49 | 50 | PackageMetadata metadataFromJson = PackageMetadata.FromJson(metadataJson) ?? throw new InvalidOperationException("Can't deserialize the metadata json."); 51 | 52 | Assert.Equal("lodash", metadataFromJson.Name); 53 | Assert.Equal("Lodash modular utilities.", metadataFromJson.Description); 54 | Assert.Equal("4.17.15", metadataFromJson.PackageVersion); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/oss-tests/StringExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Tests; 4 | 5 | using OpenSource.Helpers; 6 | 7 | public class StringExtensionsTests 8 | { 9 | [Theory] 10 | [InlineData("lodash-js", "-js", "", "lodash")] 11 | [InlineData("examplenode", "node", "", "example")] 12 | [InlineData("reactjs-javascript", "-javascript", "", "reactjs")] 13 | [InlineData("reactjs-js", "-js", "", "reactjs")] 14 | public void TestReplaceAtEnd(string original, string oldValue, string newValue, string expected) 15 | { 16 | Assert.Equal(expected, original.ReplaceAtEnd(oldValue, newValue)); 17 | } 18 | 19 | [Theory] 20 | [InlineData("js-lodash", "js-", "", "lodash")] 21 | [InlineData("node-example", "node-", "", "example")] 22 | [InlineData("jsrxjs", "js", "", "rxjs")] 23 | public void TestReplaceAtStart(string original, string oldValue, string newValue, string expected) 24 | { 25 | Assert.Equal(expected, original.ReplaceAtStart(oldValue, newValue)); 26 | } 27 | } -------------------------------------------------------------------------------- /src/oss-tests/TestData/Base64Zip.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/OSSGadget/d2cc60070831192660c98974afbddb036d07a928/src/oss-tests/TestData/Base64Zip.zip -------------------------------------------------------------------------------- /src/oss-tests/TestData/Go/go_yaml_1.3.0_info: -------------------------------------------------------------------------------- 1 | {"Version":"v1.3.0","Time":"2021-09-22T21:48:32Z"} -------------------------------------------------------------------------------- /src/oss-tests/TestData/Go/go_yaml_1.3.0_mod: -------------------------------------------------------------------------------- 1 | module sigs.k8s.io/yaml 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/davecgh/go-spew v1.1.1 7 | gopkg.in/yaml.v2 v2.4.0 8 | ) -------------------------------------------------------------------------------- /src/oss-tests/TestData/Go/go_yaml_list: -------------------------------------------------------------------------------- 1 | v1.3.0 2 | v1.0.0 3 | v1.2.0 4 | v1.1.0 -------------------------------------------------------------------------------- /src/oss-tests/TestData/Maven/maven_ant_1.6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Central Repository: ant/ant/1.6 6 | 7 | 12 | 13 | 14 | 15 |
16 |

ant/ant/1.6

17 |
18 |
19 |
20 |
21 | ../
22 | ant-1.6-sources.jar                               2005-09-20 05:44   2182693      
23 | ant-1.6-sources.jar.md5                           2005-09-20 05:44        66      
24 | ant-1.6-sources.jar.sha1                          2005-09-20 05:44        74      
25 | ant-1.6.jar                                       2005-09-20 05:44    952104      
26 | ant-1.6.jar.md5                                   2005-09-20 05:44        32      
27 | ant-1.6.jar.sha1                                  2005-09-20 05:44        40      
28 | ant-1.6.pom                                       2005-09-20 05:44       182      
29 | ant-1.6.pom.md5                                   2005-09-20 05:44       116      
30 | ant-1.6.pom.sha1                                  2005-09-20 05:44       124      
31 | maven-metadata.xml                                2005-09-20 05:44       103      
32 | maven-metadata.xml.md5                            2005-09-20 05:44        67      
33 | maven-metadata.xml.sha1                           2005-09-20 05:44       122      
34 | 		
35 |
36 |
37 | 38 | 39 | -------------------------------------------------------------------------------- /src/oss-tests/TestData/Maven/maven_ant_1.6.pom: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | ant 4 | ant 5 | Ant 6 | 1.6 7 | -------------------------------------------------------------------------------- /src/oss-tests/TestData/Maven/maven_ant_all.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Central Repository: ant/ant 7 | 8 | 13 | 14 | 15 | 16 |
17 |

ant/ant

18 |
19 |
20 |
21 |
22 | ../
23 | 1.4.1/                                            2005-09-20 05:44         -      
24 | 1.5/                                              2005-09-20 05:44         -      
25 | 1.5.1/                                            2005-09-20 05:44         -      
26 | 1.5.2/                                            2005-09-20 05:44         -      
27 | 1.5.3-1/                                          2005-09-20 05:44         -      
28 | 1.5.4/                                            2005-09-20 05:44         -      
29 | 1.6/                                              2005-09-20 05:44         -      
30 | 1.6.1/                                            2005-09-20 05:44         -      
31 | 1.6.2/                                            2005-09-20 05:44         -      
32 | 1.6.3/                                            2005-09-20 05:44         -      
33 | 1.6.4/                                            2005-09-20 05:44         -      
34 | 1.6.5/                                            2005-09-20 05:44         -      
35 | 1.7.0/                                                           -         -      
36 | maven-metadata.xml                                2005-09-20 05:44       537      
37 | maven-metadata.xml.md5                            2005-09-20 05:44        63      
38 | maven-metadata.xml.sha1                           2005-09-20 05:44       118      
39 | 		
40 |
41 |
42 | 43 | 44 | -------------------------------------------------------------------------------- /src/oss-tests/TestData/Maven/maven_ant_metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | ant 3 | ant 4 | 1.4.1 5 | 6 | 7 | 1.4.1 8 | 1.5 9 | 1.5.1 10 | 1.5.2 11 | 1.5.3-1 12 | 1.5.4 13 | 1.6 14 | 1.6.1 15 | 1.6.2 16 | 1.6.3 17 | 1.6.4 18 | 1.6.5 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/oss-tests/TestData/Maven/maven_core_1.0.0_alpha2-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/OSSGadget/d2cc60070831192660c98974afbddb036d07a928/src/oss-tests/TestData/Maven/maven_core_1.0.0_alpha2-sources.jar -------------------------------------------------------------------------------- /src/oss-tests/TestData/Maven/maven_core_1.0.0_alpha2.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/OSSGadget/d2cc60070831192660c98974afbddb036d07a928/src/oss-tests/TestData/Maven/maven_core_1.0.0_alpha2.aar -------------------------------------------------------------------------------- /src/oss-tests/TestData/Maven/maven_core_1.0.0_alpha2.pom: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | android.arch.core 6 | core 7 | 1.0.0-alpha2 8 | aar 9 | https://developer.android.com/topic/libraries/architecture/index.html 10 | 2017 11 | 12 | 13 | The Apache Software License, Version 2.0 14 | http://www.apache.org/licenses/LICENSE-2.0.txt 15 | repo 16 | 17 | 18 | 19 | 20 | The Android Open Source Project 21 | 22 | 23 | 24 | scm:git:https://android.googlesource.com/platform/frameworks/support 25 | http://source.android.com 26 | 27 | 28 | 29 | com.android.support 30 | support-annotations 31 | 25.3.1 32 | compile 33 | 34 | 35 | com.android.support 36 | support-core-utils 37 | 25.3.1 38 | compile 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/oss-tests/TestData/Maven/maven_core_metadata.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | android.arch.core 4 | core 5 | 6 | 1.0.0-alpha3 7 | 1.0.0-alpha3 8 | 9 | 1.0.0-alpha1 10 | 1.0.0-alpha2 11 | 1.0.0-alpha3 12 | 13 | 20170615113008 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/oss-tests/TestData/Maven/maven_cose_20230908-javadoc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/OSSGadget/d2cc60070831192660c98974afbddb036d07a928/src/oss-tests/TestData/Maven/maven_cose_20230908-javadoc.jar -------------------------------------------------------------------------------- /src/oss-tests/TestData/Maven/maven_cose_20230908.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/OSSGadget/d2cc60070831192660c98974afbddb036d07a928/src/oss-tests/TestData/Maven/maven_cose_20230908.jar -------------------------------------------------------------------------------- /src/oss-tests/TestData/Maven/maven_cose_20230908_artifact_metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "artifacts": [ 3 | { 4 | "name": "cose-20230908-javadoc.jar", 5 | "tag": "javadoc" 6 | }, 7 | { 8 | "name": "cose-20230908.jar", 9 | "tag": "jar" 10 | }, 11 | { 12 | "name": "cose-20230908.pom", 13 | "tag": "pom" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /src/oss-tests/TestData/Maven/maven_cose_metadata.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | com.google.cose 4 | cose 5 | 6 | 20230908 7 | 20230908 8 | 9 | 20230908 10 | 11 | 20230908231136 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/oss-tests/TestData/Maven/maven_fluentui_listitem_0.0.8.pom: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.microsoft.fluentui 5 | fluentui_listitem 6 | 0.0.8 7 | aar 8 | fluentui_listitem 9 | Fluent UI Android, Module : fluentui_listitem 10 | https://github.com/microsoft/fluentui-android 11 | 12 | 13 | MIT License 14 | https://github.com/microsoft/fluentui-android/blob/master/LICENSE 15 | 16 | 17 | 18 | 19 | fluent-ui-android 20 | Microsoft Inc. 21 | fluentuinativeowners@microsoft.com 22 | 23 | 24 | 25 | scm:git:github.com/microsoft/fluentui-android.git 26 | scm:git:ssh://github.com/microsoft/fluentui-android.git 27 | https://github.com/microsoft/fluentui-android/tree/main 28 | 29 | 30 | 31 | com.microsoft.fluentui 32 | fluentui_core 33 | 0.0.8 34 | 35 | 36 | org.jetbrains.kotlin 37 | kotlin-stdlib-jdk7 38 | 1.4.30 39 | 40 | 41 | androidx.appcompat 42 | appcompat 43 | 1.2.0 44 | 45 | 46 | androidx.recyclerview 47 | recyclerview 48 | 1.1.0 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/oss-tests/TestData/Maven/maven_fluentui_listitem_metadata.xml: -------------------------------------------------------------------------------- 1 |  2 | com.microsoft.fluentui 3 | fluentui_listitem 4 | 5 | 0.3.4 6 | 0.3.4 7 | 8 | 0.0.24 9 | 0.1.0 10 | 0.1.1 11 | 0.1.2 12 | 0.1.3 13 | 0.1.4 14 | 0.1.5 15 | 0.1.6 16 | 0.1.7 17 | 0.1.8 18 | 0.1.9 19 | 0.1.10 20 | 0.1.11 21 | 0.1.12 22 | 0.1.13 23 | 0.1.14 24 | 0.1.15 25 | 0.1.16 26 | 0.1.17 27 | 0.1.18 28 | 0.1.19 29 | 0.1.20 30 | 0.1.21 31 | 0.1.22 32 | 0.2.0 33 | 0.2.1 34 | 0.2.2 35 | 0.2.3 36 | 0.3.1 37 | 0.3.2 38 | 0.3.4 39 | 40 | 20250402135938 41 | 42 | -------------------------------------------------------------------------------- /src/oss-tests/TestData/NPM/minimum_json.json: -------------------------------------------------------------------------------- 1 | {"_id":"example","name":"example","dist-tags":{"latest":"0.0.0"},"versions":{"0.0.0":{"name":"example","version":"0.0.0","_id":"example@0.0.0","_npmVersion":"1.0.0","_npmUser":{"name":"test","email":"test@microsoft.com"}}},"time":{"created":"2022-08-10T21:35:37.950Z","0.0.0":"2022-08-10T21:35:38.278Z","modified":"2022-08-10T21:35:37.950Z"}} -------------------------------------------------------------------------------- /src/oss-tests/TestData/NPM/unpublishedpackage.json: -------------------------------------------------------------------------------- 1 | {"_id":"@somosme/webflowutils","_rev":"3-9be941baa0509bbc96a1349f8464fd6d","name":"@somosme/webflowutils","time":{"created":"2022-08-10T19:49:56.913Z","1.0.0":"2022-08-10T19:49:57.198Z","modified":"2022-08-10T21:31:52.293Z","unpublished":{"time":"2022-08-10T21:31:32.856Z","versions":["1.0.0"]}},"maintainers":[{"email":"antonio@somos.me","name":"antoniomb"}]} -------------------------------------------------------------------------------- /src/oss-tests/TestData/NuGet/powershellgallery/powershell_gallery_v2.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | Default 4 | 5 | Packages 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/oss-tests/TestData/NuGet/powershellgallery/psreadline/versions.json: -------------------------------------------------------------------------------- 1 | [ 2 | "1.0.0", 3 | "1.1.0", 4 | "1.2.0", 5 | "1.2.1", 6 | "1.2.2", 7 | "1.2.3", 8 | "1.2.4", 9 | "1.2.5", 10 | "1.2.6", 11 | "1.2.7", 12 | "1.2.8", 13 | "1.2.9", 14 | "2.0.0", 15 | "2.0.1", 16 | "2.0.2", 17 | "2.0.3", 18 | "2.0.4", 19 | "2.0.5", 20 | "2.0.6", 21 | "2.0.7", 22 | "2.0.8", 23 | "2.0.9", 24 | "2.1.0", 25 | "2.2.0", 26 | "2.2.1", 27 | "2.2.2", 28 | "2.2.3", 29 | "2.2.4", 30 | "2.2.5", 31 | "2.2.6", 32 | "2.2.7", 33 | "2.2.8", 34 | "2.2.9", 35 | "2.3.0", 36 | "2.3.1", 37 | "2.3.2", 38 | "2.3.3", 39 | "2.3.4", 40 | "2.3.5", 41 | "2.3.6", 42 | "2.3.7", 43 | "2.3.8", 44 | "2.3.9", 45 | "2.4.0", 46 | "2.4.1-beta1" 47 | ] 48 | -------------------------------------------------------------------------------- /src/oss-tests/TestData/NuGet/razorengine/4.2.3-beta1.metadata.json: -------------------------------------------------------------------------------- 1 | {"authors":"Matthew Abbott, Ben Dornis, Matthias Dittrich","dependencyGroups":[{"TargetFramework":{"Framework":"Any","Version":"0.0.0.0","Platform":"","PlatformVersion":"0.0.0.0","HasPlatform":false,"HasProfile":false,"Profile":"","DotNetFrameworkName":"Any,Version=v0.0","DotNetPlatformName":"","IsPCL":false,"IsPackageBased":false,"AllFrameworkVersions":true,"IsUnsupported":false,"IsAgnostic":false,"IsAny":true,"IsSpecificFramework":false},"Packages":[{"Id":"Microsoft.AspNet.Razor","Include":[],"Exclude":[],"VersionRange":{"IsFloating":false,"Float":null,"OriginalString":"[4.0.0-beta6, )","HasLowerBound":true,"HasUpperBound":false,"HasLowerAndUpperBounds":false,"IsMinInclusive":true,"IsMaxInclusive":false,"MaxVersion":null,"MinVersion":"4.0.0-beta6"}}]}],"description":"RazorEngine - A Templating Engine based on the Razor parser.","totalDownloads":null,"iconUrl":null,"version":"4.2.1-beta1","licenseUrl":"https://github.com/Antaris/RazorEngine/blob/master/LICENSE.md","projectUrl":"https://github.com/Antaris/RazorEngine","readmeUrl":null,"packageDetailsUrl":"https://www.nuget.org/packages/RazorEngine/4.2.1-beta1?_src=template","published":"2015-08-22T07:11:33.1-04:00","owners":null,"id":"RazorEngine","requireLicenseAcceptance":false,"summary":"Simple templating using Razor syntax.","tags":"C#, razor, template, engine, programming","title":"RazorEngine","listed":true,"verified":false,"vulnerabilities":[{"advisoryUrl":"https://github.com/advisories/GHSA-ph3v-2hq5-5qfq","severity":1}],"@id":"https://api.nuget.org/v3/catalog0/data/2022.03.11.23.17.27/razorengine.4.2.1-beta1.json"} -------------------------------------------------------------------------------- /src/oss-tests/TestData/NuGet/razorengine/versions.json: -------------------------------------------------------------------------------- 1 | ["2.1.0","3.0.0","3.0.3","3.0.4","3.0.5","3.0.6","3.0.7","3.0.8","3.1.0","3.2.0","3.3.0","3.4.0","3.4.1","3.4.2","3.5.0-beta1","3.5.0-beta2","3.5.0-beta3","3.5.0","3.5.1","3.5.2","3.5.3","3.6.0","3.6.1","3.6.2","3.6.3-beta1","3.6.3-beta2","3.6.3","3.6.4","3.6.5-beta1","3.6.5","3.6.6-beta1","3.6.6-beta2","3.6.6","3.7.0-beta1","3.7.0","3.7.1-alpha1","3.7.2","3.7.3","3.7.4","3.7.5-beta1","3.7.5-beta2","3.7.5","3.7.6","3.7.7","3.8.0","3.8.1","3.8.2","3.9.0","3.9.1","3.9.2","3.9.3","3.10.0","3.10.1-alpha001","4.0.0-beta1","4.0.0-beta2","4.0.1-beta1","4.0.2-beta1","4.0.3-beta1","4.1.0-beta1","4.1.1-beta1","4.1.2-beta1","4.1.3-beta2","4.1.4-beta1","4.1.5-beta1","4.1.6-beta1","4.2.0-beta1","4.2.0-beta2","4.2.0-beta3","4.2.1-beta1","4.2.2-beta1","4.2.3-beta1","4.2.4-beta1","4.2.5-beta1","4.2.6-beta1","4.2.7-beta1","4.3.0-beta1","4.3.1-beta1","4.3.2-beta1","4.4.0-rc1","4.4.1-rc1","4.4.2-rc1","4.4.3-rc1","4.5.0-rc1","4.5.1-alpha001"] -------------------------------------------------------------------------------- /src/oss-tests/TestData/NuGet/slipeserver.scripting/index.json: -------------------------------------------------------------------------------- 1 | {"@id":"https://api.nuget.org/v3/registration5-gz-semver2/slipeserver.scripting/index.json","@type":["catalog:CatalogRoot","PackageRegistration","catalog:Permalink"],"commitId":"5c5c9ce6-0f54-4364-ac33-a79fb8bcc6d3","commitTimeStamp":"2022-11-20T18:10:52.9301862+00:00","count":4,"items":[{"@id":"https://api.nuget.org/v3/registration5-gz-semver2/slipeserver.scripting/page/0.1.0-ci-20210204-180233/0.1.0-ci-20210826-172946.json","@type":"catalog:CatalogPage","commitId":"8f3408ff-7a72-48f4-a532-cb71483f4a05","commitTimeStamp":"2022-03-25T00:36:25.7654113+00:00","count":64,"lower":"0.1.0-CI-20210204-180233","upper":"0.1.0-CI-20210826-172946"},{"@id":"https://api.nuget.org/v3/registration5-gz-semver2/slipeserver.scripting/page/0.1.0-ci-20210826-173444/0.1.0-ci-20220325-002917.json","@type":"catalog:CatalogPage","commitId":"8f3408ff-7a72-48f4-a532-cb71483f4a05","commitTimeStamp":"2022-03-25T00:36:25.7654113+00:00","count":64,"lower":"0.1.0-CI-20210826-173444","upper":"0.1.0-CI-20220325-002917"},{"@id":"https://api.nuget.org/v3/registration5-gz-semver2/slipeserver.scripting/page/0.1.0-ci-20220325-215611/0.1.0-ci-20220807-160739.json","@type":"catalog:CatalogPage","commitId":"092a36d4-efb8-4e35-8d96-74a12ed8de57","commitTimeStamp":"2022-08-07T16:12:38.9645281+00:00","count":64,"lower":"0.1.0-CI-20220325-215611","upper":"0.1.0-CI-20220807-160739"},{"@id":"https://api.nuget.org/v3/registration5-gz-semver2/slipeserver.scripting/page/0.1.0-ci-20221013-182634/0.1.0-ci-20221120-180516.json","@type":"catalog:CatalogPage","commitId":"5c5c9ce6-0f54-4364-ac33-a79fb8bcc6d3","commitTimeStamp":"2022-11-20T18:10:52.9301862+00:00","count":42,"lower":"0.1.0-CI-20221013-182634","upper":"0.1.0-CI-20221120-180516"}],"@context":{"@vocab":"http://schema.nuget.org/schema#","catalog":"http://schema.nuget.org/catalog#","xsd":"http://www.w3.org/2001/XMLSchema#","items":{"@id":"catalog:item","@container":"@set"},"commitTimeStamp":{"@id":"catalog:commitTimeStamp","@type":"xsd:dateTime"},"commitId":{"@id":"catalog:commitId"},"count":{"@id":"catalog:count"},"parent":{"@id":"catalog:parent","@type":"@id"},"tags":{"@id":"tag","@container":"@set"},"reasons":{"@container":"@set"},"packageTargetFrameworks":{"@id":"packageTargetFramework","@container":"@set"},"dependencyGroups":{"@id":"dependencyGroup","@container":"@set"},"dependencies":{"@id":"dependency","@container":"@set"},"packageContent":{"@type":"@id"},"published":{"@type":"xsd:dateTime"},"registration":{"@type":"@id"}}} -------------------------------------------------------------------------------- /src/oss-tests/TestData/oss-defog.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/OSSGadget/d2cc60070831192660c98974afbddb036d07a928/src/oss-tests/TestData/oss-defog.dll -------------------------------------------------------------------------------- /src/oss-tests/VersionTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 2 | 3 | namespace Microsoft.CST.OpenSource.Tests; 4 | 5 | using Microsoft.CST.OpenSource.PackageManagers; 6 | 7 | public class VersionTests 8 | { 9 | [Theory] 10 | [InlineData("0.1,0.2,0.3", "0.3,0.2,0.1")] 11 | [InlineData("0.1,0.3,0.2", "0.3,0.2,0.1")] 12 | [InlineData("0.04,0.03,0.02", "0.04,0.03,0.02")] 13 | [InlineData("1,23,99,0,0", "99,23,1,0,0")] 14 | [InlineData("1.2.3,1.2.3.4,1.2.4", "1.2.4,1.2.3.4,1.2.3")] 15 | [InlineData("1.0.1pre-1,1.0.1pre-2,1.2,1.0", "1.2,1.0.1pre-2,1.0.1pre-1,1.0")] 16 | [InlineData("foo", "foo")] 17 | [InlineData("v1,v3,v2", "v3,v2,v1")] 18 | [InlineData("v1-rc1,v3-rc3,v2-rc2", "v3-rc3,v2-rc2,v1-rc1")] 19 | [InlineData("v1-rc1,v1-rc3,v1-rc2", "v1-rc3,v1-rc2,v1-rc1")] 20 | [InlineData("234,73", "234,73")] 21 | [InlineData("73,234", "234,73")] 22 | public async Task TestVersionSort(string preSortS, string postSortS) 23 | { 24 | string[]? preSort = preSortS.Split(new[] { ',' }); 25 | string[]? postSort = postSortS.Split(new[] { ',' }); 26 | System.Collections.Generic.IEnumerable? result = BaseProjectManager.SortVersions(preSort); 27 | Assert.True(result.SequenceEqual(postSort), $"Result {string.Join(',', result)} != {string.Join(',', postSort)}"); 28 | } 29 | } -------------------------------------------------------------------------------- /src/oss-tests/oss-tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0;net8.0 5 | enable 6 | enable 7 | false 8 | true 9 | 10 | 11 | 12 | DEBUG;TRACE 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | runtime; build; native; contentfiles; analyzers; buildtransitive 25 | all 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | PreserveNewest 36 | 37 | 38 | PreserveNewest 39 | 40 | 41 | 42 | 43 | ResXFileCodeGenerator 44 | Resources.Designer.cs 45 | 46 | 47 | 48 | 49 | True 50 | True 51 | Resources.resx 52 | 53 | 54 | -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", 3 | "version": "0.2", 4 | "publicReleaseRefSpec": [ 5 | "^refs/heads/main$", 6 | "^refs/heads/v\\d+(?:\\.\\d+)?$" 7 | ], 8 | "cloudBuild": { 9 | "buildNumber": { 10 | "enabled": true 11 | } 12 | } 13 | } 14 | --------------------------------------------------------------------------------