Skip to content

remove literal PW #5016

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 2, 2025
Merged

remove literal PW #5016

merged 7 commits into from
May 2, 2025

Conversation

Rick-Anderson
Copy link
Contributor

No description provided.

@@ -262,7 +262,7 @@ dotnet ef dbcontext scaffold Name=ConnectionStrings:Blogging Microsoft.EntityFra
The following example skips scaffolding an `OnConfiguring` method. This can be useful when you want to configure the DbContext outside of the class. For example, ASP.NET Core apps typically configure it in Startup.ConfigureServices.

```dotnetcli
dotnet ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=Blogging;User Id=myUsername;Password=myPassword;" Microsoft.EntityFrameworkCore.SqlServer --no-onconfiguring
dotnet ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=Blogging;User Id=myUsername;Password=--;" Microsoft.EntityFrameworkCore.SqlServer --no-onconfiguring
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that still a legal pw?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh, I'm not sure - but it's the same password you had before: you had Password=-- and then an additional ;pw which wasn't part of the password, since ; is the connection string delimiter. And since pw isn't a valid option, the connection string was invalid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh, I'm not sure - but it's the same password you had before: you had Password=-- and then an additional ;pw which wasn't part of the password, since ; is the connection string delimiter. And since pw isn't a valid option, the connection string was invalid.

that was my intention.

I should have added:

In the preceding code, replace --;pw; with a valid password.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See below - I agree with @cincuranet, why not just use *** as the placeholder?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If *** is a valid password you can't use it. You have to use something that can never be valid, even better if it throws exceptions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If *** is a valid password you can't use it. You have to use something that can never be valid, even better if it throws exceptions

Sorry @blowdart, I see you resolved the issue.

@Rick-Anderson Rick-Anderson requested a review from roji April 28, 2025 17:27
dotnet ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=Blogging;User Id=myUsername;Password=myPassword;" Microsoft.EntityFrameworkCore.SqlServer --no-onconfiguring
dotnet ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=Blogging;User Id=myUsername;Password=\0;" Microsoft.EntityFrameworkCore.SqlServer --no-onconfiguring

In the preceding code, replace `\0` with a valid strong password.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's probably still a valid password. How about I use ;|; or ;A; and tell them to replace ;A with a ...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not simply ***?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not simply ***?

Because that's a valid PW and can be copy/pasted. And customer copy/paste.

Comment on lines 265 to 267
dotnet ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=Blogging;User Id=myUsername;Password=***" Microsoft.EntityFrameworkCore.SqlServer --no-onconfiguring

In the preceding code, replace `***` with a valid strong password, followed by a semicolon `;`, for example, `password=<A strong password>;`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least this makes them do a copy/paste/copy `password=;/edit

***; by itself is a valid password and can be copy/pasted - right? If not, I'll revert to ***;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rick-Anderson yes, *** can be a valid password. So can the string \0.

Having something like ...;User Id=myUsername;Password=;A; doesn't mean that there's an invalid password ;A;. Since semicolon is the separator for connection string, this means there's an empty password (which in theory might also be valid? I'm not sure), and then an invalid connection string option A (which will make the connection fail).

I'm not sure what exactly is the idea here... Yes, documentation placeholders for password are generally legal passwords - that seems quite standard; what exactly is the problem with using *** as a placeholder?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rick-Anderson yes, *** can be a valid password. So can the string \0.

Having something like ...;User Id=myUsername;Password=;A; doesn't mean that there's an invalid password ;A;. Since semicolon is the separator for connection string, this means there's an empty password (which in theory might also be valid? I'm not sure), and then an invalid connection string option A (which will make the connection fail).

Perfect, that's what we want. Copy/paste fail.

I'm not sure what exactly is the idea here... Yes, documentation placeholders for password are generally legal passwords - that seems quite standard; what exactly is the problem with using *** as a placeholder?

Right, and smoking was standard 50 years ago, even among MD. Lots of bad security practices were use in the past. The SFI mantra is remove insecure practices.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, that's what we want. Copy/paste fail.

