Giter VIP home page Giter VIP logo

Comments (78)

PromoFaux avatar PromoFaux commented on September 17, 2024 1

I gave up on being hip as soon as I turned 30. XD

from adminlte.

PromoFaux avatar PromoFaux commented on September 17, 2024

Hey, thanks for the post.. I've only skimmed this so far, but promise I'll do the justice of giving it a full read when I get home from work!

Just a note.. it can only be accessed by malicious third parties if it's set up to be visible from the outside world... (which we do not do, by default.. it would have to be done in the port-forwarding settings of the users router...)

Other than wanting to see the stats, why would you forward port 80 to the pi-hole?

But I totally understand the sentiment of your post, and I will give it some thought.

I will read it properly.

from adminlte.

PromoFaux avatar PromoFaux commented on September 17, 2024

Yeah, ok wow. I really didn't read that properly. You make a lot of valid points, which will be discussed.

@Mcat12 Before you push devel to master, could you completely strip the whitelist/blacklist php pages from the repo, rather than just hide the links. I know they don't fully function yet, but just to be on the safe side we should probably get that locked down before we push them out to users.

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

This will not be a problem in the next release, but we will certainly figure out a way to fix this!

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

Does #49 fix this?

from adminlte.

Fedora-Core avatar Fedora-Core commented on September 17, 2024

At first sight it should work.
However.... At first sight.
It is a work-around.
Like back in the mid-1990s.

The well-paid IT-gurus from the multi-million-dollar advertising industry are already busy with the modification of their Pi-Hole-"whitelist" hack.
With something like the following =>
<img src="http://adserver.com/admin/php/add.php?list=white&pass=0.0&domain=adserver.com">

---------------------------- Please 'harden' the Pi-Hole admin webserver.

Security should not be accomplished with a work-around.
It should be done fundamentally.

Security should not be accomplished with GUI code.
It should be done with the underlying server systems.

----------------------------

Final General Observation =>
This proposed fix ( even when fixed again ) would be valid only for this particular piece of the Pi-Hole adminLTE functionality.
Who knows ( now ) what other functionalities are imaginable in the future ?
Do these new functionalities also need to fix their access problems with a GUI work-around ?

----------------------------

Greetings, F.C.

from adminlte.

PromoFaux avatar PromoFaux commented on September 17, 2024

👍

from adminlte.

PromoFaux avatar PromoFaux commented on September 17, 2024

I've had some thoughts on this myself, which we are currently discussing internally, I'll be sure to run in by you for final analysis before we realise we have missed something important :)

from adminlte.

DonLexos avatar DonLexos commented on September 17, 2024

Well one thing to take in consideration is that when you require a password no matter how you save it it needs to expire. It's not a real fix if you require it and cookie the user for 30 minutes who then goes out and browses the internets only to visit a addomain.com/admin/trick-url with his credentials saved.

Not entirely sure about lighttpd but what could help is that a ?sessionid=X is required in the url and otherwise it requests the login details. The adserver can't ever guess it, and as long as it is not saved in a cookie (but in a session) it should not be able to find it.

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

Persistent cookies? (And with the password comes maintenance, and users forgetting passwords, locking themselves out and all the other fun of securing the things...)

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

The password is only saved in the js, not a cookie, so it is never kept for longer than the user has the page open.

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

Here's a wild one, Google Authenticator,,, 2 Factor it...

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

But a password and a cookie, make the process so there isn't a single point of failure (or single point of override in this case...)

from adminlte.

DonLexos avatar DonLexos commented on September 17, 2024

No cookies at all, if the /admin/php/whitelist.php checks for a valid cookie it does not really matter if there is a password or not if the user logged in prior.

You could simply have the password stored in a file somewhere and have the user log in, then create a session and use that in the URLs.

2factor might bring many new challenges. I would love it (since I already use 2FA) however I can imagine that for some users that might complicate things.

from adminlte.

DonLexos avatar DonLexos commented on September 17, 2024

