Product articles Redgate Flyway Callbacks and placeholders
Simple Safeguards for PowerShell…

Simple Safeguards for PowerShell Scripting with Flyway

This article demonstrates simple techniques to security-check any processes that use Bash or PowerShell scripts to automate database tasks, when using Flyway. These checks help ensure a script is trusted, hasn't been tampered with since creation, and doesn't contain commands commonly used with malicious intent. They add a valuable layer of protection, without sacrificing the power and flexibility that makes Flyway so effective.

Guest post

This is a guest post from Phil Factor. Phil Factor (real name withheld to protect the guilty), aka Database Mole, has 30 years of experience with database-intensive applications.

Despite having once been shouted at by a furious Bill Gates at an exhibition in the early 1980s, he has remained resolutely anonymous throughout his career.

He is a regular contributor to Simple Talk and SQLServerCentral.

Ensuring data security is a fundamental responsibility in IT management. Many organizations have failed to meet this obligation, and the resulting data leaks, identity theft, and fraud have led to public reprimands, legal action and fines. While attention often focuses on external threats, it’s important to remember that malicious activity also comes from within. On three occasions in my long IT career, I’ve seen developers caught in the act and escorted off the premises clutching their desk contents in a bin liner.

Even seemingly innocuous database scripts can be a gateway to exploitation, and a development database containing real data becomes a high-value target. It’s essential to periodically review development practices to ensure they meet current security standards.

Flyway makes database automation easy, allowing developers to write PowerShell, Java or Bash scripts that generate reports, run code reviews, or update documentation during migration runs. However, this flexibility makes it even more important to follow good scripting practices, especially if those scripts might have access to sensitive data or production systems. A compromised script might expose credentials, leak data, or silently alter production systems.

Flyway’s handling of SQL migrations includes built-in safeguards like checksum validation. However, external scripts, like PowerShell or Bash callbacks, aren’t subject to the same protection and so need a bit of extra care. Fortunately, with a few simple checks, such as static code searches for malicious patterns and script signing, we can guard against unauthorized changes to external scripts with the same tenacity that Flyway brings to validating SQL migrations.

Understanding the risks of scripted automation

Scripts like PowerShell or Bash run with the privileges of the user who executes them. This makes them powerful tools for automation but also means they can do damage if misused or compromised, especially if that user has access to sensitive data or Personally Identifiable Information (PID).

When used in database development, such scripts often have access to environment variables (including credentials), can read or modify files, and connect directly to databases. Even when using integrated authentication, they run in the user’s security context and can access anything the user can. A short block of code inserted into a PowerShell script by a malicious actor could lead to unauthorized data access and extraction, modification or deletion of critical database entries, or the insertion of malicious data or code into the database. If the release accidentally uses compromised PowerShell callbacks associated with development to update the production server (rather than merely the ‘dry run’ script) this will happen to the live data.

Flyway, like most automation tools, supports these scripting languages for task automation, and by adding a few lightweight security checks, teams can ensure these scripts remain safe, unchanged, and appropriately scoped.

Mitigation strategies: check, sign and verify scripts

I’ve no desire to explore here the many ways available to Ops teams to detect suspicious activity by ‘threat actors’ within the network. A corporate network is liable to be secure, but it nevertheless falls to development teams to find commonsense practical ways to check that it isn’t happening. Much of the work of source and configuration management aims to assist with this.

For any scripted approach to database development, there are two ways to be confident your scripts haven’t been tampered with or used to compromise security. First, we can use regular expressions (regex) to search for signs that a script contains commands or utilities often used with malicious intent. You’ll never cover every edge case, and a regex can’t reliably distinguish intent, but it can catch the most blatant issues. Once a script passes that check, your second job is to make sure it stays unchanged.

I’ll provide some PowerShell functions that offer a drop-in way to implement these checks and raise flags on potentially unsafe behavior or malicious access:

  • Find-SecurityConcerns – uses regex to inspect scripts for patterns common to malicious behavior (e.g., use of Invoke-WebRequest, Invoke-Expression, or base64 obfuscation).
  • Sign-Files and Verify-Files – sign trusted scripts with GPG and then verify those signatures before execution to ensure nothing in the callbacks has changed since they were initially validated and signed.