I disagree. You're saying our doc samples should show a connection string that's invalid, in a way that has nothing to do with the password, by adding an arbitrary invalid A option just to make the connection string fail. That just seems wrong.

Right, and smoking was standard 50 years ago, even among MD. Lots of bad security practices were use in the past. The SFI mantra is remove insecure practices.

What exact problem are you trying to solve? How exactly is having *** as a password placeholder in our docs insecure? Is there some guideline you can point to that says we need to do this?

@Rick-Anderson Rick-Anderson requested a review from cincuranet May 1, 2025 02:26
@SamMonoRT
Copy link
Member

According to documentation, the guidance is to use Placeholder or _placeholder (both case-insensitive)

@Rick-Anderson
Copy link
Contributor Author

Rick-Anderson commented May 1, 2025

According to documentation, the guidance is to use Placeholder or _placeholder (both case-insensitive)

What guidance? Placeholder or _placeholder are both valid passwords, and the goal is to prevent copy/paste/use.
5 years ago we used $Credential_Placeholder$, but that's a valid password.

@Rick-Anderson
Copy link
Contributor Author

Rick-Anderson commented May 1, 2025

@blowdart can you resolve this SFI difference? My understanding is to remove code/markup containing a valid password that can be copy/pasted/used. In this case Password=myPassword

EDIT: @blowdart resolved the issue

If *** is a valid password you can't use it. You have to use something that can never be valid, even better if it throws exceptions

@SamMonoRT
Copy link
Member

According to documentation, the guidance is to use Placeholder or _placeholder (both case-insensitive)

What guidance? Placeholder or _placeholder are both valid passwords, and the goal is to prevent copy/paste/use. 5 years ago we used $Credential_Placeholder$, but that's a valid password.

Send you link to documentation on IM and also why is the goal to prevent copy/paste/use - is this some rule we can get a link to and send to rest of the .NET teams?

@roji
Copy link
Member

roji commented May 1, 2025

According to documentation, the guidance is to use Placeholder or _placeholder (both case-insensitive)

What guidance? Placeholder or _placeholder are both valid passwords, and the goal is to prevent copy/paste/use.
5 years ago we used $Credential_Placeholder$, but that's a valid password.

So what if a documented placeholder could be a valid password? What exactly is the security risk here?

@Rick-Anderson
Copy link
Contributor Author

So what if a documented placeholder could be a valid password? What exactly is the security risk here?

As I've mentioned numerous times, customer copy/paste code. The PW we use is at the top of the password dictionary. I'll send you a SFI link soon. We know customers copy/paste and use.

@roji
Copy link
Member

roji commented May 1, 2025

As I've mentioned numerous times, customer copy/paste code. The PW we use is at the top of the password dictionary. I'll send you a SFI link soon. We know customers copy/paste and use.

I'm not following - so what if a customer copy-pastes the code and ends up with ***** as the password in their connection string? How is that a security issue?

@Rick-Anderson
Copy link
Contributor Author

Rick-Anderson commented May 1, 2025

As I've mentioned numerous times, customer copy/paste code. The PW we use is at the top of the password dictionary. I'll send you a SFI link soon. We know customers copy/paste and use.

I'm not following - so what if a customer copy-pastes the code and ends up with ***** as the password in their connection string? How is that a security issue?

@blowdart hopefully will correct me if I'm wrong. The SFI policy is to never use a valid password in documentation, even it can't be a security issue because it's localdb or what not. Customer can migrate that code to a server and use the same password. Here's what the LLM's say:

If your local DB later moves to Azure SQL or AWS RDS using the same password, and a malicious actor already has that password, they can scan IP ranges or phish for connection info and try to connect.

Why is there a PW on the DB if it's not needed for security?

All I know is this is a SFI rule, so I'll bow out now if you need further convincing.

@roji
Copy link
Member

roji commented May 2, 2025

The SFI policy is to never use a valid password in documentation, even it can't be a security issue because it's localdb or what not. Customer can migrate that code to a server and use the same password.

Is there some resource/policy document I could see to understand this better?

I may be dense, but I simply don't see the issue here - regardless of localdb. Hopefully @blowdart can shed some light on this.

