ASP.NET | News: Recent Episodes

None

News from the ASP.NET and Visual Studio web team

View Details

OpenSSF Scorecard is a tool developed by the Open Source Security Foundation (OpenSSF) that provides automated security assessments for open-source projects. The primary goal of the Scorecard project is to help developers and users determine the security posture of open-source software by generating a score based on a series of security-related checks.

Using Scorecard, developers can assess the risks associated with each check and make informed decisions about accepting these risks, evaluating alternative solutions, or making improvements.

Moreover, while projects can use GitHub Actions to generate a scorecard for their specific project (the OpenSSF also generates scorecards on behalf of many popular open source projects), it’s also possible for a security team or an Open Source Programs Office (OSPO) to generate the scorecards at scale. For example, at Microsoft, OSPO regularly computes scores for all public and private repositories, making historical information and trends available to teams. The image below illustrates the score of a Microsoft owned repository. Note that project owners can dig into all aspects of the scorecard, not just see the score.

OverviewThis article is specifically aimed at .NET maintainers, showcasing how Scorecard and its recently introduced support for .NET can help enhance both the security and quality of the ecosystem.

It explores the implications of this support, identifies gaps where maintainers can contribute to further improve Scorecard and shares insights from our research on the .NET open-source ecosystem, revealing several low-hanging fruits that maintainers should address to strengthen the security of their projects.

We believe that by focusing on these areas, we, as .NET developers, can bring a significant enhancement to our community’s security posture and contribute to a more secure open-source ecosystem.

What is Scorecard and why should you use itScorecard has the following key features:

  1. Automated Security Checks: The tool performs a set of security-related checks on an open-source project, such as dependency management, continuous integration (CI) usage, security testing, and code review practices.
  2. Scoring System: Each project is evaluated against these security checks and receives a score (on a scale of 0 to 10) that reflects the overall security maturity of the project.
  3. Security Best Practices: The checks are based on security best practices for open-source development, such as the use of pinned dependencies, branch protection, code reviews, and fuzzing.
  4. Ease of Use: Developers and users can easily run Scorecard checks on their repositories via GitHub Actions, as well as view public scorecards for popular open-source projects.
  5. Community and Ecosystem Support: As part of OpenSSF’s initiatives, the Scorecard project helps improve the overall security of the open-source ecosystem by encouraging maintainers to adopt secure development practices.

Using the OpenSSF Scorecard for a project is important because it helps ensure that the open-source software you maintain follows essential security best practices. It can also be used to evaluate whether dependencies you take into your codebase meet your expected level of adherence to security practices.

Today, Scorecard is recognized and utilized across various sectors of the software engineering industry. For instance, it is mentioned in the Cybersecurity and Infrastructure Security Agency (CISA) Tools and Resources. Moreover, Sonatype, who specialize in software supply chain automation and security, references its checks and recommends its adoption in their annual reports. Google’s Open Source Insights project highlights the scorecard checks of each package shown.

This is why it matters:

  1. Identifying Security Risks

Open-source projects are widely used across industries but can be vulnerable to security risks if not properly managed. Scorecard helps identify these risks by evaluating key security practices such as dependency management, code reviews, and CI workflows, enabling developers to take proactive steps to enhance security and prevent incidents like data breaches or system compromises.

  1. Improving Software Quality

Scorecard checks promote good development practices, such as enforcing code reviews, updating dependencies, and using security tools like fuzzing and static analysis, which enhance both security and code quality. By identifying gaps in these areas, Scorecard helps teams prioritize improvements and manage technical debt effectively.

  1. Building Trust with Users

Projects with a high security score on the OpenSSF Scorecard show users, contributors, and businesses that security is a priority, building trust and encouraging adoption as users are more likely to rely on software that is actively following secure development practices. For enterprises and government organizations, this trust is essential for integrating open-source software into their infrastructure.

  1. Meeting Compliance Requirements

Many organizations have strict security and compliance requirements (e.g., SOC 2, ISO 27001) that mandate secure software development practices. Scorecard provides an objective evaluation of a project’s security posture, helping maintainers meet these standards and making it easier for organizations to pass audits and regulatory checks.

  1. Transparency in Security Posture

Open-source projects are often maintained by small teams or volunteers, making it difficult for users to assess their security. Scorecard provides transparency by generating an automated, easy-to-read security score that anyone can view, helping users and contributors make informed decisions about which projects to trust or support.

  1. Encouraging Secure Best Practices

Scorecard encourages project maintainers to adopt secure practices like branch protection, regular security reviews, and integrating automated tools in CI/CD pipelines. By using Scorecard, teams can identify and improve weak areas, ensuring they consistently follow security best practices as their project evolves.

  1. Preventing Supply Chain Attacks

A major concern in modern software development is the risk of supply chain attacks, where attackers compromise project dependencies or processes to inject malicious code. Scorecard assesses how effectively a project manages its dependencies, which is vital for preventing such attacks. Projects with strong scores in dependency management ensure that their dependencies are updated, verified, and secure, minimizing the risk of exploitation by malicious actors.

What are the checks run by ScorecardThe checks listed in the table below are automatically executed against a target project by default.

| Name | Description | Risk Level | | --- | --- | --- | | Binary-Artifacts | Is the project free of checked-in binaries? | High | | Branch-Protection | Does the project use Branch Protection? | High | | CI-Tests | Does the project run tests in CI, e.g. GitHub Actions, Prow? | Low | | CII-Best-Practices | Has the project earned an OpenSSF (formerly CII) Best Practices Badge at the passing, silver, or gold level? | Low | | Code-Review | Does the project practice code review before code is merged? | High | | Contributors | Does the project have contributors from at least two different organizations? | Low | | Dangerous-Workflow | Does the project avoid dangerous coding patterns in GitHub Action workflows? | Critical | | Dependency-Update-Tool | Does the project use tools to help update its dependencies? | High | | Fuzzing | Does the project use fuzzing tools, e.g. OSS-Fuzz, QuickCheck or fast-check? | Medium | | License | Does the project declare a license? | Low | | Maintained | Is the project at least 90 days old, and maintained? | High | | Pinned-Dependencies | Does the project declare and pin dependencies? | Medium | | Packaging | Does the project build and publish official packages from CI/CD, e.g. GitHub Publishing? | Medium | | SAST | Does the project use static code analysis tools, e.g. CodeQL, LGTM (deprecated), SonarCloud? | Medium | | Security-Policy | Does the project contain a security policy? | Medium | | Signed-Releases | Does the project cryptographically sign releases? | High | | Token-Permissions | Does the project declare GitHub workflow tokens as read only? | High | | Vulnerabilities | Does the project have unfixed vulnerabilities? Uses the OSV service? | High | | Webhooks | Does the webhook defined in the repository have a token configured to authenticate the origins of requests? | Critical |

What is supported for .NET/NuGetFor the past two years, Scorecard has started to implement dedicated support for projects within the .NET ecosystem, which use the NuGet package manager. The most recent features added are support for checking pinned dependencies when restoring packages using a lock file and when using Central Package Management.

We would like to extend a special Thank you to the team who implemented and coordinated these contributions, listed alphabetically:

  • Arturo Ortiz
  • Avishay Balter
  • Ioana Amarande
  • Joel Verhagen
  • Jon Douglas
  • Liam Moat
  • Melanie Guittet

Running Scorecard on a NuGet packageTo run a scorecard locally, you can check out the OpenSSF Scorecard documentation. You can then run Scorecard with the repository name as the input (--repo=[YOUR REPO NAME]) or you can run it with the name of a NuGet package for one that is hosted on NuGet.org. To do that you need to specify the --nuget flag and provide the package name for which you want the corresponding GitHub source code to be checked.

For example: --nuget=Newtonsoft.Json

Note that this feature is only supported for packages that define the repository attribute in their package metadata .nuspec file.

PackagingThis check evaluates whether the project is published as a package. Packages make it easier for users to download, install, update, and receive security patches via a package manager. The check currently looks for GitHub packaging workflows and language-specific GitHub Actions that upload the package to NuGet and other package managers.

Note that if a project uses different packaging tools, it may still receive a low score, as Scorecard can’t detect all packaging methods. A low score doesn’t necessarily mean the project is at risk. If your packaging method isn’t recognized, consider opening an issue with the Scorecard maintainers.

In case your project receives a low score on this check, you can try the following remediation steps:

  • Publish your project as a downloadable package, e.g., if hosted on GitHub, use GitHub’s mechanisms for publishing a package.
  • If hosted on GitHub, use a GitHub action to release your package to language-specific hubs.

Pinned dependenciesFor restoring NuGet packages, it is considered best practice to use Central Package Management (CPM) and/or a lock file to fully lock down the package dependency graph, ensuring consistent and repeatable builds while also preventing counter dependency confusion (also known as substitution) attacks. These are supply chain attacks where a malicious package with the same name as an internal dependency is uploaded to a public repository, tricking systems into downloading and using it instead of the legitimate package. More information can be found here.

This Scorecard check aims to determine whether the project pins its dependencies during the build and release process. A “pinned dependency” refers to a dependency explicitly set to a specific hash, rather than allowing a mutable version or version range.

The check typically identifies unpinned dependencies in Dockerfiles, shell scripts, and GitHub workflows used in the build and release stages of the project. For .NET/NuGet, Scorecard detects potential risks when installing or restoring NuGet packages without using Central Package Management or without specifying the locked mode flag either in the restore command or via the RestorePackagesWithLockFile attribute in all the .csproj files.

This makes sure the repository is either using the built-in security mechanism in nuget.org that cryptographically validates the dependencies you’re using (when using CPM), or that a lock file is used to do the same during build time.

Examples:The following CLI commands will be marked as a pinned dependency:

nuget restore -LockedModedotnet.exe restore --locked-modemsbuild.exe /t:restore /p:RestoreLockedMode=true The following commands will be marked as unpinned dependencies:

nuget restoredotnet.exe restoremsbuild.exe /t:restore Unless, you either:

  • set ManagePackageVersionsCentrally to true in the directory.*.props file AND add a specific version to all included packages OR
  • set theRestorePackagesWithLockFile attribute to true in all .csproj files in the repository.

In case your project receives a low score on the pinned dependencies check, you can try the following remediation steps:

  • If your project is producing an application, declare all your dependencies with specific versions in your package format file (e.g. packages.config for NuGet).
  • If the package manager supports lock files (e.g. packages.lock.json for NuGet), check these in the source code. The files maintain signatures for the entire dependency tree and prevent future exploitation in case the package is compromised.
  • For Dockerfiles, pin dependencies by hash as in this example. If using a manifest list, pin to the manifest list hash instead.
  • In GitHub workflows used in building and releasing your project, pin dependencies by hash. See main.yaml for example. To determine the permissions needed for your workflows and pin actions to commit SHAs, you may use StepSecurity’s online tool.
  • To update dependencies after pinning, use tools such as Dependabot and Renovate bot.

An analysis of Scorecard checks for .NET open source repositories on GitHubOn GitHub, there are over 1,000 C# and F# repositories with more than 1,500 stars. Our team analyzed the Scorecard scores for these repositories using the public Scorecard API to get an ecosystem-wide view of the state of .NET open-source projects.

The diagram below displays the average scores for all Scorecard checks for those repositories. Please note that scores below zero are not relevant and may indicate an error during the Scorecard check execution.

It’s especially noteworthy to look at the most critical security check, Dangerous Workflows. In this case, the check either receives a perfect score of 10 or identifies an error, which occurs in over 250 repositories. This reveals existing support gaps and highlights opportunities to improve Scorecard by contributing to it.

Moreover, the pinned dependency scores show a gap in support for the NuGet ecosystem that should be improved given the recent work that was done. As these features were newly released at the time this article was written, the change in score is still not visible. There is a similar gap in support for packaging that can be better addressed by Scorecard to further detect the NuGet ecosystem.