The GPG “Verify-Files” check can be done in a callback, such as a beforeMigrate, before a migration run. . The code you use would need to look for callbacks in all your Flyway ‘locations’ (the configuration item that provides a list of all directories to search for migration or callback files).

The integrity check (Find-SecurityConcerns) is designed to be run when you have many callback scripts that need to be checked through before being signed. It isn’t particularly suitable to be run in a callback.

A diagram of a migration process AI-generated content may be incorrect.

These checks don’t take much time to run and can be built into existing pipelines that use PowerShell scripting for automation. They attempt to provide the necessary oversight, without undermining the flexibility a tool like Flyway provides.

Signing files and then checking if they have changed

It is a good practice to validate the origin of the scripts before use. This is best done with cryptographic signatures. I like to sign files using GPG and then, before using them, check whether the signature is still valid. This verifies that the scripts are from a trusted source, as well as indicating if they have changed since they were signed.

As an alternative, it’s possible to verify the integrity of scripts using checksums, in the same way Flyway does for migration files. You can check the ‘last modified’ date of the file with a record of its value and, if it has changed, then run a checksum on the file to compare the result with your records.

Creating GPG signatures

The Sign-Files routine below can create either a detached GPG signature or a ‘clearsign’ signature. For our purposes, we use a detached signature, which stores the cryptographic signature in a separate file, rather than embedding it within the signed file as clearsign does. This keeps the original file unaltered, preserving its format and structure, while allowing you to verify its integrity and authenticity.

To validate a file with a detached signature, you need both the original file and its corresponding signature file (.gpg), using the correct GPG key to confirm that the file has not been tampered with since it was signed.

Verifying the file signatures

The Verify-Files PowerShell function checks whether each script has a valid detached signature using GPG. It can be incorporated into your deployment pipeline to validate script integrity at runtime.

Implementing a Script Integrity Check

In this step, we run automated checks on our callback scripts to catch obvious signs of malicious intent. The Find-SecurityConcerns PowerShell function performs a simple regex-based scan across script files, flagging potentially dangerous usage patterns (“Known Malicious Patterns”), like commands that can exfiltrate data, spawn processes, or obscure payloads through encoding.

Currently, it checks for the use of the following PowerShell commands and utilities:

  • Invoke-WebRequest: This command can be used to make HTTP requests, which may be used to exfiltrate data or download malicious payloads.
  • Invoke-Expression: Evaluates a string as a command. It can be exploited to execute arbitrary code, making it a potential vector for attacks.
  • curl and wget: These utilities can be used to download files from the internet, posing a risk for downloading malicious content.
  • scp: Secure copy command used for transferring files between hosts, which could be utilized for data exfiltration.
  • Start-Process: Starts a new process, which may be used to execute external programs with malicious intent.
  • Start-Job: Initiates a background job, potentially hiding malicious activities from immediate detection.
  • New-Object System.Net.WebClient: Creates a web client object that can download or upload data, posing a risk for data exfiltration or malicious downloads.
  • FromBase64String: Converts a Base64 encoded string to binary data, often used in obfuscation techniques to hide malicious payloads.
  • ConvertTo-SecureString: Converts a plain text string to a secure string, which might be used to handle sensitive data improperly.
  • [System.Text.Encoding]::UTF8.GetString: Decodes a byte array to a UTF-8 string, possibly used in obfuscation or data manipulation.
  • reg add and reg delete: These commands modify the Windows registry, potentially altering system configurations and permissions maliciously.

This isn’t a security audit, but it’s an effective way to spot common red flags across your script directories. With this function you can also whitelist files that you know to be safe, define custom patterns, and optionally log findings, making it well suited to run as part of a pre-deployment validation step.

Conclusion

However secure a corporate development environment may be, it makes sense to tackle security at every level. While integrating PowerShell scripts into Flyway migrations offers substantial benefits, it is part of the task of supervising development work to ensure that there are no security risks associated with it. Implementing a PowerShell function to check scripts for malicious alterations can significantly enhance the security of the database development environment. By proactively validating scripts, organizations can protect sensitive data, maintain user trust, and ensure the integrity of their database systems.

These simple techniques can help teams to security-check their Flyway automation processes, without losing the power and flexibility that makes a database migration tool like Flyway so effective.

 

Tools in this post

Redgate Flyway

DevOps for the Database

Find out more