Enhance Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle package to define a custom bundle format
danroth27 opened this issue Β· 114 comments
We've built Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle as an experimental way to alter the packaging of Blazor WebAssembly apps so they work in environments that block the download of DLLs. We should consider if we want to release a stable and supported version of this package. Before we do so, we should verify that this packaging strategy is successful in these restrictive environments.
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.
I think there are a lot of people who would like to develop applications in Blazor. At the same time many of them do not know that Blazor application can be blocked by a firewall and this can be an unpleasant surprise for them. In my opinion a solution like MultipartBoundle have to be supported by ASP.NET team and included in default Blazor templates.
@Andrzej-W Have you tried out the experimental multipart bundle functionality and does it enable Blazor WebAssembly app execution in environments were you were previously blocked?
Unfortunately my Blazor app is not ready yet, it is not published and I don't have personal experience with firewalls blocking Blazor app. The app is intended for a wide audience and I must do my best to make it accessible to everyone. I hope MultipartBoundle will be an effective solution to the firewall/antivirus problem.
Perhaps you should add to the JavaScript code responsible for loading this bundle the ability to signal problems by calling the configured URL. It would be useful for monitoring the scale of the problem. It is always possible that the proposed solution will work now and after a few days/weeks/months firewall vendors will discover it and the problem suddenly returns. This function should also be able to show an error message to the user, something similar to already available "blazor-error-ui", but of course it should be a different <div>
with different message.
I did take a look at the approuch suggested in the blog post recently published and it seams rather complex. I believe a feature like this should be enabled by a matter of adding a nuget package to the project and adding a value to the csproject file to tell the build process to do the needful.
@smartprogrammer93 I agree. I would like to do prototypes of offloading certain calculations to the client of our services by using WASM (combined with existing JS front-end code). Using .NET WASM is already something that makes front-end developers worried, and stuff like this just makes it impossible to even consider.
I did take a look at the approuch suggested in the blog post recently published and it seams rather complex. I believe a feature like this should be enabled by a matter of adding a nuget package to the project and adding a value to the csproject file to tell the build process to do the needful.
I totally agree. A default way to make the applications work in all scenarios is a must.
If the applications generated in Blazor can be blocked by a proxy in a number of scenarios, then it should be implemented by default when built in Release by adding a checkbox in VS for the project.
Also, there is the issue of static web sites, in where there is no code running in the server, so the build should already do everything that is required to create the files in the final form.
What about AOT compilation? Does this process generate wasm files of the libraries that would not be blocked?
If MS had built Office Web running in Blazor webassembly, all this would be already up and running from day 1 because otherwise it would be blocked in most companies. Maybe you could work with one of the MS Teams and build something enterprise inhouse. That would give you a better understanding or the real issues not only during deploying but also bugs in the pre-release versions. Inhouse collaboration would allow you to have access to the source code also and debug issues early.
@smartprogrammer93 @petertiedemann @rmencia-isv Are any of you currently operating apps in environments where the download of Blazor WebAssembly apps is currently blocked? If yes, could you please try out the Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle package and let us know if it enables Blazor WebAssembly deployment in those problematic environments? Before we make a feature like this as part of the framework, we want to collect data from customers on whether it actually solves the problem.
I think question was to @petertiedemann (but yes, I work for a company where topics here can apply as valid scenario)
@rmarinho We agree that this issue of Blazor WebAssembly apps getting blocked in certain environments is concerning, which is why we're exploring alternative packaging approaches. Please note though that it's not all environments that have this problem - it's specifically environments that block the download of DLLs. Many deployments of Blazor WebAssembly never hit this issue.
The request here is for folks that are deploying to these more restrictive environments to try out the Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle package and let us know if this alternative packaging strategy enables Blazor WebAssembly usage.
@danroth27 Our own network is not restricted in such a way, but we are a software company developing software for large industrial enterprises, and I would not be surprised to see them doing this kind of blocking.
@petertiedemann Makes sense. We should have enough extensibility in place now that it should be possible to customize packaging to work for specific environments. Whether we can provide a generic solution that will work in all environments is what we're investigating with the multipart bundle package.
Please don't forget about static Blazor web sites when you think about that solution.
@danroth27 are you able to give more details about what βSome environments blockβ¦β means in terms of how wide the problem is and what those environments are likely to be (ie is it Enterprise only, Government and Defence etc)?
Also how would you know if you did hit this - is there a specific error code?
Hi @JohnGoldsmith. We've seen users report that some firewalls are setup to block the download of all Windows PE files. The files simply fail to get downloaded. We think this is only impact a small subset of users, not the majority, but enough users reported it that we are exploring ways to address the problem. Sometimes users can work with their IT departments to remove the restriction for their apps. When this isn't feasible, users can repackage the app with different files name extensions, which we provide instructions on how to do. In other cases the inspection of the files is deeper, so we added extensibility in .NET 6 to enable further customization of the app packaging. These extensibility points give users the flexibility to adapt to the requirements of specific environments. We're also exploring multipart bundling as a generic solution, and we're looking for verification from users that are currently blocked that this approach works for them.
@danroth27 that's good to know -thank you very much for the detailed explanation. It's also good to know that there's a way out if it does raises it's head (for me).
Thanks again.
This may be a dumb question but why are the .dlls from blazor apps not being turned into .wasm files?
@CoryKoehler They are. But the DLLs are still needed currently for certain code paths and for their metadata.
@danroth27 , willl this solution work for Static Blazor web app ? where there is no server to handle app.bundle
Hi @danleydmello. I believe this solution works for static sites as long as the site host gives you a way to setup the mime type mapping for the custom .bundle extension. For example, I think Azure Static Web Apps lets you do this. GitHub Page I think doesn't.
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.
Hi @danroth27 . First of all thank you for the proposed solution, it's really very important question. I have few things to consider.
I'm developing a new module for Cockpit (Admin UI for servers). My module is a Blazor Wasm App that is hosted as a set of static files by the internal Cockpit Web Server (Cockpit modules must be client-side apps). Unfortunately I can't add required HTTP headers, because it's not supported by Cockpit.
I could ask Cockpit Developers to add required HTTP Header for *.bundle
files globally into the main Cockpit Project, but I predict various reasons why they might decide to reject these changes:
- Current Mime-Type (
multipart/form-data; boundary="--0a7e8441d64b4bf89086b85e59523b7d"
) looks uncommon for resource files, especially with static ID inboundary
field. It would be better to find a solution that works with some common Mime-Type (likeapplication/octet-stream
). .bundle
file extension is quite abstract. It would be easier to register proposed Mime-Type in Cockpit for more concrete file extension (like.netpack
or.blazor
). In case if it would be possible to change Mime-Type tooctet-stream
some well-known extension like.bin
might also be better.
There are few other things that I'd like to mention:
- Bundling gives huge speed gain for the initial loading under Cockpit (up to 12x on a very fast PC with the app running from localhost). With
app.bundle
file the boot time is under 3 seconds, while with.dll
files there are horrible 35 seconds. I used compression in both cases. So bundling makes a big sense in terms of performance and it's a must have for my App. - I had to add additional CORS for proposed bundling method in order to work under Cockpit (
default-src 'self' ... data: blob:; script-src-elem 'self' ... 'unsafe-inline' data: blob:; connect-src 'self' ... blob:
). It's not a blocker for me, because CORS are configurable in Cockpit, but it's better to avoid that (it's not required to configure such CORS for .DLL files approach). - May be you could consider adding required Mime-Type for GitHub Pages globally. It would allow people to host static Blazor Wasm Apps in GitHub. It would also allow me to tell Cockpit Developers that this Mime-Type has already been added for GitHub Pages, so they could do the same.
- WebAssembly deployment layout manual proposes to consider using AOT compilation in order to exclude DLL files. Am I correct that it's currently an outdated info? Should I add a new issue regarding that?
Thank you once again for your work. Hope that my questions can be solved somehow.
I have put this into my wasm app and deployed it and google ads and other security / vpns are still flagging our blazor wasm.
I see this is being pushed back to .net 7 and this is something that we cannot wait a year on.
I have also tried AOT and other solutions that are outlined in the web assembly deployment layout manual documentation
I would really like to use the Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle package, because my company blocks dlls, so we cannot see Blazor WASM applications. However, after installing the Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle NuGet package I get this Error when I Publish:
Could not copy "C:\Users....nuget\packages\microsoft.aspnetcore.components.webassembly.multipartbundle\0.1.0-alpha.21470.2\staticwebassets\Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.lib.module.js" to "C:...\Client\obj\Release\net6.0\browser-wasm\PubTmp\Out\wwwroot_content\Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle\Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.lib.module.js". Exceeded retry count of 10. Failed.
Any idea what is wrong?
@CoryKoehler They are. But the DLLs are still needed currently for certain code paths and for their metadata.
@danroth27 according to the Deployment Layout documentation an "Alternative[] to consider include" is:
Use Ahead-of-time (AOT) compilation and deployment, which produces a compiled WebAssembly app that doesn't require downloading DLLs to clients.
Is this incorrect?
Maybe I'm being super naive here, but couldn't the DLLs be embedded in a base64-encoded string in a .JS file that .JS then decodes and feeds to Mono? Let their firewalls see through that.
Oh and obfuscate it too while you're at it. A simple XOR cipher should do the trick.
Update: Ok yeah, I'm trying out this package and looking at the app.bundle, and I don't think this is going to fool any firewall. It announces its Mime type as application/octet-stream (redflag) and then is immediately followed by the famous MZ.
I'll try it out with one of my clients who's the most paranoid completely justifiably conservative type you'll ever meet when it comes to this stuff, and let you know. But assuming it doesn't work I'll try out the customizations like embedding in a JS file and obfuscation. We've come too far to let this be a blocker.
Update 2: Oddly enough, my client's system is NOT blocking Blazor apps. I'll have to see if I can find another client who is. Will certainly let you guys know if I do and how it goes.
@danroth27 according to the Deployment Layout documentation an "Alternative[] to consider include" is:
Use Ahead-of-time (AOT) compilation and deployment, which produces a compiled WebAssembly app that doesn't require downloading DLLs to clients.
Is this incorrect?
Whoops! No, that's wrong. Even when you AOT compile, the assemblies are still needed for their metadata and other reasons. I'll get the doc corrected. Thanks for bringing this to my attention! It's a common point of confusion. @guardrex FYI.
Doc update complete, including the additional lead-in text changes, and will go live within 24 hours.
I noticed that Bitdefender now blocks .NET 6.0 blazor wasm apps but not .NET 5.0.
Maybe that is something that can be communicated with Bitdefender ?
I noticed that Bitdefender now blocks .NET 6.0 blazor wasm apps but not .NET 5.0. Maybe that is something that can be communicated with Bitdefender ?
Does it still block it when using the MultipartBundle package?
Haven't tested it yet. I will try it and report here the results
UPDATE: The multipartbundle package is still getting blocked
This needs to be taken more seriously and with more urgency. It also affects google ads and any site getting flagged is a huge mess. Also the user trust goes out the window the moment they see a site blocked by their antivirus.
This a serious matter that should be resolved out-of-the-box asap, not in a year or two.
What is the exact security product / edition you're testing this with? I'd like to try it and see exactly what happens.
As I said, and no offense intended, but I don't understand why anyone on this team thought that simple multipart bundling was going to change anything from a security perspective. The files need to be made to look like JavaScript or something else these systems have been trained to allow. "application/octet-stream" is basically announcing you're something dangerous - which of course Blazor ISN'T because it's as safe as JavaScript.
I have created a nuget package to try and circumvent false positives from antiviruses. More info on the project's page:
https://github.com/stavroskasidis/BlazorWasmAntivirusProtection
Please give it a try to see if it helps.
I have created a nuget package to try and circumvent false positives from antiviruses. More info on the project's page: https://github.com/stavroskasidis/BlazorWasmAntivirusProtection
Please give it a try to see if it helps.
Thank you for posting this. What exact antivirus products are you testing against? More importantly which ones block Blazor normally? You mentioned Bitdefender but they have half a dozen products and I want to make sure I get the right edition to test with.
I have created a nuget package to try and circumvent false positives from antiviruses. More info on the project's page: https://github.com/stavroskasidis/BlazorWasmAntivirusProtection
Please give it a try to see if it helps.Thank you for posting this. What exact antivirus products are you testing against? More importantly which ones block Blazor normally? You mentioned Bitdefender but they have half a dozen products and I want to make sure I get the right edition to test with.
I can confirm that the following are blocking blazor wasm 6.0. You can test it easily with sites like mudblazor.com
Thank you! This is extremely helpful. I will download trial versions of these products and test with my live dev site and also try your solution. We will figure this out.
Re my duplicate issue #40319. We have a customer whose GData Internet Security flags up files written to the cache as Trojans. Neither bundling or the package provided by @stavroskasidis fix this.
This is our second customer who has hit this, with two different Antivirus providers. I'm with @stavroskasidis and @legistek; this needs to be addressed as a dire emergency. .Net 7 is too far away. Blazor Wasm is not fit for purpose for developing enterprise software if it is blocked by AV and firewalls.
We've been able to work around the GData caching issue by turning off Blazor caching, as per the docs.
We've been able to work around the GData caching issue by turning off Blazor caching, as per the docs.
Is that mean dlls will be downloaded everytime by the browser?
@danleydmello I expect so, yes
@danleydmello I expect so, yes
I think this whole problem is way bigger than most people think.
I am a developer from Austria, developing a B2B application with blazor since the release of .NET5.
From my experience with (Austrian) customers, i can confidentially say, that every 4th or 5th customer is experiencing this issue.
I dont know if IT-staff is not updating their firewalls or if they just use very restrictive systems, but this is definitly not a problem where we can say we wait until every firewall adapts blazor. That will just not happen.
We can luckily handle the problem very well because it is a pure B2B application, so we can tell each customer individually to whitelist our application in their firewall.
Next week i would like to start developing our corporate website using blazor, but i think i will instead go with angular or vue, because i can just not risk a lot of potential customers to skip our product because the website is not loading.
I have to say that i really fell in love with blazor, but i think this issue is really threatening the future of it...
From my experience with (Austrian) customers, i can confidentially say, that every 4th or 5th customer is experiencing this issue.
@Kruki Can you confirm you are seeing this issue even when using the multipart bundling approach? Have you also tried https://github.com/stavroskasidis/BlazorWasmAntivirusProtection? Do you have any additional details on what specific firewall software your hitting issues with and what specific check it is doing that is causing blocking issues?
I will implement these approaches with the next update!
I cannot tell specifically which systems customers are using, because we dont want them to bother to talk with us more about the error, we are glad that it works after they whitelist our software.
I will ask our support team to find out what firewall systems are used by the troubled customers next time!
I've found in the past with firewall issues and customers that it's impossible to get any information out of them as to why the system blocked it. We're lucky to get it whitelisted and usually leave it at that.
But @danroth27 it's pretty easy to see what's going on - many systems block executables wholesale. Whether they are looking for the EXE/DLL extension, "MZ", or something more sophisticated, it's impossible to know without trial and error. The only thing to do here is make it look as little like an executable as possible.
The Blazor team could implement some code in the loader that when the file doesn't load (it's blocked), it logs the problem. It' could be integrated with Azure Application Insights and the company could gather all that information and find the affected customers. That information can be shared with Blazor team and help find solutions.
Also, at MS, it wouldn't be too difficult to set up a few of the most common Antiviruses and Firewalls in a couple of VMs in Azure.
I'm sure that if you contact the AV/Firewall companies they can even give you a free license for testing purposes and try all these scenarios.
Also, encrypting the DLLs during the build should work. Then, the loader can decrypt them on loading. The key would be public, but it's not a security risk, it's only to bypass the firewalls.
Maybe it's worth thinking about compiling the whole lot of DLLs and dotnet as webassembly code and run them directly instead of using mono and bypass the whole problem.
Also, encrypting the DLLs during the build should work
Yes I agree. Or even some simple obfuscation. Bit-shifting or XOR.
Maybe it's worth thinking about compiling the whole lot of DLLs and dotnet as webassembly code and run them directly instead of using mono and bypass the whole problem.
You may be late to the party, but this has been discussed extensively. The original assemblies are still needed for reflection and other things even with AOT.
Additional information from the DLL for reflexion and other things can be generated as a separate file during compile time, and then use it when the application is loaded. Then, the calls to reflexion use the generated metadata instead of accessing any structures in the code at runtime. Everything is already pre-calculated.
I've been doing this for ages when creating my own DSLs using ANTLR. When the compiler parses the code and creates SQL, C# and additional data structures required to avoid expensive reflexion during execution. All in one go.
I'm pretty sure that the Blazor/dotnet/compiler teams have very smart people to make that thing work.
The only thing to do here is make it look as little like an executable as possible.
The experimental multipart bundle approach we provide is one attempt at doing that. The https://github.com/stavroskasidis/BlazorWasmAntivirusProtection package goes further and changes the MZ headers. For folks that are hitting issues, we need to know if these approaches have already been tried before we explore additional techniques.
we need to know if these approaches have already been tried before we explore additional techniques.
Understood, and I will say - without singling anyone out - that there seems to be more complaining going on here than actual troubleshooting. I have tried it on every system I can - law firms, financial institutions, etc. - and no one is blocking it. I wish I could find one that is. That said, I would still urge a more defensive approach here on your guys' part. In other words, I don't think you need to wait to find someone blocking it before taking more serious measures to obfuscate it, and again, no offense intended, but any system that does decide to block it is not going to be fooled by a multipart MIME type that's labelled as "application/octet-stream".
Additional information from the DLL for reflexion and other things can be generated as a separate file during compile time, and then use it when the application is loaded.
@rmencia-isv Again this has been suggested (including by me) and discussed above; I don't purport to fully understand it, but it is clear that AOT is not able to provide 100% of the functionality of the CLR and thus some things still require the assemblies. All the work on this is open source; I'm sure your experience would be valuable if you wanted to contribute.
@danroth27 We already know that Multipart Bundling doesn't work across the board. And that BlazorWasmAntivirusProtection still can't stop cached DLLs from being flagged (probably because of "application/octet-stream"). A universal, foolproof solution must be found. Sorry I don't have suggestions of my own, I'm not schooled in such things.
I wish .net stop using the PE format and introduce a new format that works across all supported platforms.
@danroth27 , I'm using Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle in my blazor wasm project.
After publish, I'm running the app in my local machine via IIS
, when I run my app, it works but I get the following error logged in console,
Failed to find a valid digest in the 'integrity' attribute for resource 'https://localhost:44354/app.bundle' with computed SHA-256 integrity 'eYN2/4BkgrEnY6XJa9qJv5aq3D7yAHV6mt0ZxvVUj3k='. The resource has been blocked.
Unknown error occurred while trying to verify integrity.
Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.lib.module.js:19 TypeError: Failed to fetch
at beforeStart (Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.lib.module.js:10:38)
at blazor.webassembly.js:1:55508
at async Promise.all (:44354/index 0)
at async Nt.importInitializersAsync (blazor.webassembly.js:1:55244)
at async blazor.webassembly.js:1:59306
at async At (blazor.webassembly.js:1:59221)
Please can you assist?
@fingers10 ... Not sure if it will help in this specialized case, but the guidance for the problem in a general case is at ...
@Kruki Can you confirm you are seeing this issue even when using the multipart bundling approach? Have you also tried https://github.com/stavroskasidis/BlazorWasmAntivirusProtection? Do you have any additional details on what specific firewall software your hitting issues with and what specific check it is doing that is causing blocking issues?
I had a case today and found out that the customer is using "Barracuda CloudGen Firewall".
I was told that their firewall (with a strict security policy configured) is just not allowing .dll sideloading at all.
Thanks @Kruki for these additional details!
their firewall (with a strict security policy configured) is just not allowing .dll sideloading at all.
Can you clarify what you mean by sideloading the DLLs? Are the DLLs blocked from being downloaded on the network? Or are they blocked in some other way?
In my experience with this in the context of our Win32 application, the firewalls block downloading entirely while other client-side software prevents installation or execution. Fortunately we don't have to worry about the latter in this case.
For me this sounds like they are blocking it right away from being downloaded.
Thanks @Kruki! And can you confirm that the app is already using the preview multipart bundling to deliver the app?
@danroth27 I cannot confirm this, because we were whitelisted before using this package. I just wanted to provide some info. Understandably i don't want the customer to take us out of whitelist again to test this.
It seems like the bundling solution just moves the antivirus from flagging the DLL download directly, to flagging the /app.bundle download.
@Xeio Is that speculation or are you seeing the app.bundle get flagged with a deployed app? It it's getting flagged, could you please try https://github.com/stavroskasidis/BlazorWasmAntivirusProtection and see if that helps?
I got linked this from a user https://cdn.discordapp.com/attachments/738259572669677601/953873631144976425/unknown.png
EDIT: I'll try that package when I get a chance. Should I disable the bundling while using that?
I got linked this from a user
Got it - so they are still blocked. Thank you for letting us know!
I'll try that package when I get a chance. Should I disable the bundling while using that?
Yes, you should remove the multi part bundling and follow the instructions on the https://github.com/stavroskasidis/BlazorWasmAntivirusProtection readme. Please note this is not a Microsoft maintained project, but it is using a technique to modify the .NET assemblies that we are also considering.
Seems like flipping bits in the header also isn't good enough like that project does. Same user was kind enough to test again: https://cdn.discordapp.com/attachments/738259572669677601/954218938605117500/unknown.png
Also ran it through VirusTotal since I forgot I could tell it to hit the file directly. Seems like bit flipping "fixes" a few AV compared to the normal trimmed DLL, but BitDefender and G-Data still detect an issue.
Seems like flipping bits in the header also isn't good enough like that project does
Of course it's not. I'm sorry to keep repeating this but why does anyone think that these kinds of minimalist moves are going to fool sophisticated security hardware and software? If it were that easy they wouldn't be very good security mechanisms.
I really believe much more significant obfuscation is going to be needed. Ideas I would consider -
- XOR mask the entire assemblies
- Embed the assemblies in valid .JS code as global base64 strings. This, I believe, has the greatest chance of success because if the blockers aren't going to allow JS then their users are blocked from virtually any site, not just ours. They could then be decoded in javascript and supplied to the Mono WASM runtime without having to touch the disk in binary form.
why does anyone think that these kinds of minimalist moves are going to fool sophisticated security hardware and software?
Well, if we don't try it then we're really just guessing. We're trying simple approaches first to avoid introducing potentially unneeded complexity.
@Xeio In .NET 6 the Blazor WebAssembly packaging can be completely customized: https://docs.microsoft.com/aspnet/core/blazor/host-and-deploy/webassembly-deployment-layout. Unfortunately, at this point we don't have a suggested packaging that works in your customer's environment, so you'll need to either experiment with alternative packaging or work with the customer to unblock the app in their environment. We will revisit this issue in .NET 7.
Well, if we don't try it then we're really just guessing. We're trying simple approaches first to avoid introducing potentially unneeded complexity.
Thanks, and I hear you, Dan. But on this end we need confidence that our product is going to work reliably before we deploy it widely and have an embarrassing disaster. I just think that taking small steps is going to prolong the pain we the publishers are going to experience as we keep encountering new environments that reject each next incremental mitigation measure that's taken. I think a better approach would be to start with what we know all security systems have to allow in order for basic modern websites to work, and then try to make the Blazor assemblies look like that. Hence the "base64 string in a valid .JS file" idea.
.NET 6 the Blazor WebAssembly packaging can be completely customized:
Let me ask you (or anyone) this. I confess I haven't looked too closely at the customized packages yet other than to try them out. (Been a little busy building my awesome application ;)). But could my ideas above (XOR or base64 in JS) be implemented within your framework? Just want to know if something like that ought to be possible before I spend a lot of time in the weeds of custom packaging.
Was curious to just test it, a base64 encode inside a json payload is only potentially reliable right now. Doesn't seem to be detected by virus engines currently, but at least one company flags a base64 encoded DLL header as suspicious.
Granted at that point it's essentially on the scale of encrypting them with key at compile-time (that gets included in the client), stuffing them bas64 encoded in a JSON file (so the extension doesn't get flagged). Seems like that would be possible to do modeling off the BlazorWasmAntivirusProtection project above at least in a custom way.
My project is just a hobby thing though, I may just set everything to <TrimMode>copyused</TrimMode>. It seems like it's just a few of the Microsoft DLLs that get flagged by AV scans once trimmed, my project-specific DLLs (and nuget packages) at least that I can tell do not so far. Downside of course is it takes the download from 2.5M to 4.7M at initial load. π€·ββοΈ
@Xeio sorry for being dense but are you saying you tried a Blazor custom package that transmitted the assemblies as base64 strings? Are you able to share your code?
What I was thinking specifically was transmitting them as Javascript files, or perhaps a single Javascript file. Like this:
assemblies.js
let asm_system_dll = "d2hhdGV2ZXI=";
let asm_myassembly_dll = "d2hhdGV2ZXIy";
// Now convert to arrays and feed them to Mono
etc.
Even the most conservative firewalls should see this as valid Javascript code, because it is. And I believe - if I understand the guts of the WASM SDK correctly - this would have the added benefit of being able to be fed directly to the Mono runtime in memory as a blob, and never having to touch the disk in binary form. That should further help with antiviruses, most of which I believe do not actively scan RAM.
The size increase is frustrating though. I assumed base64 compressed well but apparently not. Still, if it's used as a fallback and it's this or our users can't use our applications, I'll take it.
@Xeio sorry for being dense but are you saying you tried a Blazor custom package that transmitted the assemblies as base64 strings? Are you able to share your code?
Not quite. I figured it would be prudent, before even attempting that, to just use a standard tool to base64 encode one of the flagged DLLs, save it as a json file, and upload it to a scanner engine to see what it spits out.
This is that result. It's worth noting that at least for now no AV seems to flag the file, but there is a vendor that flags it as suspicious on the "Community" tab.
Hello everyone, I have updated my package BlazorWasmAntivirusProtection and added support for multiple dll obfuscations, changing the default to XORing the dlls with a key, instead of just changing the headers.
Please give it a try to see if the new XOR obfuscation helps you.
Works for us with G Data & Sophos, but doesn't address G Data's flagging of cached files (G Data now goes haywire, picking up tmp files too, but that may be unrelated)
Our applications running with blazor wasm. Many of our customer complains about issue with blocking dll.
But there is another problem with blazor wasm and firewalls. Now two times our domain was blocked due to false positives of firewall/antivirus producer. Our customer could not access our applications for several hours. This issue getting worse and we hope that there will be soon a solution from Microsoft which solves the issues.
On the attached screenshot form virustotal you see the blocked Microsoft.JSInterop.WebAssembly.dll getting blocked by several antivirus programs. Or you can use the link: https://www.virustotal.com/gui/file/bf3c1a22f16103f087c6131c5ca3543aeec2fb34ab4a6fa1bc3126661722379e?nocache=1
When building a solution for the firewall issue also such issues with antivirus programs should be taken into consideration.
@Schaeri is right, and I should have pointed this out sooner myself. G Data entirely blocked our domain for a day because it had recorded an "infected file" from our domain. This included our corporate website.
This is WITH the xor obfuscation???
Gotcha. Thank you for your efforts on this. Perhaps what I'm unclear on (and thus Dan and his team likely are also unclear on) is what we are asking Microsoft to do about it? Incorporate obfuscation directly into the standard blazor packages by default right?
(I'd also be for suing some of these antivirus makers. They're really out of control and reckless in what they call malicious and it's harming our businesses).
Curious has anyone tried signing the dlls with an EV certificate? I wonder if that would make any difference to some of these security or AV systems. Just like EV gets you past Windows smart screen (which is worth every penny despite feeling a little like a racket given how freaking expensive they are).
In order to bypass default caching of blazor we can set BlazorCacheBootResources
property to false and implement our own caching in beforeStart
method and use it to serve the resources through wasmOptions.loadBootResource
.
@nvmkpk Please could you share some example code?
@nvmkpk Please could you share some example code?
For BlazorCacheBootResources
, just add it to the blazor project's csproj file. For adding caching in beforeStart
, there are several examples online. Sorry, I don't have any code as I haven't tried it myself.
I had a Blazor Wasm app fail at a customer today whose firewall blocks .dll files, both the apps .dlls and the .NET/Blazor ones.
Using @stavroskasidis's BlazorWasmAntivirusProtection with default settings, i.e. file rename to .bin and XOR, works and allows the app to download the .bin files and run.
That said, it would be awesome with something that is officially support out of the box, as this can quickly become a moving target.
This is a screenshot from the response tab in DevTools when trying to download the .dll files. The .dll files was blocked with a 403 status code and the HTML from the screenshot returned.
I had a Blazor Wasm app fail at a customer today whose firewall blocks .dll files, both the apps .dlls and the .NET/Blazor ones.
Using @stavroskasidis's BlazorWasmAntivirusProtection with default settings, i.e. file rename to .bin and XOR, works and allows the app to download the .bin files and run.
That said, it would be awesome with something that is officially support out of the box, as this can quickly become a moving target.
This is a screenshot from the response tab in DevTools when trying to download the .dll files. The .dll files was blocked with a 403 status code and the HTML from the screenshot returned.
Could you please provide as much info as you know about the customer's firewall (Product Name, Version etc)?
...
Could you please provide as much info as you know about the customer's firewall (Product Name, Version etc)?
Unfortunately, I don't have access to any more information than what's in that screenshot. The security team just says "no" to all questions and requests, as they tend to do :)
Works for us with G Data & Sophos, but doesn't address G Data's flagging of cached files (G Data now goes haywire, picking up tmp files too, but that may be unrelated)
There is a new version of the BlazorWasmAntivirusProtection (1.7.1) package that solves this by swapping Blazor's default caching mechanism with a custom one that saves the obfuscated assemblies on the cache instead of the unobfuscated ones.
So now even the cached files are obfuscated, so there should not be any more antivirus shenanigans with the cache.
awesome idea and blog post here
How do I do this without a server project (standalone) from a static website/fileshare like azure or github pages?
Why does "Publish browser-wasm" produce 30 dlls anyways? Is there a setting or config somewhere I can tell it to publish a single dll? I can for console apps?
Fails!
const bundleFromData = await bundleResponse.formData();
TypeError: Failed to fetch
Works?
const bundlebuffer = await bundleResponse.arrayBuffer();
const bundleblob = await bundleResponse.blob;
Array and Blob both work, so what is different and wrong about formData()?
How do you tell it the boundary "--0a7e8441d64b4bf89086b85e59523b7d"?
@1618employment That blog post describes how the MultipartBundle package, in the title of this issue, works. This thread supercedes that article. The BlazorWasmAntivirusProtection package works in Blazor Wasm standalone.
thanks, I'll take a look...I think the C# code for creating FormData is incorrect, the boundary needs to be inside the foreach loop in order to create multiple boundaries for multipart/formdata, as its written now it only puts a single boundary "--0a7e8441d64b4bf89086b85e59523b7d" at the start of the entire bundle file!
@1618employment MultipartBundle doesn't do enough to fix the problem, don't spend any more time on it. Use BlazorWasmAntivirusProtection.
@Andrzej-W Have you tried out the experimental multipart bundle functionality and does it enable Blazor WebAssembly app execution in environments were you were previously blocked?
This resolved my issue and fw is no longuer blocking blazor wasm from executing. But the generated app.bundle file is huge and seems to be downloaded for each new browser session. Is there a possibility to cache it ?
@rahou25 If you read past Dan's quoted message, you'll find that BlazorWasmAntivirusProtection is now the best solution to the problem. It obfuscates rather than bundles, and will cache the results.
I've just started experimenting with Blazor and I was rather astounded to see a ton of .dll's being downloaded in my browser's network tab. Surely there should be an option to bundle this all up into a few minified .js files similar to something like Webpack? It might not be as cacheable but at least it would look like a regular SPA-style download.
I've just started experimenting with Blazor and I was rather astounded to see a ton of .dll's being downloaded in my browser's network tab. Surely there should be an option to bundle this all up into a few minified .js files similar to something like Webpack? It might not be as cacheable but at least it would look like a regular SPA-style download.
With HTTP2, which frankly all browsers support now, the amount of files doesn't matter from a performance point of view. It's actually a benefit that you can choose to download parts of the apps dll's initially and then lazy load others when a feature is needed.
I would like to point out another value of bundling the .dll's: SEO.
From my experience, when bundling your dll's, you make better use of your "crawl budget" when getting pages indexed in a search engine.
The google search console was constantly giving me the message below when I requested to re-index an updated page.
Oops! Something went wrong
We had a problem submitting your indexing request. Please try again later.
What I noticed is that even though I am using render-mode="WebAssemblyPrerendered"
, the google bot is still trying to download all resources associated with each page in my website leading to a big amount of requests for a small website.
Though I am not 100% sure (because the Google search console does not provide more details about the problem) I believe that the fix for me was to bundle the dll's so that I now have a more reasonable ratio of requests per page.
After weeks of not being able to make re-indexing requests, and the bundling logic deployed yesterday, today I finally succeeded to make a re-indexing request.
My "use case" is serving a static website/app from decentralized storage.
Whether you're using IPFS or web3 each file gets a unique identifier so referencing 200+ DLLs this way isn't feasible.
One unique id for index.html, which references a second unique id for blazor.webassembly.js, and a third for app.bundle is more doable.
I know there is a way to use a manifest file, but again 200+ DLLs makes this tedious, 20 much better, 2 = best.
I could probably write a javascript "shim" to unpack a gzip bundle and load the DLLs, but again this is a bit outside my wheel house and I'm not sure the effort would be worth the reward.
It seems to me like a Microsoft supported solution to this issue would be a better long term plan.
Why does every dev need to host and serve their own instance of these standard files, "blazor.webassembly.js" and those DLLs?
What happens when these files need to be updated?
What version are we on now 6.0.9, so every dev/project has to go recompile and redeploy?
Seems like a better solution would be for Microsoft to manage and serve the required runtime files from an official CDN and developers are just responsible for hosting "Just My Code"?
if they aren't going support compiling down to a single DLL then something like...
<script src="https://cdn.microsoft.com/framework/6.0.8/runtime.min.js" integrity="hash"></script>
<script src="https://cdn.microsoft.com/framework/6.0.9/runtime.min.js" integrity="hash"></script>
If a dev wants to host their own framework files that's ok too, just would like to see more options!