Other checks illustrated below, which are not tied to specific ecosystems and rely solely on GitHub APIs, highlight low-hanging fruit opportunities for .NET ecosystem maintainers to make improvements and enhance open-source security. Some of them like having branch protection mechanisms in place, have only read permissions for GH tokens, SAST (usage of static code analysis tools) and do code reviews would be easy to implement and have a big impact on the overall security of the repository.

Recommendations and action itemsWith the recent improvements in handling pinned dependencies and packaging checks for the NuGet package manager, the ability to assess the security features of GitHub repositories in the .NET ecosystem will be substantially enhanced. This should encourage repositories’ maintainers to adopt necessary improvements, leading to higher scores measured by Scorecard and improved overall security of the entire .NET ecosystem.

In conclusion, regularly running OpenSSF Scorecard checks helps ensure your project stays secure, up-to-date, and aligned with coding best practices. This proactive approach significantly reduces the risk of security vulnerabilities within your software ecosystem.

Don’t delay! Check the Scorecard of your favorite GitHub repository today and if you’d like to improve the score, take a look at the suggested mitigation steps. Furthermore, if you are interested to contribute and enhance the Scorecard capabilities for the .NET ecosystem you can find ideas in the next section .

References and future workThe following links capture open issues for extending the OpenSSF Scorecard support for the .NET and NuGet ecosystem:

  • Add support for NuGet – over-arching issue tracking all ongoing work related to .NET/NuGet
  • Support for Windows containers (and for Powershell in Dockerfiles)
  • Checks should support Powershell scripts
  • Pinned Dependency checks support for Azure DevOps Pipelines
  • Pinned Dependency checks for NuGet/.NET does not consider implicit restore

The post OpenSSF Scorecard for .NET and the NuGet ecosystem appeared first on The NuGet Blog.

View Details

I use my webcam constantly for streaming and I'm pretty familiar with all the internals and how the camera model on Windows works. I also use OBS extensively, so I regularly use the OBS virtual camera and flow everything through Open Broadcasting Studio.

For my podcast, I use Zencastr which is a web-based app that talks to the webcam via the browser APIs. For YouTubes, I'll use Riverside or StreamYard, also webapps.

I've done this reliably for the last several years without any trouble. Yesterday, I started seeing the most weird thing and it was absolutely perplexing and almost destroyed the day. I started seeing regular pauses in my webcam stream but only in two instances.

  • The webcam would pause for 10-15 seconds every 90 or so seconds when access the Webcam in a browser
  • I would see a long pause/hang in OBS when double clicking on my Video Source (Webcam) to view its properties

Micah initially said USB but my usb bus and hubs have worked reliably for years. Thought something might have changed in my El Gato capture device, but that has also been rock solid for 1/2 a decade. Then I started exploring virtual cameras and looked in the windows camera dialog under settings for a list of all virtual cameras.

Interestingly, virtual cameras don't get listed under Cameras in Settings in Windows:

From what I can tell, there's no user interface to list out all of your cameras - virtual or otherwise - in windows.

Here's a quick PowerShell script you can run to list out anything 'connected' that also includes the string "cam" in your local devices

Get-CimInstance -Namespace root\cimv2 -ClassName Win32\_PnPEntity | Where-Object { $\_.Name -match 'Cam' } | Select-Object Name, Manufacturer, PNPDeviceID and my output

Name Manufacturer PNPDeviceID ---- ------------ ----------- Cam Link 4K Microsoft USB\VID\_0FD9&PID\_0066&MI\_00\7&3768531A&0&0000 Digital Audio Interface (2- Cam Link 4K) Microsoft SWD\MMDEVAPI\{0.0.1.00000000}.{AF1690B6-CA2A-4AD3-AAFD-8DDEBB83DD4A} Logitech StreamCam WinUSB Logitech USB\VID\_046D&PID\_0893&MI\_04\7&E36D0CF&0&0004 Logitech StreamCam (Generic USB Audio) USB\VID\_046D&PID\_0893&MI\_02\7&E36D0CF&0&0002 Logitech StreamCam Logitech USB\VID\_046D&PID\_0893&MI\_00\7&E36D0CF&0&0000 Remote Desktop Camera Bus Microsoft UMB\UMB\1&841921D&0&RDCAMERA\_BUS Cam Link 4K (Generic USB Audio) USB\VID\_0FD9&PID\_0066&MI\_03\7&3768531A&0&0003 Windows Virtual Camera Device Microsoft SWD\VCAMDEVAPI\B486E21F1D4BC97087EA831093E840AD2177E046699EFBF62B27304F5CCAEF57 However, when I list out my cameras using JavaScript enumerateDevices() like this

``` // Put variables in global scope to make them available to the browser console.
async function listWebcams() {
try {
const devices = await navigator.mediaDevices.enumerateDevices();
const webcams = devices.filter(device => device.kind === 'videoinput');

if (webcams.length > 0) {  
  console.log("Connected webcams:");  
  webcams.forEach((webcam, index) => {  
    console.log(`${index + 1}. ${webcam.label || `Camera ${index + 1}`}`);  
  });  
} else {  
  console.log("No webcams found.");  
}

} catch (error) {
console.error("Error accessing media devices:", error);
}
}
listWebcams(); ``` I would get:

Connected webcams:test.html:11 1. Logitech StreamCam (046d:0893)test.html:11 2. OBS Virtual Camera (Windows Virtual Camera)test.html:11 3. Cam Link 4K (0fd9:0066)test.html:11 4. LSVCamtest.html:11 5. OBS Virtual Camera So, what, what's LSVCam? And depending on how I'd call it I'd get the pause and

getUserMedia error: NotReadableError NotReadableError: Could not start video source Some apps could see this LSVCam and others couldn't. OBS really dislikes it, browsers really dislike it and it seemed to HANG on enumeration of cameras. Why can parts of Windows see this camera and others can't?

I don't know. Do you?

Regardless, it turns that it appears once in my registry, here (this is a dump of the key, you just care about the Registry PATH)

``` Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\CLSID{860BB310-5D01-11d0-BD3B-00A0C911CE86}\Instance\LSVCam]
"FriendlyName"="LSVCam"
"CLSID"="{BA80C4AD-8AED-4A61-B434-481D46216E45}"
"FilterData"=hex:02,00,00,00,00,00,20,00,01,00,00,00,00,00,00,00,30,70,69,33,\
08,00,00,00,00,00,00,00,01,00,00,00,00,00,00,00,00,00,00,00,30,74,79,33,00,\
00,00,00,38,00,00,00,48,00,00,00,76,69,64,73,00,00,10,00,80,00,00,aa,00,38,\
9b,71,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 ``` If you want to get rid of it, delete HKEY_CLASSES_ROOT\CLSID{860BB310-5D01-11d0-BD3B-00A0C911CE86}\Instance\LSVCam

WARNING: DO NOT delete the \Instance, just the LSVCam and below. I am a random person on the internet and you got here by googling, so if you mess up your machine by going into RegEdit.exe, I'm sorry to this man, but it's above me now.

Where did LSVCam.dll come from, you may ask? TikTok Live Studio, baby. Live Studio Video/Virtual Cam, I am guessing.

``` Directory of C:\Program Files\TikTok LIVE Studio\0.67.2\resources\app\electron\sdk\lib\MediaSDK_V1

09/18/2024 09:20 PM 218,984 LSVCam.dll
1 File(s) 218,984 bytes ``` This is a regression that started recently for me, so it's my opinion that they are installing a virtual camera for their game streaming feature but they are doing it poorly. It's either not completely installed, or hangs on enumeration, but the result is you'll see hangs on camera enumeration in your apps, especually browser apps that poll for cameras changes or check on a timer.

Nothing bad will happen if you delete the registry key BUT it'll show back up when you run TikTok Studio again. I still stream to TikTok, I just delete this key each time until someone on the TikTok Studio development team sees this blog post.

Hope this helps!


© 2021 Scott Hanselman. All rights reserved.

View Details

IntroductionIn November 2023 (NuGet 6.8, Visual Studio 17.8, .NET SDK 8.0.100), we released NuGet Audit. NuGet Audit provides warnings during restore when a package with a known vulnerability is used by a project. More information about NuGet Audit, including detailed configuration options can be found on our learn website. New features are still being added, so if you haven’t read the docs recently, consider having another look, or check our release notes, to see if new features that may help you have been added.

Here is a quick summary of available settings that will be available in NuGet 6.12, Visual Studio 17.12, .NET SDK 9.0.100.

| Setting | Description | | --- | --- | | NuGetAudit (property) | Enable or disable NuGetAudit | | NuGetAuditMode (property) | Report only direct packages with known vulnerabilities, or report both directory and transitive packages with known vulnerabilities. | | NuGetAuditSeverity (property) | Selects the minimum vulnerability severity to report on. | | NuGetAuditSuppress (item) | Don’t warn about specific advisory URLs. | | WarningsNotAsErrors (property) | This is not NuGet Audit specific, but if your project uses TreatWarningsAsErrors, consider adding NU1901, NU1902, NU1903, and NU1904 to this list to avoid newly disclosed package vulnerabilities from causing restore and build failures. |

A significant change in NuGet Audit in .NET 9 and VS 17.12 is that the NuGetAuditMode default has changed from “direct” to “all”. Projects using TreatWarningsAsErrors may see new errors. You can use WarningsNotAsErrors to keep treating NuGet Audit’s warnings as warnings. Using a Directory.Build.props file can be used to automatically set it in all projects contained within all subdirectories.

What it looks likeOn command line restores, NuGet Audit’s warnings will appear like any other MSBuild warning or error:

D:\src\test\vulnTest\ClassLib1\ClassLib1.csproj : warning NU1903: Package ‘Newtonsoft.Json’ 9.0.1 has a known high severity vulnerability, https://github.com/advisories/GHSA-5crp-9r3c-p9vr [D:\src\test\vulnTest\vulnTest.sln]

In Visual Studio, these warnings will appear in the Error List window

Solution Explorer will show a yellow bar warning you at least one project has a package with a known vulnerability. There is a clickable link to take you to NuGet’s Package Manager UI (PM UI) for the solution. Note: Currently PM UI at the solution level does not show transitive packages, only direct packages.

Additionally, projects using the newer SDK style projects will have a Dependencies node under the project, and any warnings related to a specific package displayed under the package itself. Projects using the older non-SDK style format will have a references node, rather than dependencies, and will not show additional information about package specific warnings or have overlay icons.

Recommended way to resolve warningsGetting a warning about packages with known vulnerabilities is only part of the process. Once discovered, action needs to be taken to remove the potential vulnerability from your solution.

The easiest case is when a package you reference directly has the known vulnerability, in which case you update the version to another version that fixes the vulnerability. If no newer version exists, you can try to contact the package owner, but you may need to look for an alternative package and stop using the one with a known vulnerability. See our documentation on auditing package dependencies for more tips on remediation

However, often a vulnerability will be in a transitive dependency, and the solution is not so obvious. Our recommendation is to prefer updates to packages “closest” to your direct references. Though, there’s nothing wrong with just upgrading the package with known vulnerability either.

For example, say your project references package A. Package A has a dependency on package B, which in turn has a dependency on package C. In this example, we’ll consider that package C version 1.0.0 has a known vulnerability, fixed in version 2.0.0. Our recommendation is to first try upgrading package A. If that doesn’t resolve the audit warning, then try upgrading package B. If that doesn’t resolve the audit warning, then upgrade C directly.

How to upgrade transitive packagesIn order to upgrade a transitive package to a higher version, you need to add it as a direct package reference. Our docs have more information about NuGet’s dependency resolution algorithm.