If users copy-paste the connection string from the documentation as-is, then in 99.99999% of cases their program will now fail, since the actual password in their actual database is different. Regardless of password, the program will also fail because other components in the connection string (hostname, database name) are incorrect as well).

For the extremely, extremely contrived case where the actual password in the actual database happens to be the same as the documented placeholder (i.e. the user set their actual password to *****), if the user copy-pastes they now end up in the same state as if they manually corrected the incorrect connection string to include their real password. So there doesn't seem to be a security issue here either.

So once again, I'm looking to understand what actual security concerns are being addressed here.

BTW I'm not sure how the guidline to never use a potentially valid password in documentation could work. In the database cases there's a connection string which we can indeed intentionally foul up, but in many/most APIs the password is a standalone field which can be any valid string. How does one never show a valid password if all strings are valid?

@ErikEJ
Copy link
Contributor

ErikEJ commented May 2, 2025

Since localdb is Windows only, why not just use:

dotnet ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=Blogging;Integrated Security=true;" Microsoft.EntityFrameworkCore.SqlServer --no-onconfiguring

@roji
Copy link
Member

roji commented May 2, 2025

@ErikEJ that might make sense in this specific sample, but we probably have other cases where we have placeholders and I'd like to fully understand this.

@Rick-Anderson
Copy link
Contributor Author

How does one never show a valid password if all strings are valid?

Where is the null string a valid for a pw? Typically you can add characters to throw an exception, return an error, etc as in this pr with the ;;

@Rick-Anderson
Copy link
Contributor Author

Since localdb is Windows only, why not just use:

dotnet ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=Blogging;Integrated Security=true;" Microsoft.EntityFrameworkCore.SqlServer --no-onconfiguring

I was wonder the same. I removed the password, I think that's better than

dotnet ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=Blogging;User Id=myUsername;Password=;;;" Microsoft.EntityFrameworkCore.SqlServer --no-onconfiguring

In the preceding code, replace Password=;;; with a valid strong password, followed by a semicolon ;, for example, password=<A strong password>;

@roji
Copy link
Member

roji commented May 2, 2025

Where is the null string a valid for a pw? Typically you can add characters to throw an exception, return an error, etc as in this pr with the ;;

But that's the point - in most cases all characters are valid; semicolon is only invalid in this case because the password is embedded inside a large connection string. And as I've been trying to argue above, showing a mangled connection string doesn't seem to be in our users' interest.

I guess null would work in other contexts, though that seems to be a "wrong" code sample in a similar way as the mangled connection string - showing wrong code that inherently fails doesn't make sense to me.

I'm still waiting to understand the actual sense behind all of this.

@Rick-Anderson
Copy link
Contributor Author

But that's the point - in most cases all characters are valid

On what frameworks is the null PW valid? I generally use illegal characters < >, / to force errors in copy/paste. See this PR.

Your assertion is that customers will view the connection string and replace myPassword in Password=myPassword; with their own strong PW. The following instructions requires the PW to change to, adding very little friction

dotnet ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=Blogging;User Id=myUsername;Password=;;;" Microsoft.EntityFrameworkCore.SqlServer --no-onconfiguring

In the preceding code, replace Password=;;; with a valid strong password, followed by a semicolon ;, for example, password=<A strong password>;

That shows them how to construct a con str without risking copy/paste/use.

showing a mangled connection string doesn't seem to be in our users' interest.

But showing a valid connection string that leads some uses to the pit of insecurity is far more problematic to our users' interests.

Fortunately this has been decided many levels above us, so there is nothing to debate.

@Rick-Anderson
Copy link
Contributor Author

@roji can you approve/merge the PR? This is part of my SFI commitment. We can continue the discussion offline.

Copy link
Member

@roji roji left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally prefer to understand changes I'm asked to do, which is why I'm pushing here.

But the change as it is now is indeed much better than a mangled connection string - we're "lucky" that we're showing localdb on Windows etc. I'm approving and will merge.

@roji roji merged commit 39879a7 into main May 2, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants