Giter Site home page Giter Site logo

duo-labs / efigy Goto Github PK

View Code? Open in Web Editor NEW
508.0 508.0 39.0 228 KB

A small client application that uses the Duo Labs EFIgy API to inform you about the state of your Mac EFI firmware

Home Page: http://efigy.io

License: BSD 3-Clause "New" or "Revised" License

Python 100.00%
efi firmware macos security

efigy's People

Contributors

futureimperfect avatar kylelady avatar mynameismeerkat avatar pnowaczyk avatar vielmetti avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

efigy's Issues

Exception if running on firmware with "E" in build number

Running the app on MacBookAir3,2 with firmware "MBA31.0061.B0E" -- received the exception:

Traceback (most recent call last):
  File "./efi.py", line 623, in <module>
    efigy_cli()
  File "./efi.py", line 367, in __call__
    self.check_fw_versions(sys_info, api_results)
  File "./efi.py", line 538, in check_fw_versions
    api_efi_build = int(api_efi_str[2].replace("B",""))
ValueError: invalid literal for int() with base 10: '0E'

Clearly code isn't handling this build number correctly... should it just be converting from hex?

Dubious Version Number Warning

When I run the command, I get (among other information) this line:

 EFI firmware version check:
	[-] ATTENTION - You are running an unexpected firmware version given the model of your system (MacBookPro11,5) and OS build you have installed (16G1036). Your firmware is MBP114.0177.B00, the firmware we expected to see is MBPro114.0177.B00.

It looks dubious to me as the only difference in the version numbers is “MBP” vs. “MBPro” (where the “P” should represent the pro already).

Request - additional option to auto run

Currently the EFIgyLite_cli.py tool requires interactive response to the question 'Do you want to continue and submit this request? [Y/N]'

This makes it difficult to impossible to 'call' the EFIgyLite_cli.py script via another script.

I therefore request an additional command line option be added e.g. -a to automate or -y to always say yes. Therefore calling the script as follows -

EFIgyLite_cli.py -o -y

would run it and not ask the normal submit question and would return the desired results.

https://api.efigy.io SSL Certificate has expired

The SSL Certificate for https://api.efigy.io expired on September 17, 2020.

Not sure if Duo is still even supporting this utility, doesn't seem to have updated any models/firmware since Mojave.

Will likely have to retire the use of using this utility in my environment for checking the firmware state.

log option

The -l option doesn't work as indicated in the output of -h.
-h shows
" -l LOG, --log LOG File to log output to"
-l is treated as directory that the output file is written to with a generated filename.

Running the following command
" python EFIgyLite_cli.py -l efigy-out-2017-10-11.txt "
resulted in the following error with "N" replacing the the actual value generated
"[!] Error opening specified log file at 'efigy-out-2017-10-11.txt/EFIgyLite_cli_NNNNNNNNNNN_NN.log' - [Errno 2] No such file or directory: 'efigy-out-2017-10-11.txt/EFIgyLite_cli_NNNNNNNNNNN_NN.log'
"

SMC version and model unrecognized

gilbahat@heka:~/EFIgy$ ./EFIgyLite_cli.py -o

EFIgyLite API information:
Server: https://api.efigy.io
API Version: 0.2
Updated On: Mar 1 2018, 22:25


Endpoint: 127.0.0.1
# Enumerated system information (This data will be sent to the API in order to determine your correct EFI version):

Hashed SysUUID   : 23edbb5824f4002913f9c87bdcce37c06cab010da5f3241361e0ea204884358d
Hardware Version : MacBookPro15,1
EFI Version      : 220.171.0
SMC Version      : None
Board-ID         : Mac-937A206F2EE63C01
OS Version       : 10.14.5
Build Number     : 18F203

[?] Do you want to continue and submit this request? [Y/N] Y

Unknown model of Mac supplied: MacBookPro15,1

-o command line flag returns bad result

With the latest version of the script if I do -

EFIgyLite_cli.py -o

Which is only supposed to return the firmware information I get the following result

Your firmware version 194.0.0 is older than expected for a MacBookPro14,3 running build 18F132. You should update your EFI firmware.

If I do not use the -o option then I get

# Results:

EFI firmware version check:
	[+] SUCCESS - The EFI Firmware you are running (194.0.0) is the expected version for the OS build you have installed (18F132) on your MacBookPro14,3

Highest build number check:
	[+] SUCCESS - You are running the latest build number (18F132) of the OS version you have installed (10.14.5)