Using Central Package Management with the transitive pinning setting, CPM can automate this for you, with the added benefit that when you upgrade your direct package reference and the transitive package is no longer needed, it automatically disappears from your project’s package graph. However, note that CPM with transitive pinning will still cause packages to become dependencies if you pack your project into your own package to share with others, even if your project doesn’t directly call APIs on that package.

Suppressing specific advisoriesSometimes you might determine after a security review that your software is not at sufficient risk for a particular advisory. For example, several serialization libraries in the past had security advisories where there’s a Denial of Service (DoS) risk when an attacker can craft an input that has deep object nesting leading to a stack overflow. Usually, this can be mitigated by telling the serializer to limit the maximum allowed nesting depth. Therefore, if your software is already mitigating the package’s security risk, you might choose to suppress the specific advisory.

To do so, edit the project file with a text or XML editor, and add a NuGetAuditSuppress element within an ItemGroup.

<Project Sdk="Microsoft.NET.Sdk"> <!-- other parts of the project left out of this example --> <ItemGroup> <NuGetAuditSuppress Include="https://github.com/advisories/GHSA-6qmf-mmc7-6c2p" /> </ItemGroup></Project> You can put these MSBuild items in a Directory.Build.props file if you wish to define it in one place but apply to all projects in subdirectories. However, you may also wish to consider only putting it in specific projects that you have done a security review on, to minimize risk that a different project in the solution takes the same dependency and starts using the library in an insecure way.

However, we strongly encourage you to upgrade packages to versions without known vulnerabilities, rather than suppressing the advisory.

How to find transitive package pathThere are several ways to find the package path. Which method you prefer depends on what tools you normally use during your development.

dotnet nuget whyOn the command line, dotnet nuget why was added to the .NET SDK 8.0.400 and the .NET 9 preview 6 SDK. Pass it a project file and package id, and it will show you why the package is in your package graph, even through project references. Like other dotnet CLI commands, it only works with SDK style projects. But we’re working on an improvement where you can restore with MSBuild, then point dotnet nuget why at your project’s assets file. Stay tuned!

VS solution explorerSDK style projects also provide the full package graph under the project’s Dependency node. It’s also searchable!

First, expand search options and enable “search external files”.

Then you can search the package name, and it will show you all instances under each project’s Dependencies node.

Visual Studio NuGet Package Manager UIWhen you look at the Installed tab in Visual Studio’s package manager UI, when the project uses PackageReference for package management, it will show both direct and transitive packages. Currently this only happens when you manage packages for a project, not for the solution, although we’re working to improve this.

If you mouse hover of a package in the package list, the tooltip will include the name of one direct package that has caused that transitive package to be included in the project.

Looking at the assets file manuallyAll of the above experiences are based on reading NuGet’s assets file, so if none of them work for you, you can always look at the assets file directly to find the same information. The assets file should not be considered a stable format, so we do not recommend building tools that read the file. We already have upcoming feature plans which need to introduce breaking changes in the json schema, though we will change the version number at the top of the file. But this is not a problem when viewing and searching the file manually.

Generally, the assets file can be found in the obj/project.assets.json under your project’s directory, but if you use the .NET SDK’s artifacts output layout, or otherwise change the default layout, you can also find the location by running the following command on a command prompt:

dotnet msbuild -getProperty:ProjectAssetsFile If your project is non-SDK style, you may get an error about an import that can’t be found. In this case, open Visual Studio’s Developer Command Prompt, and remove the dotnet from the command line, to use Visual Studio’s MSBuild.exe directly.

Use a text editor to search for the package id that has a known vulnerability, look through potentially multiple search results, and you’ll be able to find which packages list that package as a dependency. Repeat with the other packages until you find the information you’re looking for, perhaps the package your project directly references. Here’s an example showing that Newtonsoft.Json, and a few other packages, are dependencies of the package NuGet.Packaging:

