How to List Python Packages Across All Mac, Windows, and Linux Devices
Using Kolide, you can easily view and query Python Packages across your fleet.
Introduction
Python is a popular programming language that often comes pre-installed on Mac, Windows, and Linux devices. In order for some Python programs to work, they must import third party libraries which are managed by a Python package manager.
Collection is done by enumerating common locations of Python packages and cannot detect custom installations like the ones generated with pyenv
The following file/folder patterns are searched:
/usr/local/lib/python%/dist-packages
/usr/local/lib/python%/site-packages
/opt/homebrew/lib/python%/dist-packages
/opt/homebrew/lib/python%/site-packages
/usr/lib/python%/dist-packages
/usr/lib/python%/site-package
/Library/Python/%/site-packages
/System/Library/Frameworks/Python.framework/Versions
- Paths in
[HU|HKLM]\SOFTWARE\Python\PythonCore\%\InstallPath
What Python Package Data Can Kolide Collect?
Kolide's endpoint agent bundles in osquery to efficiently collect Python Packages from Mac, Windows, and Linux devices in your fleet. Once collected, Kolide will parse, clean up, and centrally store this data in Inventory for your team to view, query, or export via API.
Kolide meticulously documents every piece of data returned so you can understand the results.
Python Packages Schema
Column | Type | Description | |
---|---|---|---|
id | Primary Key |
Unique identifier for the object |
|
device_id | Foreign Key |
Device associated with the entry |
|
device_name | Text |
Display name of the device associated with the entry |
|
author | Text |
Python package author |
|
directory | Text |
Directory where Python modules are located |
|
license | Text |
The author supplied license of the Python package |
|
name | Text |
Python package display name |
|
path | Text |
Path at which the module in the Python package resides |
|
summary | Text |
Python package-supplied summary |
|
version | Text |
The text representation of the version |
|
version_major | Bigint |
|
|
version_minor | Bigint |
|
|
version_patch | Bigint |
|
|
version_subpatch | Bigint |
|
|
version_pre | Text |
|
|
version_build | Text |
|
|
collected_at | Timestamp |
Time the row of data was first collected in the database |
|
updated_at | Timestamp |
Time the row of data was last changed in the database |
|
What Can You Do With This Information?
Kolide enables you to write your own queries against the data the agent collects. This allows you to build your own reports and API endpoints. For example, you can:
SELECT
device_name,
name AS package_name,
version
FROM device_python_packages WHERE name = 'numpy'
version | device_name | package_name |
---|---|---|
1.21.2 | crys | numpy |
1.16.0 | Michelles-MacBook-Air | numpy |
1.16.0 | dev-mac-pro | numpy |
1.15.3 | Lenovo-ThinkPad-X1 | numpy |
1.16.5 | focal-fossa-test-laptop | numpy |
1.17.4 | balthazar | numpy |
SELECT
COUNT(*) AS installations,
name,
version
FROM device_python_packages
WHERE name = 'pip'
GROUP BY name, version
-- Order by three pieces of semantic version
ORDER BY
CAST(SPLIT_PART(version,'.',1) AS int) DESC,
CAST(SPLIT_PART(version,'.',2) AS int) DESC,
-- Coalesce for the 3rd segment of semantic version in cases of 2 part version (eg. '18.1')
CAST(COALESCE(SPLIT_PART(version,'.',1),'0') AS int) DESC
name | version | installations |
---|---|---|
pip | 22.0.4 | 7 |
pip | 21.3.1 | 8 |
pip | 21.2.4 | 9 |
pip | 20.2.3 | 17 |
pip | 20.0.2 | 12 |
pip | 18.1 | 2 |
pip | 9.0.1 | 1 |
WITH
evil_python_packages(package_name) AS (
VALUES
('10Cent10'),('10Cent11'),('aryi'),('aws-login0tool'),('Ctx'),('DiscordSafety'),
('dpp-client'),('dpp-client1234'),('genesisbot'),('importantpackageimportant-package'),
('ipboards'),('learninglib'),('maratlib'),('maratlib1'),('matplatlib-plus'),
('mllearnlib'),('mplatlib'),('noblesse'),('noblesse2'),('noblessev2'),('owlmoon'),
('pptest'),('pymafka'),('pytagora'),('pytagora2'),('suffer'),('trrfab'),
('yandex-yt'),('yiffparty')
)
SELECT
device_name,
package_name,
version
FROM device_python_packages
JOIN evil_python_packages ON package_name = name;
package_name | version | device_name |
---|---|---|
noblessev2 | 2.1.1 | dover |
pytagora | 3.0.1.245 | Lenovo-ThinkPad-X1-Yoga |
yandex-yt | 1.0.0 | flame |
genesisbot | 0.5.1 | balthazar |
dpp-client | 1.0.1 | DESKTOP-FRC2567 |
Why Should I Collect Python Packages?
Since python is a widely used avenue for installing software, there is the potential for malicious actors to try and use it to distribute malware. Given the wide range of possible software that can be installed via python, it is important to regularly audit the list of installed packages on a machine.
Python packages are cataloged and tracked to allow:
- Reviewing installed packages to verify desired device configuration
- Discovering potential malicious software
- Identifying out-of-date or otherwise vulnerable software packages
End-User Privacy Consideration
Kolide practices Honest Security. We believe that data should be collected from end-user devices transparently and with privacy in mind.
Python package installations may reveal a partial list of the applications installed on your device. This could include software used for personal or sensitive reasons.
When you use Kolide to list Python Package data from end-user devices, Kolide gives the people using those devices insight into exactly what data is collected, the privacy implications, and who on the IT team can see the data. This all happens in our end-user privacy center which can be accessed directly by employees.