And @dschaper and in a normal situation a cookie would be set by the code that handles the successful browser login. Even if you let it expire in 5 minutes the window of opportunity for a rogue <img src="http://adserver.com/admin/php/add.php?list=white&domain=adserver.com"> is small but still there.

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

We do have a method to tell if the request came from the /admin.php page though... @DonLexos take a look at your /admin.php page and look at the X-Headers...

from adminlte.

PromoFaux avatar PromoFaux commented on September 17, 2024

Surely we can't use that as an auth method...? Wouldn't that be quite easy to spoof?

from adminlte.

DonLexos avatar DonLexos commented on September 17, 2024

@dschaper trying to find them in Chrome Dev console but fail to locate them.

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

Not as a single authentication method, but as a part of a layered approach. And to spoof that then the ad companies would have to send out that x-header, and I seriously doubt they would go that route... (It'd be nice to get some legal protection on the phrase used in the X-header and then nail them for trademark infringement if they used it...) I'm just throwing out multiple methods that we can use in a layer approach...

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

@DonLexos Can you install HTTP Headers from the Chrome store?

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

capture

from adminlte.

DonLexos avatar DonLexos commented on September 17, 2024

Got it, you would use the referer?

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

The X-Pi-Hole header, and I think with some magic you could randomize the payload for the header and verify that, or at least change up the payload so that it's not predictable? Totally throwing off the wall here just to see if anything clicks...

from adminlte.

DonLexos avatar DonLexos commented on September 17, 2024

But how would the page get that token?

I mean if it is in a cookie the rogue addomain.com/admin/etc would simply still work since it is locally, problem is we redirect addomain.com to pi-hole-ip and that has access to exactly that info, no?

from adminlte.

Verpz avatar Verpz commented on September 17, 2024

Php for the password? And not everyone has cookies enabled. 2 step would be great but wouldn't the pi need Internet access?

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

If you look at the lighttpd.conf you see that anything that is served via the admin directory has that X-Header added to it, so that could be just another piece of authenticating information, maybe along with a session cookie or something. If a company want's to endrun us, they will, there's no stopping them honestly, we just need to make it more uncomfortable than comfortable for them to do anything. And we'll probably need to change tactics, just like we needed to change when IPv6 became the way to send ads down the pipe....

Of course I could be completely wrong, but it's an idea?

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

And the blank replacement page has it's own X-Header added...

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

@Verpz, Nope, with 2 factor you only need to sync up once, then everything is generated via a shared algorithm. no internet access is needed. (Although a Pi-hole without net access wouldn't do too well, since it needs upstream DNS servers to resolve good addresses, and the install script picks it's IP address by checking to see which interface has a route to 8.8.8.8)

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

Gotta run to a site survey, the team knows how to ping me if they have any questions...

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

Oh, and I have cookies and JS disable in Chrome, but I allow the sites I want through, and I think that's a fair thing to ask our users... I'm kind of laying hard on the enterprise aspect of things, I think that would be a great place to get into...

from adminlte.

jacobsalmela avatar jacobsalmela commented on September 17, 2024

Ad Block Plus uses X-headers with unique IDs to make sure they get whitelisted. I wrote an article on it a while back, so I'm sure something like that would be possible.

from adminlte.

DonLexos avatar DonLexos commented on September 17, 2024

If you look at the lighttpd.conf you see that anything that is served via the admin directory has that X-Header added to it, so that could be just another piece of authenticating information, maybe along with a session cookie or something.
But that does not prevent the issue raised then would it. The addomain.com/admin/whatever would also contain that specific X-Header since it is served from the same directory. A cookie could work only if that would not be accepted if the url is not http://192.168.1.x/admin/ but http://addomain-trick.com/admin

from adminlte.

PromoFaux avatar PromoFaux commented on September 17, 2024

I've been thinking along the lines of a seperate web server entirely for the admin pages. Behind a non-standard port which the user chooses themselves. In that case, we have no way of knowing what the port used is, and neither would ad companies.

from adminlte.

PromoFaux avatar PromoFaux commented on September 17, 2024

Hell, it could even be done in lighttpd

from adminlte.

DonLexos avatar DonLexos commented on September 17, 2024

Well the port part sounds like a plan! Not sure if you should enable 2 webservers, some people are really keen on keeping things light. I would be happy to install MySQL for example since my pi only does the pi-hole blocking, but others disagree.

from adminlte.

Verpz avatar Verpz commented on September 17, 2024

What if the api is moved to a separate folder like /api, that is separately password protected. Or to trigger the whitelist / blacklist function it requires a password in the url like this:

/admin/php/add.php?list=white&domain=ad.com?password=whatever

Would the url be really un secure?
Two step auth sounds great but it may be confusing to some users.

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

I see a possible split in the code base, home use and enterprise use. Home use is getting more and more complex. Passwords are just a difficult thing to do operationally, but I like the ideas, keep them coming and lets see what we can cherrypick out and put together... Thanks for everyone's input on all of this...

from adminlte.

Verpz avatar Verpz commented on September 17, 2024

What if there are two install options, like for basic home setup with no extra features (set and forget) or an advanced install where perhaps a flag is added to the install command such as:

-a or -advanced

Which gives more options and customisation which could be used for "enterprise" installations or for people who want extra features and such. This way there wouldn't be two separate projects or a split in the code. Am I right in saying that the api / add.php is the main security issue here? In that case a random api key generated on install and a user defined password on install should fix that issue, unless /admin needs to be protected in general.

from adminlte.

DonLexos avatar DonLexos commented on September 17, 2024

What if, the admin folder is not default at /admin/ but at /whatever/. Maybe even by user choice, or just random /admin3312/. Even adding 4 digits would resolve the rogue adserver thing since I doubt they will add 10000 lines of image code (and when they do you can always add a digit more).

As long as the script mentions the admin page at the end
:: You can find the stats in the admin panel at http://192.168.1.x/admin3312/

Only thing you need to do is save it. Or would that wreck the git intergration?

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

That might work, but users either won't like or will choose a generic one like pihole or admin.

from adminlte.

DonLexos avatar DonLexos commented on September 17, 2024

Well in that case why let them chose? I would not care a bit as long as I know where it is, and it does not change after an upgrade since I simply bookmark the /admin3312/ page.

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

How about staying with passwords (until we move to different ports or something) and check the hash of the password and input. That should fix the problem of inputting something like 0.0 for the password.

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

Also, store the password after install as a hash instead of plain text. This function could be useful.

from adminlte.

DonLexos avatar DonLexos commented on September 17, 2024

Passwords is also a good solution! Would also prevent users in same network to access (and white/blacklist things) in a more commercial installation environment.

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

Currently, that's what's up in devel.

from adminlte.

PromoFaux avatar PromoFaux commented on September 17, 2024

Wait was password=0.0 a specific exploit? How would that even work? I really think we should get a solid thought through bulletproof option together, rather than a half-baked stopgap. We're not desperate to include the extra functionality to the website, as nice as it would be.

from adminlte.

DonLexos avatar DonLexos commented on September 17, 2024

I will need to dive into git(hib) better so I can fetch the devel branche, test/play with it myself and help out there (if/when needed).

from adminlte.

PromoFaux avatar PromoFaux commented on September 17, 2024

Wait was password=0.0 a specific exploit? How would that even work? I really think we should get a solid thought through bulletproof option together, rather than a half-baked stopgap. We're not desperate to include the extra functionality to the website, as nice as it would be.

from adminlte.

PromoFaux avatar PromoFaux commented on September 17, 2024

Argh. Apologies, commenting from mobile. Messing things up!

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

I haven't tested it yet, but hashing and checking hashes should prevent any exploits such as that.

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

Just tested, 0.0 doesn't work

from adminlte.

PromoFaux avatar PromoFaux commented on September 17, 2024

I'm pretty sure it was just given as an example. What he's saying is that if the password is intercepted, somehow, the function can be run.

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

That's going to be the same problem with any of his solutions. Without encryption, it's going to stay like that...

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

I don't think that there's enough features to split between home and enterprise. With #53 this issue may be solved until we move to redirecting ads to an empty server or port or something.

from adminlte.

ryt51V avatar ryt51V commented on September 17, 2024

I've just been reading through this issue, pi-hole/pi-hole#354, and #49

In those pull requests, it looks like we're rolling our own password protection, which usually means spending a lot of effort on writing and maintaining that's likely to have some flaw compared to something prebuilt we can use that's been written by a netsec team whose code has been well looked over by the FLOSS community.

pi-hole/pi-hole#360 and #53 also - my first thought was "Wait, why not bcrypt?" then "Wait, why not salt it?", followed by "Wait, I'm not even remotely netsec, surely there's even more missing than the basics I've read repeatedly on Ars Technica?"

Forgive me but I must be missing something - is there a reason we're not using lighttpd's mod_auth? I can see @Fedora-Core already mentioned lighttp's mod_auth in passing. (Ironically Googling "lighttpd mod_auth" brings up Jacob's article as the second result.) We know it will be relatively reliable, and there are quite a few options on how we encrypt the password, plus digest auth.


On another note:

  • @Fedora-Core mentioned running the admin web server on a different IP address.
  • @PromoFaux mentioned running it on a different port.
  • @DonLexos mentioned running it on a different subdirectory.

Another option: we run it on a different virtual host. I don't know lighttpd as well as apache, but I understand it can support virtual hosts just fine. The result would be, for example http://mypiholeadmin/admin, takes you to the admin interface, whereas going to http://myadserver/admin takes you to the blocking vhost. Since we control DNS this is easy to add to the hosts file or 01-pihole.conf.

First of all the ad provider would need to use a domain that isn't their own to try to trick the pi-hole, e.g.
<img src="http://piholeadmin/admin/php/add.php?list=white&domain=adserver.com">, which is bad form for them (not sure how non-pi-hole users' browsers will react to that) and I'm sure some ad networks wouldn't even allow. EDIT: Heh, we could even make it a globally routable domain (e.g. http://piholeblocking.cheaptld), register it ourselves and put some code - non-malicious but messes up the page for non-pihole users? Big ad wouldn't want to link to it then!

If we want, similar to the subdir idea we could ask the user for a domain to obfuscate it a bit - e.g. http://mypiholeadmin9725. EDIT: Or we could use the actual pi's hostname for this? Different for every user but they should know what it is.

Also, I believe would allow us to specify lighttpd options specific to the admin interface more easily than with a subdirectory, in particular mod_auth. It would also simplify the blocking vhost (regex wouldn't have to accommodate /admin).

from adminlte.

ryt51V avatar ryt51V commented on September 17, 2024

Also, I'm just thinking of a few things we can do to stop embedding. I doubt we can fully harden it this way and in any case I'm still strongly in favour of passwording the interface, but just food for thought:

from adminlte.

PromoFaux avatar PromoFaux commented on September 17, 2024

it looks like we're rolling our own password protection

It's there, but I personally am not happy with it. It's a workaround/hack to put off an issue, but it's there.

At the moment the whitelisting from the website is being put on hold whilst we work on the refactor, so there is plenty of oppurtunity to get this aspect of things nailed down. I still think the separate port idea is the simplest solution.

from adminlte.

ryt51V avatar ryt51V commented on September 17, 2024

It's there, but I personally am not happy with it. It's a workaround/hack to put off an issue, but it's there.

I know password protection wasn't considered until this issue was raised. But, done right, is it not a good idea as a permanent feature? IMO it's something we ought to have as standard anyway.

Password aside, in terms of separating the admin interface, your separate port idea is my second choice and I agree that it's by far the simplest to implement and maintain.

from adminlte.

DonLexos avatar DonLexos commented on September 17, 2024

I like the own hostname idea, or running it on a (non existent) domain. What if the domain would be the non existent adminconsoleformypihole.pi. We can resolve this ourselves and in combination with what @ryt51V mentioned it could resolve to somewhere in /var/www/html/whatever that is not accessible through blockeddomain.com/admin/ (or http://192.168.1.xx/admin).

from adminlte.

PromoFaux avatar PromoFaux commented on September 17, 2024

Sorry, @ryt51V I meant in terms of rolling our own. Self-rolled authentication/security/encryption of any sort is generally a bad idea!

I really like @Fedora-Core's suggestion of multiple IPs, but it's a bit beyond my understanding of how things work! Which is why I ended up thinking about separate ports instead. :)

from adminlte.

ryt51V avatar ryt51V commented on September 17, 2024

@PromoFaux Ah, right, thanks for clarifying. This is why I'm a bit confused in the first place - AFAIK using lighttpd's mod_auth in the first place would not only have been better but also quicker and easier. i.e. A quicker ugly hack, except not ugly and not really a hack.

I think multiple IPs for each service are ideal, but are not appropriate for an auto install script, both now and after this project has matured. Ports, vhosts and subdirs are far more suitable.

from adminlte.

looterz avatar looterz commented on September 17, 2024

I noticed pi-hole had no authentication for the web panel when installing today, and im also not really a fan of lighttpd. So, I moved it over to nginx and setup a simple basic_auth user:pass setup, nothing fancy but it works. Definitely agree on the separate static ip solution for long-term security, though.

For even better security for the web service (although probably overkill) you could setup HTTPS Client Authentication so that only the administrator of the pi-hole with the certificate can interact with the web service.

from adminlte.

DanTup avatar DanTup commented on September 17, 2024

I haven't read all of the comments here, but is this not just XSRF ("Cross Site Request Forgery")?

XSRF is a common issue - eg. if I'm logged into my bank and then I visit a malicious site, what's to stop them outputting a form with hidden fields and auto-posting to my banks transfer form to steal my money?

There's some info in this here:

https://en.wikipedia.org/wiki/Cross-site_request_forgery

One fix is basically to make sure all whitelists requests get a random value (token) entered into the form when the HTML is rendered and when submitted to the server, validate that that token is correct. Here's what it looks like in aspnet mvc (I know you don't use that, just the one I'm most familiar with).

from adminlte.

DanTup avatar DanTup commented on September 17, 2024

May also be worth reviewing CSP and locking down anything else that shouldn't be allowed. And X-Frame-Options to ensure the control panel can't be loaded inside a frame on a site (eg. to be click-jacked).

Edit: Oh, I see a lot of this is already being discussed in #444! :)

Edit (Mcat12): Corrected link (It was going to an issue on almasaeed2010's AdminLTE)

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

Yep, actually just implemented the token on the whitelist branch and X-Frame-Options on the other repo (that's where the server configs are).

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

@Fedora-Core Have you checked out the latest dev versions of Pi-hole and the web interface?

from adminlte.

Fedora-Core avatar Fedora-Core commented on September 17, 2024

Open Source is great !
If one dares to open the source...

Yes, I have followed the development branch.

And now you have introduced a "source" for far more serious issues => concurrency !

What if father Abe is blacklisting a bunch of porn domains for his little daughter,
and his son Ben is busy whitelisting a newschannel,
and his son Carl is busy whitelisting a gamesportal,
all at the same 2 second interval ?
Since that's the time-frame that the script typically needs to finish on a bare Raspberry-pi.

And a pihole running in a college dorm has probably several adminweb-users...

Problem = concurrency !

Don't tell me that you will instruct the pihole adminweb-users not to do this...
Don't tell me that you will instruct the pihole installers not to give the adminweb away...

Once your software is in the wild, you have strictly no control over it's use.
Your development needs to be 100% foolproof.

This is about delegation of duty, and also - I'm not going into it - elevation of privileges.

Proposal:
The PHP must accept the request from the adminwebuser, and pass it on to another process.
That other process should - independently - execute all the accumulated request that have been queued in a very well defined - and publicized - time-slice.
Don't look at the PHP semaphores, they are in fact a form of mutex.
Don't look at the PHP queues, they use shared-memory (don't know how Docker likes that)
Don't try to install another package for queueing, most require too much effort.
There is a very simple solution to tackle this.
° A cron job (a one minute interval would do just fine)
° A subdirectory "arriving" with write access for www-data
° A subdirectory "arrived" with write access for www-data and the cron job
° A subdirectory "accepted" with write access for the cron job
° A subdirectory "iamalreadyandstillbusy" with write access for the cron job
° Elevated privileges for the cron job only (SignalHangUp towards DNSMasq)
° etc

Get inspired ;-)

Yes we can!

note:

The English language has this expression:
Eating_your_own_dog_food
About Feb 19, 2016 =>
I have immediately (19) implemented my own proposed short term solution.
I'm safe.
I have during the following week-end (20-21) implemented my own proposed long term solution.
I'm very safe.

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

Re: Docker, Is it the Docker way to have a container that includes both a DNS Resolver and a web server? Wouldn't the concept of microservices dictate that two separate containers be used and Compose them together? Or if using a recent Docker version, advertise the services?

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

@Fedora-Core What about using a database for the queue? We are currently experimenting with sqlite with the Python rewrite and it's going well. PHP could add to a queue and then call a pihole script that would run through it. Just thinking out loud here. :)

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

Would that just put the race in a different queue though? Not really solving the concurrency unless you lock the database for access and then it's just pushing the the issue to another thread.

Speaking of which, would you folks be okay with a new issue for concurrency discussions. Don't want to have this single issue addressing two separate themes... Yeah, I'm a little AR about that kind of thing, 😃

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

A new issue would be good. But about the database, it could have an auto incrementing id, and the program would go from lowest to highest id. Therefore when a new action gets into the queue, it'll be handled by the program after all the other actions get handled. I'm pretty sure sqlite would be able to handle concurrency, as this mentions that it locks the database during writes.

from adminlte.

dschaper avatar dschaper commented on September 17, 2024

Okay, I was thinking Race versus Concurrency. User A blacks a domain while User B whites the same domain in the same update cycle. I'm still fighting with even needing an external database with Python, just using all internal data structures and exposing via API or interfaces. But that's yet another Issue :)

from adminlte.

viemmsakh avatar viemmsakh commented on September 17, 2024

I'm a little late to this conversation, but would a simple sqlite db with session variables work? Seems like that would be a pretty easy fix to add user authentication to pages that need it without needing to overhaul too much.

  • login page (process logins and set session)
  • on add.php add to top if (!isset($_Session['login'])){ header ( 'location: admin/login.php')}
  • create a user cp that lets admin change password as needed.

If user forget password they can open up the sqlite db and add a new one in manually.

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

Thanks for your concern @viemmsakh. 😄 In the latest version we've implemented session variables in the security-focused php (whitelisting and blacklisting) that verifies that only the web interface is able to activate those actions. We've also made sure that the web interface can't be used in an IFrame (tricking users to whitelist the ad one way or another). We're still not sure whether or not we should add a login page for the web interface (or parts of it), but we'll keep your idea in mind. 👍

from adminlte.

DanTup avatar DanTup commented on September 17, 2024

Did you implement XSRF protection?

from adminlte.

PromoFaux avatar PromoFaux commented on September 17, 2024

I'm a bit behind on websec terminology.. but if CSRF is the same thing, then yes!

from adminlte.

DanTup avatar DanTup commented on September 17, 2024

@PromoFaux Sorry yes, it is :) Sometimes people write "X" for "Cross" in an attempt to be hip ;)

from adminlte.

AzureMarker avatar AzureMarker commented on September 17, 2024

These issues should be fixed for now.

from adminlte.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.