Many packages are zip files in a trenchcoat, and files can be dangerous.
OP lets you work with all sorts of packages. This can be helpful, and can be dangerous.
Lets think of things we can do with a package in terms of levels of risk:
It is generally safe to read files.
OP helps you with this: you can make anything into a package, and see what's inside.
OP provides an Open Platform for reading files and many ways to see what is inside and check the contents.
It also provides ways to inspect any code inside of the package (see mitigations):
Because Open Packages have both file data and content types, we can easily serve them up and show them in a browser.
IF the server does does now allow any other verb than -Get, and is run locally, this is fairly safe.
It is more safe if not running as root or admin, and only interacting with well-known content types.
Things start to get tricky when you can change a package.
We want to enable package editing, but do so as safely as we can.
OP can let you change packages with simple local PUT/POST/DELETE operations.
But only if you -Allow it. If we are running a local web server, we might -Allow it.
If we were running a remote web server with this flag on, we might be very foolish.
To start a local server that can edit a package, we can run:
$package |
Start-OpenPackage -Allow GET, HEAD, POST, PUT, DELETEPackages can contain code, and code can be run.
As Open Packages can be an Open Platform for applications, we can invoke from packages.
We would be very foolish if we did this with packages we do not trust.
In order to mitigate risks, Open Package provides several mitigations.
Open Packages contain metadata that most archives lack.
Each Open Package has a .PackageProperties collection.
This collection contains some useful information, such as the Identifier and Version.
It is trivial to get all of the hashes of files within a package.
If these hashes deviate, the package has been changed.
For example, if we wanted all of the hashes of a PowerShell gallery module, we can use:
$turtlePackage = Get-OpenPackage https://powershellgallery.com/Packages/Turtle
$turtlePackage.FileHashIn addition to reading hashes, we can also read any file within the package.
This allows us to scan packages.
Select-OpenPackage can be quite handy.
It allows us to select parts of a package by name, and allows us to search within package parts using:
- Regular Expressions
- XPath
- PowerShell AST Conditions
Additionally, each package has several properties to assist inspection.
For example, .package.json will return any package.json files in the package.
To assist in inspecting PowerShell packages, we can also look for specific Abstract Syntax Tree types:
.GetPowerShellCommandAstgets all commands referenced in a package.GetPowerShellParameterAstgets all parameters referenced in a package.GetPowerShellTypeAstgets all types referenced in a package
To see every property an OpenPackage provides, use Get-Member:
$openPackage = Import-Module OP -PassThru | OP
$openPackage | Get-MemberIn order to prevent package alteration, we can Lock-OpenPackage to get a read-only version of the package.
This will prevent alteration of the package, even if we choose the -Allow other http verbs in Start-OpenPackage
In order to prevent the loading of unwelcome packages or starting of unwelcome servers, many commands broadcast an event.
For example:
Get-OpenPackagewill be sent every time a package might be opened.Start-OpenPackagewill be sent every time a package might be run as a server.
These events can be used for logging of activity.
We can also use them to prevent some execution
Each event has a .MessageData dictionary.
To prevent a command from executing, just say no.
For example, we want to prevent Start-OpenPackage from launching any server, we can use:
Register-EngineEvent -SourceIdentifier Start-OpenPackage -Action {
Write-Host "Won't Start"
$event.MessageData['No'] = 'way'
}Adding any number of keys to an event's message will reject the event.
Those properties are:
NoDenyRejectRejected
If any of these properties are found, the command should stop processing.