Up-to-date OS check:
	[+] SUCCESS - You are running the latest major/minor/micro version of the OS you have installed (10.14.5)

This discrepancy might explain why @swrobel is seeing a problem in issue #28

Wrong Results

EFI firmware version check:
	[-] ATTENTION - Your Mac model (iMac7,1) does not seem to have had any EFI updates released for it :'(

Highest build number check:
	[-] ATTENTION - You are NOT running the latest release build number of your OS version (10.11.6). Your build number is 15G18013, the latest release build number is 15G17023

Up-to-date OS check:
	[+] SUCCESS - You are running the latest major/minor/micro version of the OS you have installed (10.11.6)

First of all, the program doesn't identify my Boot ROM. My version is IM71.007A.B03, which is the latest for the iMac 7,1 (based on this https://support.apple.com/en-us/HT201518 ). It definitely has received Boot ROM updates before. Also, 15G18013 is the latest build for 10.11.6, not 15G17023.

EFI Verification

Is there a way to determine that my EFI (e.g. MBP53.00AC.B03) has not been comprised?
I tried to reinstall 'MBP53.00AC.B03', however, the reinstaller fails:

screen shot 2018-04-08 at 2 42 18 pm

MacBook Pro (15-inch, Mid 2009) | MacBookPro5,3 | MBP53.00AC.B03 (EFI 1.7) |  

$ ./EFIgyLite_cli.py -o

EFIgyLite API information:
	Server: https://api.efigy.io
	API Version: 0.2
	Updated On: Mar 1 2018, 22:25


--------------------------------------------------------------------------------
Endpoint: 127.0.0.1
	# Enumerated system information (This data will be sent to the API in order to determine your correct EFI version):

	Hashed SysUUID   : XXX
	Hardware Version : MacBookPro5,3
	EFI Version      : MBP53.00AC.B03
	SMC Version      : 1.48f2
	Board-ID         : Mac-F22587C8
	OS Version       : 10.11.6
	Build Number     : 15G20015

[?] Do you want to continue and submit this request? [Y/N]  y

	Unknown model of Mac supplied: MacBookPro5,3
--------------------------------------------------------------------------------

Handling for new firmware version style seems to be incorrect

Using both check.efigy.io and EFIgy GUI I get this mismatch:

Your EFI version is not what we expected.
You're running 166.0.0.0.0, but we expected you to be running IM171.0166.B00.

The CLI does not report the expected version, but says Your firmware version 166.0.0 is older than expected for a iMac17,1 running build 18F132. You should update your EFI firmware

Model: iMac17,1
Build: 18F132

Version information in EFIgyLite_cli.py wrong

Having over the weekend received messages indicating a recent update to the script to make it compatible with Apple's new firmware versioning approach I have just visited the github to look at the new script.

A very quick initial test does suggest it is working better.

I did however notice that the date and version information in the script is totally unchanged which along with the fact the first page or so of code is unchanged would lead a less observant person to think the entire script is unchanged. (It is changed. :) )

Can I request you tidy it up by updating this information.

An optional consideration would be that I had added a custom change to the last version to make it more usable for my own purposes but it would possibly help others. I added a -a command flag to get it to run automatically with no user interaction. This allowed me to call it from a management tool to get a report.

As in -

    parser.add_argument(
    	"-a", 
    	"--automate", 
    	action="store_true", 
    	default=False, 
    	help="Auto mode always submit to api and do not ask")

Catalina OS and firmware not supported?

I have started building macOS Catalina 10.15.1 Macs and it looks like your database is not yet updated for these. Here is a sanitised result.

./EFIgyLite_cli.py -o -y

EFIgyLite API information:
	Server: https://api.efigy.io
	API Version: 0.2
	Updated On: Mar 1 2018, 22:25


--------------------------------------------------------------------------------
Endpoint: 127.0.0.1
	# Enumerated system information (This data will be sent to the API in order to determine your correct EFI version):

	Hashed SysUUID   : 1f0d988ded159e2b162759550fxxxxxxxxxxxxxxxxxxxx0f6b100648be45b
	Hardware Version : MacBookPro14,3
	EFI Version      : 202.0.0
	SMC Version      : 2.45f1
	Board-ID         : Mac-551xxxxxxxxx44E2388
	OS Version       : 10.15.1
	Build Number     : 19B88

	Unknown OS build number supplied: 19B88
--------------------------------------------------------------------------------

API returning out of date results

Using the efigy extension for osquery