"NuGet.Packaging/5.11.3": { "type": "package", "dependencies": { "Newtonsoft.Json": "9.0.1", "NuGet.Configuration": "5.11.3", "NuGet.Versioning": "5.11.3", "System.Security.Cryptography.Cng": "5.0.0", "System.Security.Cryptography.Pkcs": "5.0.0" }, Notes on specific packagesSystem.Net.Http and System.Text.RegularExpressionsThese packages are from .NET Core 1.x, and made redundant since .NET Core 2.0. Since all supported .NET platforms also support .NET Standard 2.0, we do not recommend using versions of .NET Standard below 2.0. If your project directly references either of these packages (or any other System. package version 4.), you can remove the package reference, as the assembly is built into the target framework’s reference assemblies. If your project is getting these packages transitively, follow our previous guidance in preferring to upgrade packages closer to your project. Hopefully there’s a newer version of the package that no longer uses .NET Standard 1.x or these packages.

Runtime packagesIf you look at some of the .NET platform’s security advisories, for example GHSA-hhc7-x9w4-cw47, or GHSA-7fcr-8qw6-92fr, you can see the packages affected all start with Microsoft.NetCore.App.Runtime.* or Microsoft.AspNetCore.App.Runtime.*. These packages are not referenced directly by your project but are instead implicitly added by the .NET SDK itself. In order to stop using vulnerable versions of these packages you must upgrade to a newer version of the .NET SDK.

Upcoming improvementsWork on improving the experience detecting and managing packages with known vulnerabilities hasn’t stopped. Here are some upcoming features we’re working on. You can search our GitHub issues for issues labeled with NuGetAudit to see existing ideas and bug reports. If you have an idea and can’t find an existing issue to upvote, you can create a new feature request there.

Audit sourcesWhen NuGet Audit was first released, it only searched your configured package sources for a vulnerabilities database to check your project against. If none of your package sources provides a vulnerability database, then NuGet Audit doesn’t run. While nuget.org provides a vulnerability database, and most people use nuget.org as a package source, some people intentionally do not, in order to minimize different risks. The upcoming audit sources feature will allow you to configure nuget.org as an audit source, without it also being a package source. The best of both worlds!

PM UI improvementsCurrently Visual Studio’s NuGet Package Manager UI only shows transitive packages that are dependencies of packages that the project references directly. But it does not show packages that only come in via project references. This will be changed.

Additionally, when you mouse hover over a transitive package, it shows which direct package reference has caused the transitive package to be included in the project. If a transitive package is brought in by multiple top level packages, only one of the top level packages will be reported. We’re going to improve this so that more information is available, since non-SDK style projects don’t have the Solution Explorer view that SDK style project have.

Supplied By PlatformNuGet and the .NET SDK team are working on a feature named Supplied By Platform, which will allow the .NET SDK to inform NuGet which packages are now part of the .NET reference assemblies. This will allow NuGet to automatically cull those packages from the restore graph. This means that not only will packages like System.Net.Http and System.Text.RegularExpressions automatically be removed and prevent NuGet Audit warnings, but restore performance will improve because any package that lists NETStandard.Library as a dependency (typically version 1.6.1), will have tens of packages removed from the graph, meaning fewer packages to download and recursively check for their own dependencies.

dotnet nuget audit fixWe also want to provide a way to automatically resolve all your project’s known vulnerabilities by running a single command. It will implement the recommended approach described above, analyzing the package graph and testing upgrades find which combination of upgrades removes all packages with known vulnerabilities. Like any automated tool, it won’t be perfect for all scenarios. For example, if a package with a known vulnerability only has fixes in package versions with breaking changes, the fix to resolve known vulnerabilities may leave your project failing to build. But we believe that it will be a good and quick solution for most developers.

SummaryWe covered upcoming changes to NuGet Audit, detailing how to identify and resolve vulnerabilities in your NuGet packages. You learned how to set severity levels, suppress specific advisories, and use new tools to manage vulnerabilities and maintain security. Stay tuned for future enhancements to simplify vulnerability management and be sure to view the docs for up-to-date information.

The post NuGetAudit 2.0: Elevating Security and Trust in Package Management appeared first on The NuGet Blog.

View Details

Despite significant technological progress in addressing complex security threats, the key to preventing the next attack lies in adhering to fundamental security principles. It’s essential to ensure the software ecosystem is secure, focusing on protecting .NET developers who design, build, and maintain the critical software we all use.

As the home to one of the world’s largest developer communities, NuGet is in a unique position to help improve the security of the software supply chain. In 2022, we launched several initiatives aimed at enhancing supply chain security and prioritizing the protection of developers.

In the past year, NuGet expanded by over 52,000 unique packages, a 15% increase, and saw 176 billion package downloads, up 58%. Alongside this growth, security challenges have also increased. Last year, NuGet had 267 security advisories; now, that number has doubled to ~616, affecting thousands of widely-used package versions.

OSS Secure Software Supply Chain Growth However, NuGet is not alone in facing these issues. The entire software supply chain is experiencing similar growth and challenges. According to the recent SonaType State of the Software Supply Chain report, it highlights:

  • 1/8 OSS downloads have known risk.
  • ~245,000 malicious packages have been discovered in 2023 – 2x all previous years combined.
  • ~19% of OSS that were maintained in 2022, are not maintained today.
  • 67% of consumers feel confident that their applications do not rely on known vulnerable libraries despite 10% reporting a security breach caused by OSS.
  • ~96% of known vulnerabilities have a fixed version available as they are disclosed.

Security remains a crucial concern in today’s world as new supply chain attacks are discovered daily, featuring sophisticated tactics that target central registries and keep their maintainers on high alert. In an environment where applications rely on thousands of dependencies, software security extends beyond just your own code to encompass every piece of code you depend on. It’s not unusual for 90% of the code in applications to come from open source dependencies. Developers often cannot scrutinize every line of code in these dependencies. Open source relies on trust, and as a community, it often takes time to identify malicious packages and address them.

Noise and Signal Developers and security teams are overwhelmed by a deluge of non-essential alerts, leading to vulnerability fatigue. Additionally, there are inherent limitations in the security tools available, including those we provide such as:

  • High frequency of false positives.
  • Inclusion of “unreachable” vulnerabilities, or code that is never executed.
  • Reporting of developer dependencies.
  • Exaggerated severity ratings for known vulnerabilities.
  • Failure to detect ongoing supply chain attacks or malicious dependencies.

In our role as developers, it is critical to adopt a proactive security stance that goes beyond mere compliance, ensuring the integrity and origin of the packages we use. By vigilantly monitoring for vulnerabilities and keeping our dependencies updated, we safeguard our software against threats. Additionally, maintaining transparency with our software dependencies and managing controlled environments help to mitigate the risk of security breaches. This integration of robust security practices into our software development lifecycle not only aligns with national security objectives, but also enhances the security posture across the software industry.

The cybersecurity landscape today is marked by a variety of sophisticated threats targeting both individuals and organizations. Methods such as social engineering and phishing scams exploit human vulnerabilities to steal sensitive information, including credentials. Attackers often compromise Continuous Integration and Continuous Delivery (CI/CD) pipelines, injecting malicious code before software deployment. They exploit system vulnerabilities to gain unauthorized access, targeting open-source components and dependencies, which are often more susceptible to attacks.

Techniques like typosquatting involve attackers registering domains or package IDs that mimic legitimate ones to deceive users. Insider threats also loom large, with disgruntled or malicious employees potentially misusing access to sensitive information. Furthermore, attackers hijacking cloud resources can utilize the scalable computing power of victim organizations for malicious purposes. Navigating this complex and dynamic attack landscape requires a vigilant and comprehensive approach to protect organizational assets.

What We’ve Done Today, let’s explore the various measures and features that the NuGet team has implemented over the years to enhance your security, while addressing the broad spectrum of security challenges we face together.

  • HTTPS Everywhere. Ensures that all interactions with NuGet package sources are conducted over HTTPS, providing a secure channel that protects against unauthorized interception of data. This is critical for maintaining the integrity and confidentiality of software packages during transmission.
  • Central Package Management. Allowing teams to manage NuGet packages centrally. This feature reduces the risks associated with inconsistencies and vulnerabilities that can arise from using outdated or unauthorized packages. It streamlines package updates and ensures compliance with security standards across all projects.
  • Vulnerability Notifications. These notifications are essential for maintaining security, as they alert developers to known vulnerabilities within their dependencies. This proactive approach enables timely remediation, such as updating or replacing vulnerable packages before they can be exploited in an attack.
  • Package ID Prefix Reservations. Prevents malicious actors from spoofing or mimicking trusted packages by ensuring that only authorized users can publish packages under a reserved prefix. This helps maintain trust in the package ecosystem by safeguarding package identity.
  • 2FA Required. Requiring two-factor authentication for package publishers enhances security by protecting accounts from unauthorized access. This reduces the likelihood that a compromised account can be used to distribute malicious packages, thereby protecting the community and end users.
  • Package Source Mapping. This feature allows developers to specify trusted sources for their package dependencies, effectively preventing the download of packages from untrusted or compromised sources. It is a key defense against supply chain attacks, ensuring that only safe, vetted packages are used in software development.
  • Package READMEs. READMEs help you communicate with your community to help them understand how to report security concerns or policies that works best with your workflow and any other important security information regarding your package.
  • Community Reporting. Our terms and community reporting mechanisms continue to evolve with the various security threats, impersonations, and unexpected behaviors happening on the registry. We rely on you, the community to help us keep the registry secure for everyone.

What Else Can We Do? * Open ID Connect (OIDC). OIDC enhances security with robust authentication and enables convenient access across multiple services through single sign-on (SSO), making systems easier to use and more secure. * Build Provenance. Build provenance offers transparency about the origins and history of software components, which improves security assessments and compliance with regulations. * Verified Publishers. Provides an added layer of trust and security, ensuring that the software packages developers use come from reliable and vetted sources, thereby reducing the risk of malicious code entering the software supply chain. * SBOMs (Software Bill of Materials). SBOMs provide a complete list of all software components, aiding in quick vulnerability management and ensuring compliance with software licenses. * Automatically Remediate Known Vulnerabilities. Providing one-click/command experiences that will remediate known vulnerabilities in dependencies by upgrading them. * Add Static Analysis to Reduce False Positives. Use of static analysis to understand whether a vulnerable code path is actually reachable. * AI-assisted Security Tooling. Interact with a model to remediate common security challenges in your code. * And much more!

Results We’re proud of the initial achievements from the 2022 initiatives, and the impact they’ll have on ensuring the software ecosystem is more secure. We saw:

  • Two-factor authentication (2FA) adoption on NuGet.org has soared to 100% since requiring it, particularly among users who play crucial roles in the software supply chain.
  • Significant decrease in the percentage of downloads of vulnerable packages from NuGet.org, thanks to the new features in .NET 8 and Visual Studio 17.8+ tooling that now alert users to security vulnerabilities.
  • Immediate adoption of new security and usability features, such as Central Package Management and Package Source Mapping, in recent major open-source .NET projects.
  • A positive response from the .NET community regarding the management of security challenges in packages.

Doing Your Part Most package downloads with known vulnerabilities could be avoided by choosing a better, already available fixed version. This should highlight the importance for organizations/individuals to carefully select their software versions and make strategic upgrade decisions throughout their project lifecycles.

Even after identifying a critical vulnerability, a substantial number of downloads still occur on vulnerable versions of these libraries. This is concerning and indicates that organizations/individuals need to change their behavior, as critical vulnerabilities are prime targets for exploitation by malicious actors.

By making wise upgrade choices, organizations can also realize significant savings. For example, a development team could save two weeks each year. For a medium-sized company with 20 development teams, this equates to saving 1,600 hours and $240,000 annually, assuming an hourly cost of $150. Additionally, this reduces the risk associated with using these packages.

Vulnerabilities often increase in packages that are popular and widely used. These popular packages draw attention from both positive and negative sources, increasing the chances of a critical issue arising. Typically, these packages have an established disclosure process, making their vulnerabilities more noticeable.

As the timeless advice from G.I. Joe reminds us, “knowing is only half the battle.” Both organizations and individuals must be proactive and use automated systems to effectively tackle these challenges. Here’s how to stay updated on security vulnerabilities in your projects with Visual Studio and NuGet, if you prefer a video, checkout:

Paying attention to Open Source When selecting an open-source dependency for your project, it’s crucial to choose one that’s secure, compliant, and reliable. Here are some best practices to guide your decision:

Popularity: A dependency’s popularity can indicate its reliability and community support. Popular projects often have numerous users and contributors who frequently test, update, and secure the software. This high level of engagement typically means that issues like bugs and vulnerabilities are resolved quickly, enhancing the project’s stability and security.

Documentation and Coding Standards: Clear, comprehensive documentation and well-defined coding standards are vital. These elements make it easier for developers to understand, utilize, and contribute to the project, thereby reducing integration challenges and easing long-term maintenance.

Automated Updates: Choosing dependencies that support automated updates through tools like Dependabot can maintain software security and stability with minimal manual intervention, reducing exposure to vulnerabilities.

Active Maintenance: The activity level of a project is also a critical consideration. Avoid dependencies that lack recent updates or active maintenance, as they may pose security threats and leave you without support for resolving future issues.

Security Practices: Evaluate the project’s approach to security. Prefer projects that perform regular security audits, have a transparent security policy, and address vulnerabilities promptly.

License Compatibility: Ensure the project’s license is compatible with your project to prevent potential legal issues.

Project Maturity and Release Stability: Consider the project’s age and the stability of its releases. Older, well-maintained projects are likely to have undergone extensive testing and development, suggesting a mature and reliable option. Regular, stable releases indicate an actively maintained project.

By applying these criteria, you can effectively assess the suitability of integrating a specific open-source dependency into your project, ensuring it enhances your development process without increasing risk.

NuGet offers extensive metadata and best practices to guide your approach. Check out this informative video for a comprehensive overview:

Best Practices Keeping up with best practices can save you time and money when managing your dependencies. Below are some key best practices in package management, open source software, and software supply chains:

  • NuGet Security Best Practices
  • OpenSSF Guides
  • The Journey to Secure the Software Supply Chain at Microsoft

How You Can Help * For registry maintainers, begin implementing these new security practices. * For package authors, start adopting these security best practices. * For package consumers, take the initiative to educate yourself on these best practices.

We stand on the shoulders of giants, where estimates suggest that up to 90% of the code we run in production is open source. Now is a reminder to express your gratitude to these projects by supporting their ongoing maintenance and security, benefiting everyone.

For many of our initiatives, we publish open source design proposals and tracking issues. We welcome all sorts of feedback such as reactions, comments, and even evangelism to encourage others to do the same.

Summary Fundamental security principles are essential in fortifying the software supply chain and safeguarding .NET developers across the globe. NuGet is at the forefront of enhancing security, implementing critical initiatives such as HTTPS Everywhere, Central Package Management, and proactive vulnerability notifications. These measures are vital in managing the surge in package downloads and the significant increase in security advisories, ensuring our ecosystem remains robust and secure.

The challenges posed by open-source software downloads and the neglect of unmaintained OSS are significant, yet they offer an opportunity for collective action. By fostering community involvement in the creation of new security practices, we empower developers to contribute to a safer and more secure environment for all.

The post Building a Safer Future – How NuGet is Tackling Software Supply Chain Threats appeared first on The NuGet Blog.

View Details

We won’t keep you “in the dark” about this any longer… Dark Mode for NuGet.org is finally here!

Your feedback has been invaluable in making this happen. We know that eye strain is a significant issue for many developers, and we’re excited to offer a solution. Whether you prefer it for aesthetics or necessity, Dark Mode is here to enhance your experience.

Inspired by the sleek and modern design of Fluent UI, we’re integrated a color scheme that is easy on the eyes and aligns with the aesthetics of other Microsoft products.

Dark mode on NuGet.org respects your system themes settings on both Windows and Mac. Although you can manually toggle the settings (shown below), it automatically adapts to your operating system’s preferences, so there’s no need to toggle settings within NuGet.org itself! However, you can toggle between light and dark mode in your NuGet account settings, as shown below, to truly customize your experience.

With dark mode now live, it’s the perfect time for package owners to test your packages to ensure they stand out in both light and dark environments. This small step can make a big difference in how users perceive your package at a glance.

As always, we’re constantly committed to improving your experience on NuGet.org. Please direct any feedback regarding contrast, accessibility, or any other bugs to GitHub.

The post Dark Mode Now Available on NuGet.org appeared first on The NuGet Blog.

View Details

NuGet 6.10 is included in Visual Studio 2022 and .NET 8.0 out of the box. You can also download NuGet 6.10 for Windows, macOS, and Linux as a standalone executable.

In NuGet 6.10, we introduce some exciting new features and bug fixes, such as a new dotnet nuget config command, vulnerability auditing in packages.config, and improvements to cached credentials. For more information, and a detailed list of all changes, see our release notes.

NuGet 6.10 HighlightsNew features in NuGet 6.10:

  • dotnet nuget config command
  • Vulnerability auditing in packages.config
  • Improvements to cached credentials

dotnet nuget config commandYou can now run the dotnet nuget config command with paths, get, set, and unset sub-commands to easily configure and understand your NuGet environment. Here’s a few scenarios using this command:

  • dotnet nuget config paths – will list all of the NuGet.config files associated with a current working directory.
  • dotnet nuget config get all --show-path – will list all of the configuration settings and their respective file path.
  • dotnet nuget config set signatureValidationMode require – will set the signatureValidationMode property to require in your NuGet.config file.
  • dotnet nuget config unset signatureValidationMode – will unset the signatureValidationMode property in your NuGet.config file.

Vulnerability auditing in packages.configYou can now audit for known security vulnerabilities in packages.config projects. You’ll see a familiar experience as you saw with <PackageReference> last year, but for any project that hasn’t migrated from packages.config quite yet:

Improvements to cached credentialsWhen authenticating to a private NuGet package source, there can be a retry loop after a 401 Unauthorized challenge occurs instead of a 403 Forbidden, causing unnecessary delays and potential strain on internal services. In these cases, NuGet will now verify if cached credentials work before asking for new ones, decreasing the frequency of cache invalidation and excess user prompts.

Thank you to @leong-desco for discovering this issue!

ClosingNuGet 6.10 comes with some exciting new features and bug fixes that will continue to improve your experience managing packages in your .NET projects!

On behalf of the NuGet team and the entire .NET community, we’d like to express our sincere gratitude to all the community contributors who have generously given their time and expertise to improve NuGet this release. Thank you.

For more details on NuGet 6.10, see our official release notes.

FeedbackYour feedback is important to us. If there are any problems with this release, check our GitHub Issues and Visual Studio Developer Community for existing issues. For new issues within NuGet, please report a GitHub Issue. For general NuGet experience issues, let us know via the Report a Problem option found in your favorite IDE under Help > Report a Problem.

The post Announcing NuGet 6.10 appeared first on The NuGet Blog.

View Details

With the April release of C# Dev Kit, you can now manage your NuGet packages directly from Visual Studio Code using the new commands in the command palette.

To add a NuGet package to your project, use the command “NuGet: Add NuGet Package”. If you have more than one project in your solution, you will be asked to select which project you want to add the package to. Then you can search for packages by name. Then select the version you want to apply. Once you select a package, C# Dev Kit will add it to your project and update your project file and references. To update or remove a NuGet package from your project, use the commands “NuGet: Update NuGet Package” and “NuGet: Remove NuGet Package.” These commands will show you a list of the packages that are currently installed in your project and let you choose which ones you want to update or remove. C# Dev Kit will then perform the necessary changes and update your project file and references.

Here is an example of how to use the commands to add, update, and remove NuGet packages in Visual Studio Code:

https://devblogs.microsoft.com/nuget/wp-content/uploads/sites/49/2024/05/NugetAdd.mp4We would love to hear your feedback and suggestions for more features and functionality to be added to our C# Dev Kit NuGet experience. Please Report an issue through VS Code, open an issue on GitHub, or leave a comment below!

The post Announcing NuGet Commands in C# Dev Kit appeared first on The NuGet Blog.

View Details

See the canonical version of this blog post at the Microsoft Open Source Blog!

Ten years ago, Microsoft released the source for MS-DOS 1.25 and 2.0 to the Computer History Museum, and then later republished them for reference purposes. This code holds an important place in history and is a fascinating read of an operating system that was written entirely in 8086 assembly code nearly 45 years ago.

Today, in partnership with IBM and in the spirit of open innovation, we're releasing the source code to MS-DOS 4.00 under the MIT license. There's a somewhat complex and fascinating history behind the 4.0 versions of DOS, as Microsoft partnered with IBM for portions of the code but also created a branch of DOS called Multitasking DOS that did not see a wide release.

https://github.com/microsoft/MS-DOS

A young English researcher named Connor "Starfrost" Hyde recently corresponded with former Microsoft Chief Technical Officer Ray Ozzie about some of the software in his collection. Amongst the floppies, Ray found unreleased beta binaries of DOS 4.0 that he was sent while he was at Lotus. Starfrost reached out to the Microsoft Open Source Programs Office (OSPO) to explore releasing DOS 4 source, as he is working on documenting the relationship between DOS 4, MT-DOS, and what would eventually become OS/2. Some later versions of these Multitasking DOS binaries can be found around the internet, but these new Ozzie beta binaries appear to be much earlier, unreleased, and also include the ibmbio.com source.

Scott Hanselman, with the help of internet archivist and enthusiast Jeff Sponaugle, has imaged these original disks and carefully scanned the original printed documents from this "Ozzie Drop". Microsoft, along with our friends at IBM, think this is a fascinating piece of operating system history worth sharing.

Jeff Wilcox and OSPO went to the Microsoft Archives, and while they were unable to find the full source code for MT-DOS, they did find MS DOS 4.00, which we're releasing today, alongside these additional beta binaries, PDFs of the documentation, and disk images. We will continue to explore the archives and may update this release if more is discovered.

Thank you to Ray Ozzie, Starfrost, Jeff Sponaugle, Larry Osterman, our friends at the IBM OSPO, as well as the makers of such digital archeology software including, but not limited to Greaseweazle, Fluxengine, Aaru Data Preservation Suite, and the HxC Floppy Emulator. Above all, thank you to the original authors of this code, some of whom still work at Microsoft and IBM today!

If you'd like to run this software yourself and explore, we have successfully run it directly on an original IBM PC XT, a newer Pentium, and within the open source PCem and 86box emulators.


© 2021 Scott Hanselman. All rights reserved.

View Details

Action required: If you validate that packages are repository signed by NuGet.org using a NuGet client policy, NuGet.exe verify command, or the dotnet nuget verify command, please follow these steps by April 8th, 2024 to avoid potential disruptions when installing new NuGet.org packages. If you are unsure, we have outlined steps to check if you will be impacted.

Since 2018, NuGet.org has used an X.509 certificate to sign its NuGet packages. The certificate was last renewed on March 15, 2021, and is set to expire on May 15, 2024. As early as April 8th, a new certificate will replace it as the new NuGet.org repository signing certificate for NuGet packages. Existing packages already signed with the older certificate will retain their existing signature, but the older certificate will soon no longer be used to sign packages.

You may recall a similar blog post a few months ago from when we updated the Microsoft author signing certificate. The action required to accept the new NuGet.org repository signing certificate is very similar, but does have key differences outlined in the the instructions below.

Current certificate SHA-256 fingerprint: 5A2901D6ADA3D18260B9C6DFE2133C95D74B9EEF6AE0E5DC334C8454D1477DF4

New certificate SHA-256 fingerprint: 1F4B311D9ACC115C8DC8018B5A49E00FCE6DA8E2855F9F014CA6F34570BC482D

Who will be impacted?1. Customers who are using a NuGet client policy to enforce an allow list of trusted signers that includes NuGet.org.

To tell if you have a NuGet client policy configured, check for the following elements in your nuget.config. Keep in mind that you can have nuget.config files in multiple locations with different scopes.

<config> <add key="signatureValidationMode" value="require" /></config><trustedSigners> <repository name="nuget.org" serviceIndex="https://api.nuget.org/v3/index.json"> <certificate fingerprint="5A2901D6ADA3D18260B9C6DFE2133C95D74B9EEF6AE0E5DC334C8454D1477DF4" hashAlgorithm="SHA256" allowUntrustedRoot="false" /> </repository></trustedSigners> 2. Customers who use NuGet.exe verify (Windows only) to verify that signed packages are repository signed by NuGet.org.

This will look like the following in your code:

NuGet.exe verify -Signatures <PackagePath> -CertificateFingerprint 5A2901D6ADA3D18260B9C6DFE2133C95D74B9EEF6AE0E5DC334C8454D1477DF4 3. Customers who use dotnet nuget verify to verify that signed packages are repository signed by NuGet.org.

This will look like the following in your code:

dotnet nuget verify <PackagePath> --certificate-fingerprint 5A2901D6ADA3D18260B9C6DFE2133C95D74B9EEF6AE0E5DC334C8454D1477DF4 If none of the above scenarios apply to you, then you should be unaffected by the certificate update! NuGet.org packages signed with the new certificate should install in the same way as packages signed with the old certificate.

Allow the new NuGet.org certificateClient policyIf you are using a NuGet client policy to enforce an allow list of trusted signers, then you will need to add the new NuGet.org certificate to your allow list to avoid disruptions when installing NuGet.org packages signed with the new certificate. You should keep the older NuGet.org certificate as well to continue installing NuGet.org packages signed with the older certificate. If you try to install one of these newer NuGet.org packages without updating your trusted signers, you’ll get an NU3034 error and the package will fail to install.

You can explicitly trust the new NuGet.org repository signing certificate by adding to your nuget.config file the new certificate alongside any older certificates you may already have:

<trustedSigners> <repository name="nuget.org" serviceIndex="https://api.nuget.org/v3/index.json"> <certificate fingerprint="0E5F38F57DC1BCC806D8494F4F90FBCEDD988B46760709CBEEC6F4219AA6157D" hashAlgorithm="SHA256" allowUntrustedRoot="false" /> <certificate fingerprint="5A2901D6ADA3D18260B9C6DFE2133C95D74B9EEF6AE0E5DC334C8454D1477DF4" hashAlgorithm="SHA256" allowUntrustedRoot="false" /> <certificate fingerprint="1F4B311D9ACC115C8DC8018B5A49E00FCE6DA8E2855F9F014CA6F34570BC482D" hashAlgorithm="SHA256" allowUntrustedRoot="false" /> </repository></trustedSigners> NuGet.exe verifyIf you use NuGet.exe verify to verify that a signed package is repository signed by NuGet.org, you’ll need to update the command to handle either certificate like so:

NuGet.exe verify -Signatures <PackagePath> -CertificateFingerprint "0E5F38F57DC1BCC806D8494F4F90FBCEDD988B46760709CBEEC6F4219AA6157D;5A2901D6ADA3D18260B9C6DFE2133C95D74B9EEF6AE0E5DC334C8454D1477DF4;1F4B311D9ACC115C8DC8018B5A49E00FCE6DA8E2855F9F014CA6F34570BC482D" dotnet nuget verifySimilarly, if you use dotnet nuget verify to verify that a signed package is repository signed by NuGet.org, you’ll need to update the command to handle either certificate like so:

dotnet nuget verify <PackagePath> --certificate-fingerprint 0E5F38F57DC1BCC806D8494F4F90FBCEDD988B46760709CBEEC6F4219AA6157D --certificate-fingerprint 5A2901D6ADA3D18260B9C6DFE2133C95D74B9EEF6AE0E5DC334C8454D1477DF4 --certificate-fingerprint 1F4B311D9ACC115C8DC8018B5A49E00FCE6DA8E2855F9F014CA6F34570BC482D FeedbackIf you have any questions about how you may be impacted or run into issues while following the steps above, please don’t hesitate to contact us.

For more general NuGet feedback and suggestions:

  • Check out our documentation on submitting bugs and suggestions.
  • Schedule a time to talk to NuGet.
  • Reach out to us on Twitter – mention @nuget in your tweets.

The post The NuGet.org repository signing certificate will be updated as soon as April 8th, 2024 appeared first on The NuGet Blog.

View Details

Last year, we introduced search by target frameworks on NuGet.org, allowing you to filter your search results based on the framework(s) that a package targets. We received plenty of great feedback from you on how to make the filters more effective, and we are excited to announce that we are adding new search options that will now allow you to filter search results by a package’s “compatible” frameworks.

Previously, if you wanted to search for packages matching ‘net8.0’, you would only see packages that explicitly include ‘net8.0’.

Backwards compatibility is a key principle in .NET, and this means that packages targeting previous .NET versions, like ‘net6.0’ or ‘net7.0’, are also compatible with ‘net8.0’. We show this extended computed compatibility in full on the Frameworks tab of the Package Details page (See NuGet Gallery | Newtonsoft.Json 13.0.3), but so far, our filtering experience only supported filtering packages by their explicit asset frameworks.

The new “Include compatible frameworks” option we added allows you to flip between filtering by explicit asset frameworks and the larger set of ‘compatible’ frameworks. Filtering by packages’ compatible frameworks now reveals a much larger set of packages for you to choose from.

We have also added framework badges to our search results, allowing you to get a preview of the frameworks that a package supports without having to navigate away from the search page. These badges show the lowest supported framework versions from the .NET, .NET Core, .NET Standard, and .NET Framework generations. Packages are compatible with any framework version that is equal to or higher than the badge version shown.

‘Dark blue’ badges represent explicit asset frameworks, while ‘light blue’ badges represent compatible frameworks.

Clicking on a badge will redirect you to the Framework tab on the package’s Details page on NuGet.org, where you will be able to see the full list of supported frameworks.

You may have noticed that there is another new search option in the Filters panel: “Framework Filter Mode.”

With the new ‘Framework Filter Mode’ option, if you want to see packages matching any one of your framework filters rather than all of them, you can select the Any radio button.

In contrast, when you select the All option, packages will be shown that match all of your framework filters.

For more information on these new filters, or anything else related to the NuGet.org search experience, you can check out our documentation here: Find and evaluate NuGet packages | Microsoft Learn.

What’s Next?Your feedback is incredibly important to us, and we look forward to hearing more from you as you start using these new filters on NuGet.org. For new issues within NuGet.org, please report a GitHub Issue.

Our next goal is to extend the reach of these filters by bringing framework filtering to our V3 Search API too, paving the way for a richer filtering experience for clients like Visual Studio or CLI.

The post Refining Your Search: Introducing NuGet.org’s Compatible Framework Filters appeared first on The NuGet Blog.

View Details

I've been doing not just Unit Testing for my sites but full on Integration Testing and Browser Automation Testing as early as 2007 with Selenium. Lately, however, I've been using the faster and generally more compatible Playwright. It has one API and can test on Windows, Linux, Mac, locally, in a container (headless), in my CI/CD pipeline, on Azure DevOps, or in GitHub Actions.

For me, it's that last moment of truth to make sure that the site runs completely from end to end.

I can write those Playwright tests in something like TypeScript, and I could launch them with node, but I like running end unit tests and using that test runner and test harness as my jumping off point for my .NET applications. I'm used to right clicking and "run unit tests" or even better, right click and "debug unit tests" in Visual Studio or VS Code. This gets me the benefit of all of the assertions of a full unit testing framework, and all the benefits of using something like Playwright to automate my browser.

In 2018 I was using WebApplicationFactory and some tricky hacks to basically spin up ASP.NET within .NET (at the time) Core 2.1 within the unit tests and then launching Selenium. This was kind of janky and would require to manually start a separate process and manage its life cycle. However, I kept on with this hack for a number of years basically trying to get the Kestrel Web Server to spin up inside of my unit tests.

I've recently upgraded my main site and podcast site to .NET 8. Keep in mind that I've been moving my websites forward from early early versions of .NET to the most recent versions. The blog is happily running on Linux in a container on .NET 8, but its original code started in 2002 on .NET 1.1.

Now that I'm on .NET 8, I scandalously discovered (as my unit tests stopped working) that the rest of the world had moved from IWebHostBuilder to IHostBuilder five version of .NET ago. Gulp. Say what you will, but the backward compatibility is impressive.

As such my code for Program.cs changed from this

``` public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup();

``` to this:

``` public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args).
ConfigureWebHostDefaults(WebHostBuilder => WebHostBuilder.UseStartup()); ``` Not a major change on the outside but tidies things up on the inside and sets me up with a more flexible generic host for my web app.

My unit tests stopped working because my Kestral Web Server hack was no longer firing up my server.

Here is an example of my goal from a Playwright perspective within a .NET NUnit test.

``` [Test]
public async Task DoesSearchWork()
{
await Page.GotoAsync(Url);

await Page.Locator("#topbar").GetByRole(AriaRole.Link, new() { Name = "episodes" }).ClickAsync();

await Page.GetByPlaceholder("search and filter").ClickAsync();

await Page.GetByPlaceholder("search and filter").TypeAsync("wife");

const string visibleCards = ".showCard:visible";

var waiting = await Page.WaitForSelectorAsync(visibleCards, new PageWaitForSelectorOptions() { Timeout = 500 });

await Expect(Page.Locator(visibleCards).First).ToBeVisibleAsync();

await Expect(Page.Locator(visibleCards)).ToHaveCountAsync(5);

} ``` I love this. Nice and clean. Certainly here we are assuming that we have a URL in that first line, which will be localhost something, and then we assume that our web application has started up on its own.

Here is the setup code that starts my new "web application test builder factory," yeah, the name is stupid but it's descriptive. Note the OneTimeSetUp and the OneTimeTearDown. This starts my web app within the context of my TestHost. Note the :0 makes the app find a port which I then, sadly, have to dig out and put into the Url private for use within my Unit Tests. Note that the is in fact my Startup class within Startup.cs which hosts my app's pipeline and Configure and ConfigureServices get setup here so routing all works.

``` private string Url;
private WebApplication? _app = null;

[OneTimeSetUp]
public void Setup()
{
var builder = WebApplicationTestBuilderFactory.CreateBuilder();

var startup = new Startup(builder.Environment);  
builder.WebHost.ConfigureKestrel(o => o.Listen(IPAddress.Loopback, 0));  
startup.ConfigureServices(builder.Services);  
\_app = builder.Build();

// listen on any local port (hence the 0)  
startup.Configure(\_app, \_app.Configuration);  
\_app.Start();

//you are kidding me  
Url = \_app.Services.GetRequiredService<IServer>().Features.GetRequiredFeature<IServerAddressesFeature>().Addresses.Last();

}

[OneTimeTearDown]
public async Task TearDown()
{
await _app.DisposeAsync();
} ``` So what horrors are buried in WebApplicationTestBuilderFactory? The first bit is bad and we should fix it for .NET 9. The rest is actually every nice, with a hat tip to David Fowler for his help and guidance! This is the magic and the ick in one small helper class.

``` public class WebApplicationTestBuilderFactory
{
public static WebApplicationBuilder CreateBuilder() where T : class
{
//This ungodly code requires an unused reference to the MvcTesting package that hooks up
// MSBuild to create the manifest file that is read here.
var testLocation = Path.Combine(AppContext.BaseDirectory, "MvcTestingAppManifest.json");
var json = JsonObject.Parse(File.ReadAllText(testLocation));
var asmFullName = typeof(T).Assembly.FullName ?? throw new InvalidOperationException("Assembly Full Name is null");
var contentRootPath = json?[asmFullName]?.GetValue();

    //spin up a real live web application inside TestHost.exe  
    var builder = WebApplication.CreateBuilder(  
        new WebApplicationOptions()  
        {  
            ContentRootPath = contentRootPath,  
            ApplicationName = asmFullName  
        });  
    return builder;  
}

} ``` The first 4 lines are nasty. Because the test runs in the context of a different directory and my website needs to run within the context of its own content root path, I have to force the content root path to be correct and the only way to do that is by getting the apps base directory from a file generated within MSBuild from the (aging) MvcTesting package. The package is not used, but by referencing it it gets into the build and makes that file that I then use to pull out the directory.

If we can get rid of that "hack" and pull the directory from context elsewhere, then this helper function turns into a single line and .NET 9 gets WAY WAY more testable!

Now I can run my Unit Tests AND Playwright Browser Integration Tests across all OS's, headed or headless, in docker or on the metal. The site is updated to .NET 8 and all is right with my code. Well, it runs at least. ;)


© 2021 Scott Hanselman. All rights reserved.

View Details

NuGet 6.7 is included in Visual Studio 2022 and .NET 7.0 out of the box. You can also download NuGet 6.7 for Windows, macOS, and Linux as a standalone executable.

Security is a chain; it’s only as strong as its weakest link.

The post Announcing NuGet 6.7 – Keeping You Secure appeared first on The NuGet Blog.

View Details

Action required: If you validate that packages are author-signed by Microsoft using a NuGet client policy or the NuGet.exe verify command, please follow these steps by August 14th, 2023 to avoid potential disruptions when installing new Microsoft packages. If you are unsure,

The post The Microsoft author-signing certificate will be updated as soon as August 14th, 2023 appeared first on The NuGet Blog.

View Details

There are many let's encrypt automatic tools for azure but I also wanted to see if I could use certbot in wsl to generate a wildcard certificate for the azure Friday website and then upload the resulting certificates to azure app service.

Azure app service ultimately needs a specific format called dot PFX that includes the full certificate path and all intermediates.

Per the docs, App Service private certificates must meet the following requirements:

  • Exported as a password-protected PFX file, encrypted using triple DES.
  • Contains private key at least 2048 bits long
  • Contains all intermediate certificates and the root certificate in the certificate chain.

If you have a PFX that doesn't meet all these requirements you can have Windows reencrypt the file.

I use WSL and certbot to create the cert, then I import/export in Windows and upload the resulting PFX.

Within WSL, install certbot:

sudo apt update sudo apt install python3 python3-venv libaugeas0 sudo python3 -m venv /opt/certbot/ sudo /opt/certbot/bin/pip install --upgrade pip

Then I generate the cert. You'll get a nice text UI from certbot and update your DNS as a verification challenge. Change this to make sure it's two lines, and your domains and subdomains are correct and your paths are correct.

sudo certbot certonly --manual --preferred-challenges=dns --email YOUR@EMAIL.COM --server https://acme-v02.api.letsencrypt.org/directory --agree-tos --manual-public-ip-logging-ok -d "azurefriday.com" -d "*.azurefriday.com" sudo openssl pkcs12 -export -out AzureFriday2023.pfx -inkey /etc/letsencrypt/live/azurefriday.com/privkey.pem -in /etc/letsencrypt/live/azurefriday.com/fullchain.pem

I then copy the resulting file to my desktop (check your desktop path) so it's now in the Windows world.

``` sudo cp AzureFriday2023.pfx /mnt/c/Users/Scott/OneDrive/Desktop

```

Now from Windows, import the PFX, note the thumbnail and export that cert.

``` Import-PfxCertificate -FilePath "AzureFriday2023.pfx" -CertStoreLocation Cert:\LocalMachine\My
-Password (ConvertTo-SecureString -String 'PASSWORDHERE' -AsPlainText -Force) -Exportable

Export-PfxCertificate -Cert Microsoft.PowerShell.Security\Certificate::LocalMachine\My\597THISISTHETHUMBNAILCF1157B8CEBB7CA1
-FilePath 'AzureFriday2023-fixed.pfx' -Password (ConvertTo-SecureString -String 'PASSWORDHERE' -AsPlainText -Force) ```

Then upload the cert to the Certificates section of your App Service, under Bring Your Own Cert.

Then under Custom Domains, click Update Binding and select the new cert (with the latest expiration date).

Next step is to make this even more automatic or select a more automated solution but for now, I'll worry about this in September and it solved my expensive Wildcard Domain issue.


© 2021 Scott Hanselman. All rights reserved.

View Details

GitHub Next has this cool project that is basically Copilot for the CLI (command line interface). You can sign up for their waitlist at the Copilot for CLI site.

Copilot for CLI provides three shell commands: ??, git? and gh?

This is cool and all, but I use PowerShell. Turns out these ?? commands are just router commands to a larger EXE called github-copilot-cli. So if you go "?? something" you're really going "github-copilot-cli what-the-shell something."

So this means I should be able to to do the same/similar aliases for my PowerShell prompt AND change the injected prompt (look at me I'm a prompt engineer) to add 'use powershell to.'

Now it's not perfect, but hopefully it will make the point to the Copilot CLI team that PowerShell needs love also.

Here are my aliases. Feel free to suggest if these suck. Note the addition of "user powershell to" for the ?? one. I may make a ?? and a p? where one does bash and one does PowerShell. I could also have it use wsl.exe and shell out to bash. Lots of possibilities.

function ?? { 
$TmpFile = New-TemporaryFile
github-copilot-cli what-the-shell ('use powershell to ' + $args) --shellout $TmpFile
if ([System.IO.File]::Exists($TmpFile)) {
$TmpFileContents = Get-Content $TmpFile
if ($TmpFileContents -ne $nill) {
Invoke-Expression $TmpFileContents
Remove-Item $TmpFile
}
}
}

function git? {
$TmpFile = New-TemporaryFile
github-copilot-cli git-assist $args --shellout $TmpFile
if ([System.IO.File]::Exists($TmpFile)) {
$TmpFileContents = Get-Content $TmpFile
if ($TmpFileContents -ne $nill) {
Invoke-Expression $TmpFileContents
Remove-Item $TmpFile
}
}
}
function gh? {
$TmpFile = New-TemporaryFile
github-copilot-cli gh-assist $args --shellout $TmpFile
if ([System.IO.File]::Exists($TmpFile)) {
$TmpFileContents = Get-Content $TmpFile
if ($TmpFileContents -ne $nill) {
Invoke-Expression $TmpFileContents
Remove-Item $TmpFile
}
}
}

It also then offers to run the command. Very smooth.

image

Hope you like it. Lots of fun stuff happening in this space.



© 2021 Scott Hanselman. All rights reserved.

    

View Details

Mastodon is a free, open-source social networking service that is decentralized and distributed. It was created in 2016 as an alternative to centralized social media platforms such as Twitter and Facebook.

One of the key features of Mastodon is the use of the WebFinger protocol, which allows users to discover and access information about other users on the Mastodon network. WebFinger is a simple HTTP-based protocol that enables a user to discover information about other users or resources on the internet by using their email address or other identifying information. The WebFinger protocol is important for Mastodon because it enables users to find and follow each other on the network, regardless of where they are hosted.

WebFinger uses a "well known" path structure when calling an domain. You may be familiar with the robots.txt convention. We all just agree that robots.txt will sit at the top path of everyone's domain.

The WebFinger protocol is a simple HTTP-based protocol that enables a user or search to discover information about other users or resources on the internet by using their email address or other identifying information. My is first name at last name .com, so...my personal WebFinger API endpoint is here https://www.hanselman.com/.well-known/webfinger

The idea is that...

  1. A user sends a WebFinger request to a server, using the email address or other identifying information of the user or resource they are trying to discover.

  2. The server looks up the requested information in its database and returns a JSON object containing the information about the user or resource. This JSON object is called a "resource descriptor."

  3. The user's client receives the resource descriptor and displays the information to the user.

The resource descriptor contains various types of information about the user or resource, such as their name, profile picture, and links to their social media accounts or other online resources. It can also include other types of information, such as the user's public key, which can be used to establish a secure connection with the user.

There's a great explainer here as well. From that page:

When someone searches for you on Mastodon, your server will be queried for accounts using an endpoint that looks like this:

GET https://${MASTODON\_DOMAIN}/.well-known/webfinger?resource=acct:${MASTODON\_USER}@${MASTODON\_DOMAIN}

Note that Mastodon user names start with @ so they are @username@someserver.com. Just like twiter would be @shanselman@twitter.com I can be @shanselman@hanselman.com now!

Searching for me with Mastodon

So perhaps https://www.hanselman.com/.well-known/webfinger?resource=acct:FRED@HANSELMAN.COM

Mine returns

{
"subject":"acct:shanselman@hachyderm.io",
"aliases":
[
"https://hachyderm.io/@shanselman",
"https://hachyderm.io/users/shanselman"
],
"links":
[
{
"rel":"http://webfinger.net/rel/profile-page",
"type":"text/html",
"href":"https://hachyderm.io/@shanselman"
},
{
"rel":"self",
"type":"application/activity+json",
"href":"https://hachyderm.io/users/shanselman"
},
{
"rel":"http://ostatus.org/schema/1.0/subscribe",
"template":"https://hachyderm.io/authorize\_interaction?uri={uri}"
}
]
}

This file should be returned as a mime type of application/jrd+json

My site is an ASP.NET Razor Pages site, so I just did this in Startup.cs to map that well known URL to a page/route that returns the JSON needed.

services.AddRazorPages().AddRazorPagesOptions(options =>
{
options.Conventions.AddPageRoute("/robotstxt", "/Robots.Txt"); //i did this before, not needed
options.Conventions.AddPageRoute("/webfinger", "/.well-known/webfinger");
options.Conventions.AddPageRoute("/webfinger", "/.well-known/webfinger/{val?}");
});

then I made a webfinger.cshtml like this. Note I have to double escape the @@ sites because it's Razor.

@page
@{
Layout = null;
this.Response.ContentType = "application/jrd+json";
}
{
"subject":"acct:shanselman@hachyderm.io",
"aliases":
[
"https://hachyderm.io/@@shanselman",
"https://hachyderm.io/users/shanselman"
],
"links":
[
{
"rel":"http://webfinger.net/rel/profile-page",
"type":"text/html",
"href":"https://hachyderm.io/@@shanselman"
},
{
"rel":"self",
"type":"application/activity+json",
"href":"https://hachyderm.io/users/shanselman"
},
{
"rel":"http://ostatus.org/schema/1.0/subscribe",
"template":"https://hachyderm.io/authorize\_interaction?uri={uri}"
}
]
}

This is a static response, but if I was hosting pages for more than one person I'd want to take in the url with the user's name, and then map it to their aliases and return those correctly.

Even easier, you can just use the JSON file of your own Mastodon server's webfinger response and SAVE IT as a static json file and copy it to your own server!

As long as your server returns the right JSON from that well known URL then it'll work.

So this is my template https://hachyderm.io/.well-known/webfinger?resource=acct:shanselman@hachyderm.io from where I'm hosted now.

If you want to get started with Mastodon, start here. https://github.com/joyeusenoelle/GuideToMastodon/ it feels like Twitter circa 2007 except it's not owned by anyone and is based on web standards like ActivityPub.

Hope this helps!



© 2021 Scott Hanselman. All rights reserved.

    

View Details

I got tired - photo by Elisa VenturI have been blogging here for the last 20 years. Every Tuesday and Thursday, quite consistently, for two decades. But last year, without planning it, I got tired and stopped. Not sure why. It didn't correspond with any life events. Nothing interesting or notable happened. I just stopped.

I did find joy on TikTok and amassed a small group of like-minded followers there. I enjoy my YouTube as well, and my weekly podcast is going strong with nearly 900 (!) episodes of interviews with cool people. I've also recently started posting on Mastodon (a fediverse (federated universe)) Twitter alternative that uses the ActivityPub web standard. I see that Mark Downie has been looking at ActivityPub as well for DasBlog (the blog engine that powers this blog) so I need to spend sometime with Mark soon.

Being consistent is a hard thing, and I think I did a good job. I gave many talks over many years about Personal Productivity but I always mentioned doing what "feeds your spirit." For a minute here the blog took a backseat, and that's OK. I filled that (spare) time with family time, personal projects, writing more code, 3d printing, games, taekwondo, and a ton of other things.

Going forward I will continue to write and share across a number of platforms, but it will continue to start here as it's super important to Own Your Words. Keep taking snapshots and backups of your keystrokes as you never know when your chosen platform might change or go away entirely.

I'm still here. I hope you are too! I will see you soon.

Related Links:



© 2021 Scott Hanselman. All rights reserved.

    

View Details

I am not a Home Assistant expert, but it's clearly a massive and powerful ecosystem. I've interviewed the creator of Home Assistant on my podcast and I encourage you to check out that chat.

Home Assistant can quickly become a hobby that overwhelms you. Every object (entity) in your house that is even remotely connected can become programmable. Everything. Even people! You can declare that any name:value pair that (for example) your phone can expose can be consumable by Home Assistant. Questions like "is Scott home" or "what's Scott's phone battery" can be associated with Scott the Entity in the Home Assistant Dashboard.

I was amazed at the devices/objects that Home Assistant discovered that it could automate. Lights, remotes, Spotify, and more. You'll find that any internally connected device you have likely has an Integration available.

Temperature, Light Status, sure, that's easy Home Automation. But integrations and 3rd party code can give you details like "Is the Living Room dark" or "is there motion in the driveway." From these building blocks, you can then build your own IFTTT (If This Then That) automations, combining not just two systems, but any and all disparate systems.

What's the best part? This all runs LOCALLY. Not in a cloud or the cloud or anyone's cloud. I've got my stuff running on a Raspberry Pi 4. Even better I put a Power Over Ethernet (PoE) hat on my Rpi so I have just one network wire into my hub that powers the Pi.

I believe setting up Home Assistant on a Pi is the best and easiest way to get started. That said, you can also run in a Docker Container, on a Synology or other NAS, or just on Windows or Mac in the background. It's up to you. Optionally, you can pay Nabu Casa $5 for remote (outside your house) network access via transparent forwarding. But to be clear, it all still runs inside your house and not in the cloud.

OK, to the main point. I used to have an Amazon Ring Doorbell that would integrate with Amazon Alexa and when you pressed the doorbell it would say "Someone is at the front door" on our all Alexas. It was a lovely little integration that worked nicely in our lives.

However, I swapped out the Ring for a Unifi Protect G4 Doorbell for a number of reasons. I don't want to pump video to outside services, so this doorbell integrates nicely with my existing Unifi installation and records video to a local hard drive. However, I lose any Alexa integration and this nice little "someone is at the door" announcement. So this seems like a perfect job for Home Assistant.

Here's the general todo list:

  • Install Home Assistant
  • Install Home Assistant Community Store
  • This enables 3rd party "untrusted" integrations directly from GitHub. You'll need a GitHub account and it'll clone custom integrations directly into your local HA.
  • I also recommend the Terminal & SSH (9.2.2), File editor (5.3.3) add ons so you can see what's happening.

  • Get the UniFi Protect 3rd party integration for Home Assistant

  • NOTE: Unifi Protect support is being promoted in Home Assistant v2022.2 so you won't need this step soon as it'll be included.
  • "The UniFi Protect Integration adds support for retrieving Camera feeds and Sensor data from a UniFi Protect installation on either an Ubiquiti CloudKey+, Ubiquiti UniFi Dream Machine Pro or UniFi Protect Network Video Recorder."
  • Authenticate and configure this integration.

  • Get the Alexa Media Player integration

  • This makes all your Alexas show up in Home Assistant as "media players" and also allows you to tts (text to speech) to them.
  • Authenticate and configure this integration.

I recommend going into your Alexa app and making a Multi-room Speaker Group called "everywhere." Not only because it's nice to be able to say "play the music everywhere" but you can also target that "Everywhere" group in Home Assistant.

Go into your Home Assistant UI at http://homeassistant.local:8123/ and into Developer Tools. Under Services, try pasting in this YAML and clicking "call service."

service: notify.alexa\_media\_everywhere data: message: Someone is at the front door, this is a test data: type: announce method: speak

If that works, you know you can automate Alexa and make it say things. Now, go to Configuration, Automation, and Add a new Automation. Here's mine. I used the UI to create it. Note that your Entity names may be different if you give your front doorbell camera a different name.

Notice the format of Data, it's name value pairs within a single field's value.

...but it also exists in a file called Automations.yaml. Note that the "to: 'on'" trigger is required or you'll get double announcements, one for each state change in the doorbell.

- id: '1640995128073' alias: G4 Doorbell Announcement with Alexa description: G4 Doorbell Announcement with Alexa trigger: - platform: state entity\_id: binary\_sensor.front\_door\_doorbell to: 'on' condition: [] action: - service: notify.alexa\_media\_everywhere data: data: type: announce method: speak message: Someone is at the front door mode: single

It works! There's a ton of cool stuff I can automate now!


Sponsor: Make login Auth0’s problem. Not yours. Provide the convenient login features your customers want, like social login, multi-factor authentication, single sign-on, passwordless, and more. Get started for free.


© 2021 Scott Hanselman. All rights reserved.

View Details

I was reading Gabby's blog post about the new TypeScript/JavaScript project experience in Visual Studio 2022. You should read the docs on JavaScript and TypeScript in Visual Studio 2022.

If you're used to ASP.NET apps when you think about apps that are JavaScript heavy, "front end apps" or TypeScript focused, it can be confusing as to "where does .NET fit in?"

You need to consider the responsibilities of your various projects or subsystems and the multiple totally valid ways you can build a web site or web app. Let's consider just a few:

  1. An ASP.NET Web app that renders HTML on the server but uses TS/JS
    • This may have a Web API, Razor Pages, with or without the MVC pattern.
    • You maybe have just added JavaScript via

      ```

      Ok, this makes sense as we know not only does HotReload support C# (code behinds) but also Markup via Razor Pages and changing CSS! It would definitely need to communicate "back home" to the runner which is either "dotnet watch" or VS2022.

      If I change the ASPNETCORE_ENVIRONMENT to "Production" (either via launch.json, launchsettings, or an environment variable like this, I can see that extra HotReload helper script isn't there:

      C:\github\wshotreloadtest>dotnet run --environment="Production" Building... info: Microsoft.Hosting.Lifetime[14] Now listening on: https://localhost:7216 info: Microsoft.Hosting.Lifetime[14] Now listening on: http://localhost:5216

      Remember: You never want to use dotnet run in production! It's an SDK building command! You'll want to use dotnet exec your.dll, dotnet your.dll, or best of all, in .NET 6 just call the EXE directly! .\bin\Debug\net6.0\wshotreloadtest.exe in my example. Why? dotnet run will always assume it's in Development (you literally tell it to restore, build, and exec in one run command) if you run it. You'll note that running the actual EXE is always WAY faster as well! Don't ship your .NET SDK to your webserver and don't recompile the whole thing on startup in production!

      We can see that that aspnnetcore-browser-refresh.js is the client side of Development-time HotReload. Looking at our browser console we see :

      Refused to connect to 'wss://localhost:62486/' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.

      That's a lot to think about. I started out my ASP.NET Web App's middle ware saying it was OK to talk "back to myself" but nowhere else.

      app.UseCsp(options => options.DefaultSources(s => s.Self()));

      Hm, self seems reasonable, why can't the browser connect BACK to the dotnet run'ed Kestrel Web Server? It's all localhost, right? Well, specifically it's http://localhost not ws://localhost, or even wss://localhost (that extra s is for secure) so I need to explicitly allow ws: or wss: or both, but only in Development.

      Maybe like this (again, I'm using NWebSpec, but these are just HTTP Headers so you can literally just add them if you want, hardcoded.)

      ``` app.UseCsp(options => options.DefaultSources(s => s.Self())
      .ConnectSources(s => s.CustomSources("wss://localhost:62895")));

      ```

      But port numbers change, right? Let's do just wss:, only in Development. Now, if I'm using both CSPs and WebSockets (ws:, wss:) in Production, I'll need to be intentional about this.

      What's the moral?

      If you start using CSP Headers to tighten things up, be conscious and aware of the headers you need for conveniences like Hot Reload in Development versus whatever things you may need in Production.

      Hope this helps save you some time!


      Sponsor: At Rocket Mortgage® the work you do around here will be 100% impactful but won’t take all your free time, giving you the perfect work-life balance. Or as we call it, tech/life balance! Learn more.


      © 2021 Scott Hanselman. All rights reserved.

View Details

.NET 6 is released and it's a LTS release which means it'll be fully and actively supported for the next 3 years. If you've been paused waiting for the right time to upgrade to .NET 6, it's a good time to make the move!

The .NET Upgrade Assistant can take Windows Forms, WPF, ASP.NET MVC, Console Apps, and Libraries and help you - interactively - upgrade them to .NET 6.

Why bother?

  • Massive and ongoing performance improvements
  • No need to count on .NET being on the user's machine. You can ship you own version of .NET and embed it inside your EXE! Check out Single File Deployment.
  • Tons of new C# 10 features, but they are optional, so your existing code works great but you can also "refactor via subtraction" and check out things like implicit usings.
  • Optional Profile-guided optimization (PGO) is where the JIT compiler generates optimized code in terms of the types and code paths that are most frequently used. This can mean even MORE free performance!
  • Crossgen2 can dramatically improve your startup time
  • Support for macOS Arm64 (or "Apple M1 Silicon") and Windows Arm64 operating systems, for both native Arm64 execution and x64 emulation. In addition, the x64 and Arm64 .NET installers now install side by side. For more info, see .NET Support for macOS 11 and Windows 11 for Arm64 and x64.
  • Hot Reload - just make changes and your app changes...even if you're coding in Notepad!
  • And tons more!

Check out my .NET Conf 2022 video where I see how many places I can run .NET! Windows, Linux, Docker, Mac, Raspberry Pi, even a Remarkable 2 eInk tablet. Enjoy!

Be sure to watch and enjoy ALL the great .NET Conf 2022 videos up on YouTube today.


Sponsor: Lob’s developer-friendly APIs make it easy to send a letter, check, or postcard, as easily as email. Design dynamic HTML templates to personalize mail for maximum impact. Start Exploring with Postman!


© 2021 Scott Hanselman. All rights reserved.

View Details

.NET 6 is released and it's a LTS release which means it'll be fully and actively supported for the next 3 years. If you've been paused waiting for the right time to upgrade to .NET 6, it's a good time to make the move!

Right now, Hanselman.com and Hanselminutes.com (my podcast) are running on some version of .NET 5. You can se by visiting them and scrolling to the very bottom in the footer as I've added a git commit hash and Azure DevOps Build Number and Build ID to an ASP.NET website and I'm using RuntimeInformation.FrameworkDescription to output the plain text version of .NET I'm using. This blog is on .NET Core 3.0 which is an LTS release but I'll be working with Mark Downie this week to move it to .NET 6 LTS as he's already got his instance of dasBlog running on 6!

OK, let's see what's involved. Let's start with my podcast site. I've got the code on GitHub and running locally with "dotnet run" on the command line in both Linux and Windows. I can run the "dotnet upgrade assistant" which is great, but I also like to drive stick shift sometimes for smaller projects.

I'll update my TargetFramework in my csproj project file from net5.0 to net6.0 and update the major PackageReferences from 5.0.0 to 6.0.0. It compiles.

Optionally, I'll also run "dotnet outdated" which is one of my favorite tools. You'll want to make sure you have a solid test suite and not just do this without testing.

I see that some of these are major changes so I can do a diff of these packages with a number of tools, but my favorite is FuGet.org (Thanks Frank!) so I can do a diff between the alpha version of Selenium I'm using and the released see that the RemoteLogs type is now called Logs.

I will also update my Dockerfile and change versions like this

FROM mcr.microsoft.com/dotnet/sdk:6.0 as build

and

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS runtime

I'll confirm that these images build and test. I also run my tests optionally inside a container so that's nice.

Some of my sites use Azure DevOps and others use GitHub Actions. Both use YAML (yay) to manage their config, so I'll update my UseDotNet task in Azure DevOps YAML to version: "6.0.x"

I'll commit and start building in the cloud!

``` Changes to be committed:
(use "git restore --staged ..." to unstage)
modified: Dockerfile
modified: azure-pipelines.yml
modified: hanselminutes.core.tests/SeleniumTests.cs
modified: hanselminutes.core.tests/hanselminutes.core.tests.csproj
modified: hanselminutes.core/Startup.cs
modified: hanselminutes.core/hanselminutes-core.csproj

$ git commit -m "upgrade to .net 6" ```

I will also confirm that my Azure App Service is set to .NET 6, but this is only needed if I'm NOT running in a Docker Container or if I'm NOT using a self-contained executable.

Now I repeat this for my podcast and main site and I'm now on .NET 6! The blog (a larger upgrade) is next.


Sponsor: Lob’s developer-friendly APIs make it easy to send a letter, check, or postcard, as easily as email. Design dynamic HTML templates to personalize mail for maximum impact. Start Exploring with Postman!


© 2021 Scott Hanselman. All rights reserved.

View Details

My PowerShell upgraded to the new PowerShell 7.2.0 and it happened automatically since I get PowerShell from the Windows Store. However, my fancy prompt use PSReadLine with Predictive Autocomplete stopped working suddenly.

However, suddenly I started getting this error on every prompt.

Could not load type 'System.Management.Automation.Subsystem.PredictionResult' from assembly 'Microsoft.PowerShell.PSReadLine.Polyfiller, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. at Microsoft.PowerShell.PSConsoleReadLine.PredictionViewBase.Reset() at Microsoft.PowerShell.PSConsoleReadLine.PredictionInlineView.Reset() at Microsoft.PowerShell.PSConsoleReadLine.Prediction.Reset() at Microsoft.PowerShell.PSConsoleReadLine.Initialize(Runspace runspace, EngineIntrinsics engineIntrinsics) at Microsoft.PowerShell.PSConsoleReadLine.ReadLine(Runspace runspace, EngineIntrinsics engineIntrinsics, CancellationToken cancellationToken)

Well, you can see I'm using a Beta of PSReadLine 2.2:

```

Environment

PSReadLine: 2.2.0-beta2
PowerShell: 7.2.0 ```

But I have failed to keep it up to date, and when I got into this state, I realized just because my prompt wasn't pretty (momentarily) I could update it with one line while still staying on the Beta Train.

Install-Module PSReadLine -AllowPrerelease -Force

Now I'm on 2.2.0-beta4 and all is well and I have my cool prediction history back!


Sponsor: Couchbase Capella DBaaS is flexible, full-featured and fully managed with built-in access via K/V, SQL and full text search. It’s blazing fast, yet surprisingly affordable. Try Capella today for free.


© 2021 Scott Hanselman. All rights reserved.

View Details

If you're on a version of Windows 11 that is build 22000 or greater, you can now use WSL to mount Linux disks directly. Run winver to see your Windows version. I'm on 22000.282 as of the time of this writing.

I can also run wsl --help and see the --mount instructions. If you don't have them, you're not on the latest, or you can try installing/update WSL from the Windows Store. Installing WSL from the Windows Store gets you updates faster.

``` --mount
Attaches and mounts a physical disk in all WSL2 distributions.
Options:
--bare
Attach the disk to WSL2, but don't mount it.

--type <Type>  
    Filesystem to use when mounting a disk, if not specified defaults to ext4.

--options <Options>  
    Additional mount options.

--partition <Index>  
    Index of the partition to mount, if not specified defaults to the whole disk.

--unmount [Disk]
Unmounts and detaches a disk from all WSL2 distributions.
Unmounts and detaches all disks if called without argument. ```

You'll need to be an admin to mount a disk. You can first get a list of all the disks using this PowerShell query:

``` GET-CimInstance -query "SELECT * from Win32_DiskDrive"

```

The DeviceID is a path like \.\SOMETHING and that's what matters.

Then you just wsl --mount \\.\SOMETHING".

The device will appear under /mnt/wsl/SOMETHING in your Linux instance. You can mount unpartitioned disks like this, or you can mount partitioned disks. Then you can run lsblk and see the partitions and they'll be under /dev/. Once you know the partition number you can go back and wsl --mount --\\.\SOMETHING --partition --type Filesystem. The filesystem parameter is for things like vfat, etc for filesystems that have kernel support.

Today SD Cards and Flash Drives aren't working, but USB externals work and internal drives work, as well as VHDs.


Sponsor: Couchbase Capella DBaaS is flexible, full-featured and fully managed with built-in access via K/V, SQL and full text search. It’s blazing fast, yet surprisingly affordable. Try Capella today for free.


© 2021 Scott Hanselman. All rights reserved.

View Details

I've blogged before on how to easily move WSL distributions between Windows 10 machines with import and export. I recently did a full fresh install of Windows 11 and wanted to bring my existing highly customized Ubuntu installation along with me.

You can tar up (zip up) the user-mode parts of your WSL2 distributions like this:

wsl --export Ubuntu-20.04 c:\Temp\UbuntuBackup.tar

The part after --export is the distribution name that you can see from running wsl --list -v. The last argument is a full path and filename for the archive you want created.

Next, on the machine you've moved to, you'll do the reverse. Notice that I've changed the Distro name here, and you can if you want. Remember also that you can have as many Linux Distros installed as you want.

wsl --import Ubuntu c:\Linux c:\Temp\UbuntuBackup.tar

The Linux file system is stored in a VHDX (virtual hard drive), usually deep in AppData/Local/YadaYada, but this import is an opportunity for me to store it in C:\Linux which will also make it easier to do maintenance on like Compact-VHD which shrinks your WSL2 disks.

Here's the weird part. When you import a WSL2 distro manually, running that distro on the new machine will end up logging you in as root. It's forgotten that I'm "scott."

There's a lot of ways to fix this that involve the registry or passing in arguments to wsl, but I just want it to work when I run "wsl" or "wsl -d distroname."

Run your distro, and then edit /etc/wsl.conf and add a [user] section like this:

[user] default=scott

This is the ideal way to set your WSL distro's default user for imported tars because it's stored inside the Linux file system and the setting will stick around when you export/import later on.

Hope this helps!


Sponsor: Lob APIs ensure your addresses are deliverable and everything you send arrives at the right place. Add address autocompletion and verification in minutes using React, Vue or Javascript - Try for free!


© 2021 Scott Hanselman. All rights reserved.