hostname | build_number_status | efi_version     | efi_version_status | latest_efi_version | latest_os_version | os_version
host-1   | failure             | MBP132.0238.B00 | failure            | MBP132.0233.B00    | 10.13.2           | 10.13.3
host-2   | failure             | MBP142.0169.B00 | failure            | MBP142.0167.B00    | 10.13.2           | 10.13.3

The API seems to think 10.13.2 is the most up to date OS version, and the latest_efi_version also seems to be out of date.

Unknown build number

When running EFIgy on my system, I get the following error:

EFI firmware version check:
[!] ERROR - Unknown Build Number '15G1611' given. (1507685319.35)

Security question

Hello there, I don't know if it is really the place to talk about this but… As serious and secure as Duo Labs could be, how can we trust the dataset information and results provided through the API ?

I mean, a malicious user could easily fake some data from the inside, or your service integrity could be corrupted by attacks from the outside, and then propagating false positive results with a very large scale implications. I know for instance many IT companies and administrations that will refuse to use a such tool because it relies on external services, only seeing another attack vector to manage.

So, what ensure to us that your service and data it provides are safe ? How well are protected your facilities and procedures ? What measures are being taken to avoid code and/or data corruption internally ? Do you plan to release a sort of offline dataset ?

I'm very sorry to make myself the devil's advocate, but from my point of view, these questions are very serious. The EFI version issue is real, but to rely on a service that is potentially another source of security breakdown is not a good enough solution.

EFI firmware version check ERROR - Unknown Build Number '17B48' given. (1511394575.64)

[xxxxx@MacMini ~]$ python /Users/xxxxxx/Downloads/EFIgy-master/EFIgyLite_cli.py --debug
DEBUG:main:[-] Certifi module not found, falling back to bundled cecert.pem file
DEBUG:main:[+] cacert file location: '/Users/xxxxx/Downloads/EFIgy-master/cacert.pem'

EFIgyLite API information:
Server: https://api.efigy.io
API Version: 0.2
Updated On: Nov 22 2017, 14:05


Endpoint: 127.0.0.1
# Enumerated system informaton (This data will be sent to the API in order to determine your correct EFI version):

Hashed SysUUID   : 6e6c1d07b2705fa2f9be7d1bd69528c6dd310f0d33b7840a1e7f4119446d2937
Hardware Version : Macmini6,2
EFI Version      : MM61.010B.B00
SMC Version      : 2.8f0
Board-ID         : Mac-F65AE981FFA204ED
OS Version       : 10.13.1
Build Number     : 17B48

[?] Do you want to continue and submit this request? [Y/N] Y

# Results:

EFI firmware version check:
	[!] ERROR - Unknown Build Number '17B48' given. (1511394575.64)

Highest build number check:
	[+] SUCCESS - You are running the latest build number (17B48) of the OS version you have installed (10.13.1)

Up-to-date OS check:
	[+] SUCCESS - You are running the latest major/minor/micro version of the OS you have installed (10.13.1)

EFIgy database not being updated? Wrong command/version processed?

I can see that the EFIgy script does not list support for Mojave but it also appears that the supporting database has not been updated for the latest High Sierra builds either.

./EFIgyLite_cli.py 

EFIgyLite API information:
	Server: https://api.efigy.io
	API Version: 0.2
	Updated On: Mar 1 2018, 22:25


--------------------------------------------------------------------------------
Endpoint: 127.0.0.1
	# Enumerated system information (This data will be sent to the API in order to determine your correct EFI version):

	Hashed SysUUID   : d9607c33fcd75578a5b7440ba5e74cef2fbe7862e97d4976a97c63f6861a7d1a
	Hardware Version : MacBookPro11,4
	EFI Version      : 187.0.0
	SMC Version      : 2.29f24
	Board-ID         : Mac-06F11FD93F0323C5
	OS Version       : 10.13.6
	Build Number     : 17G3025

[?] Do you want to continue and submit this request? [Y/N]  y

	# Results:

	EFI firmware version check:
		[-] ATTENTION - You are running an unexpected firmware version given the model of your system (MacBookPro11,4) and OS build you have installed (17G3025). Your firmware is 187.0.0, the firmware we expected to see is MBP114.0184.B00.


	Highest build number check:
		[-] ATTENTION - You are NOT running the latest release build number of your OS version (10.13.6). Your build number is 17G3025, the latest release build number is 17G65

	Up-to-date OS check:
		[+] SUCCESS - You are running the latest major/minor/micro version of the OS you have installed (10.13.6)
--------------------------------------------------------------------------------

Issue 1
Clearly build 17G3025 is newer than 17G65 contrary to the above incorrect report. Build 17G3025 is the one with the latest Apple Security Update for High Sierra.

Issue 2
It seems EFIgy is still looking at the older source of EFI version as returned for example by this command

system_profiler SPHardwareDataType | grep -i "Version" | awk -F ':' '{print $1 $2}'
or
echo "$(ioreg -d 3 -p IODeviceTree -n rom | awk -F\" '/version/{print $4}')"

It is possible to get the older style firmware version via a different command

/usr/libexec/firmwarecheckers/eficheck/eficheck --integrity-check
EFI Version: MBP114.88Z.0185.B00.1809171422
Primary allowlist version match found. No changes detected in primary hashes.

However according to this article - https://eclecticlight.co/2018/10/31/which-efi-firmware-should-your-mac-be-using-version-3/ this does not work on T2 equipped Macs.

It would therefore seem that if there is still to be a means of checking EFI versions the current script (and database) needs urgently updating.

High Sierra firmware update not found

Hardware Version : MacPro5,1
Boot ROM Version : MP51.0084.B00
SMC Version      : 1.39f11
Board-ID         : Mac-F221BEC8
OS Version       : 10.12.6
Build Number     : 16G29

EFI firmware version check:
[-] ATTENTION - Your Mac model (MacPro5,1) does not seem to have had any EFI updates released for it :'(

During the High Sierra install the firmware of the machine was updated. I went back to 10.12.6 Sierra but the new firmware should still be in place.

Thanks!

EFI not identified on Mac7,1?

I don't understand what this error-message means: "Can't get X86PlatformPlugin"

Log:

Enumerated system informaton (This data will be sent to the API in order to determine your correct EFI version):
2017-10-04 22:05:57.458 system_profiler[18506:1078164] platformPluginDictionary: Can't get X86PlatformPlugin, return value 0
2017-10-04 22:05:57.460 system_profiler[18506:1078164] platformPluginDictionary: Can't get X86PlatformPlugin, return value 0
Hashed SysUUID : 8156bb3a4413f6652078137070d340070be58c8669a09f9633f1a8a3f01abb64
Hardware Version : iMac7,1
Boot ROM Version : IM71.007A.B03
SMC Version : 1.20f4
Board-ID : Mac-XXXXXXXX
OS Version : 10.10.5
Build Number : 14F2511

[?] Do you want to continue and submit this request? [Y/N] Y

EFI firmware version check:
[-] ATTENTION - Your Mac model (iMac7,1) does not seem to have had any EFI updates released for it :'(

Highest build number check:
[+] SUCCESS - You are running the latest build number (14F2511) of the OS version you have installed (10.10.5)

Up-to-date OS check:
[+] SUCCESS - You are running the latest major/minor/micro version of the OS you have installed (10.10.5)

logout

Thanks, Harry

Support the 2018 MacBook Pros

There's currently no data for the 2018 MacBook Pros.

Running EFIgyLite_cli.py produces the following output:

$ ./EFIgyLite_cli.py 

	Hashed SysUUID   : ****
	Hardware Version : MacBookPro15,2
	EFI Version      : 15.6703.0
	SMC Version      : None
	Board-ID         : Mac-827FB448E656EC26
	OS Version       : 10.13.6
	Build Number     : 17G2208

[?] Do you want to continue and submit this request? [Y/N]  y

	# Results:
		[!] ERROR - Unknown model of Apple Mac 'MacBookPro15,2' given. Provide models in the form of 'MacPro6,1' for Mac Pro (Late 2013) (1533323738.95)

	Highest build number check:
		[-] ATTENTION - You are NOT running the latest release build number of your OS version (10.13.6). Your build number is 17G2208, the latest release build number is 17G65

	Up-to-date OS check:
		[+] SUCCESS - You are running the latest major/minor/micro version of the OS you have installed (10.13.6)

While I'm here, thank you for this research the API and paper are fantastic.

Incorrect results?

# Results:

EFI firmware version check:
	[-] ATTENTION - You are running an unexpected firmware version given the model of your system (MacBookPro9,2) and OS build you have installed (16G1114). Your firmware is MBP91.00D7.B00, the firmware we expected to see is MBPro91.00D7.B00.


Highest build number check:
	[-] ATTENTION - You are NOT running the latest release build number of your OS version (10.12.6). Your build number is 16G1114, the latest release build number is 16G1036

Using EFIgy with Mac management systems

It would be nice to have a way to interrogate an entire fleet of Macs via a Mac management system such as JAMF or MunkiReports.

As I see it this would be possible by first installing on each individual client both the python script and the required dependency of pyobjc, one could then via the chosen management/reporting solution run a script which runs the python client on each client.

However it would be preferable if there was a way to do this without having to install anything on the client Macs.

Is there any way to achieve this currently? Perhaps by running a script from the management system and passing the results as variables as part of a URL to https://check.efigy.io the results from the web app would then be scraped and stored in the management system.

Fatal error unknown error (_ssl.c:2825)

Sorry, my Python skills are weak. Here is the --debug.
On an iMac running Version 10.12.6 (16G29)

python EFIgyLite_cli.py --debug
DEBUG:main:[-] Certifi module not found, falling back to bundled cecert.pem file
DEBUG:main:[+] cacert file location: '/private/tmp/cacert.pem'

EFIgyLite API Information:
[-] Fatal error in EFIgyLite_cli. Exiting.....

Error:
unknown error (_ssl.c:2825)

Traceback (most recent call last):
File "EFIgyLite_cli.py", line 454, in
efigy_cli()
File "EFIgyLite_cli.py", line 244, in call
api_version = self.__make_api_get("/version")
File "EFIgyLite_cli.py", line 156, in __make_api_get
self.last_response = urllib2.urlopen(self.api_server+api_path, cafile=self.cacert_path)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 144, in urlopen
capath=capath)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 435, in create_default_context
context.load_verify_locations(cafile, capath, cadata)
SSLError: unknown error (_ssl.c:2825)

API Feature request

I like the /apple/latest_efi_firmware/ endpoint better than the /apple/oneshot endpoint (due to the complex JSON you need to POST)

It would be nice if we could send a GET request to the API with:

  • hw_ver
  • build number
  • Boot ROM Version (EFI)

and it would return JSON with something like: 'older', 'uptodate', 'newer' or 'notfound', so that we don't have to do the comparison of the EFI version on the client.

Newer than expected EFI firmware and build of 10.12.6.

I ran the current build of EFIgy, failed the first two tests, but found that I had newer than expected firmware and OS build. That's how I'm interpreting the results. I participated in Apple's AppleSeed beta-testing program for 10.12.6, which may be why.

Below are the full test results, followed by my interpretation notes.

EFIgyLite API Information:
API Version: 0.2
Updated On: Oct 3 2017, 16:44

Enumerated system informaton (This data will be sent to the API in order to determine your correct EFI version):
Hashed SysUUID : 6c300eb55df872a187804496eea3e07762c6a4c0bafb3b4b5a4dff0ad0a014ec
Hardware Version : MacBookPro11,3
Boot ROM Version : MBP112.0142.B00
SMC Version : 2.19f12
Board-ID : Mac-2BD1B31983FE1663
OS Version : 10.12.6
Build Number : 16G1023

[?] Do you want to continue and submit this request? [Y/N] y

EFI firmware version check:
[-] ATTENTION - You are running an unexpected firmware version given the model of your system (MacBookPro11,3) and OS build you have installed (16G1023). Your firmware MBP112.0142.B00, expected firmware MBP112.0138.B25.
Update your firmware!!

Highest build number check:
[-] ATTENTION - You are NOT running the latest build number of your OS version (10.12.6). Your build number is 16G1023, the latest build number is 16G29

Up-to-date OS check:
[+] SUCCESS - You are running the latest major/minor/micro version of the OS you have installed (10.12.6)

  1. My results show that my MacBookPro11,3 FAILed the EFI firmware test because it has NEWER firmware than was expected. Meanwhile, EFIgy tells me to ‘update’ my firmware. Wrong.

  2. The “Highest build number check” of 10.12.6 FAILed. This one is very odd. I’d been AppleSeed testing 10.12.6. Therefore, it would not be strange for me to have a different build of it on my MBP. However, I’d installed the FULL public installation of 10.12.6 anyway. That means I’m supposed to have the full, final, finished version of 10.12.6 on the MPB. So why do the test results say:

[-] ATTENTION - You are NOT running the latest build number of your OS version (10.12.6). Your build number is 16G1023, the latest build number is 16G29

And how do I interpret this FAIL? If I have build 16G1023, isn’t that well beyond the ‘latest’ 16G29? I think so!

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.