### CI/CD Integration Example for pgspot Source: https://context7.com/timescale/pgspot/llms.txt This bash script provides a template for integrating pgspot into a Continuous Integration/Continuous Deployment pipeline. It sets up the script to scan PostgreSQL migration files for security vulnerabilities. ```bash #!/bin/bash # ci-security-check.sh - PostgreSQL extension security scanner set -e MIGRATION_DIR="${1:-./migrations}" EXIT_CODE=0 echo "=== pgspot Security Analysis ===" ``` -------------------------------- ### pgspot Error Codes Reference Source: https://context7.com/timescale/pgspot/llms.txt This example shows how to programmatically list all available pgspot error and warning codes and their descriptions using Python. It also demonstrates how to get detailed information for a specific code using the command line. ```bash # View all available codes programmatically python3 -c " from pgspot.codes import codes for code, info in sorted(codes.items()): print(f'{code}: {info["title"]}') " # Output: # PS001: Unqualified operator # PS002: Unsafe function creation # PS003: SECURITY DEFINER function without explicit search_path # PS004: SECURITY DEFINER function with insecure search_path # PS005: Function without explicit search_path # PS006: Unsafe transform creation # PS007: Unsafe object creation # PS008: Unqualified alter sequence # PS009: Unsafe CASE expression # PS010: Unsafe schema creation # PS011: Unsafe sequence creation # PS012: Unsafe table creation # PS013: Unsafe foreign server creation # PS014: Unsafe index creation # PS015: Unsafe view creation # PS016: Unqualified function call # PS017: Unqualified object reference # PS018: Unsafe SET search_path # Get detailed info for specific code pgspot --explain PS009 ``` -------------------------------- ### Analyze PostgreSQL Extension Script with pgspot Source: https://context7.com/timescale/pgspot/llms.txt This example demonstrates a comprehensive analysis of a PostgreSQL extension script using pgspot, highlighting various security checks including function definitions, table creations, and search_path configurations. It also shows how to ignore specific warning codes. ```bash # Create a sample extension file cat > myext.sql << 'EOF' -- Extension setup CREATE SCHEMA myext; -- Safe: CREATE OR REPLACE in our own schema CREATE OR REPLACE FUNCTION myext.helper() RETURNS TEXT LANGUAGE SQL SET search_path = pg_catalog, pg_temp AS $$ SELECT 'helper'; $$ -- Safe: SECURITY DEFINER with proper search_path CREATE FUNCTION myext.admin_operation() RETURNS VOID SECURITY DEFINER SET search_path = pg_catalog, pg_temp LANGUAGE SQL AS $$ SELECT pg_catalog.now(); $$ -- Warning: Function without explicit search_path (PS005) CREATE FUNCTION myext.risky_func() RETURNS TEXT LANGUAGE SQL AS $$ SELECT pg_catalog.current_user; $$ -- Error: Unsafe table in public schema (PS012) CREATE TABLE IF NOT EXISTS public.myext_data(id int); EOF # Analyze the extension pgspot myext.sql # Output: # PS005: Function without explicit search_path: myext.risky_func() at line 18 # PS012: Unsafe table creation: myext_data at line 23 # # Errors: 1 Warnings: 1 Unknown: 0 # Analyze with specific ignores for known acceptable patterns pgspot --ignore PS005 myext.sql # Output: # PS012: Unsafe table creation: myext_data at line 23 # # Errors: 1 Warnings: 0 Unknown: 0 ``` -------------------------------- ### Check SQL for vulnerabilities and ignore specific errors Source: https://github.com/timescale/pgspot/blob/main/README.md This example demonstrates how to use pgspot to check a simple SQL statement for vulnerabilities and simultaneously ignore a specific error code (PS017). It shows the output including the detected vulnerability (PS012) and the summary counts. ```bash > pgspot --ignore PS017 <<<"CREATE TABLE IF NOT EXISTS foo();" PS012: Unsafe table creation: foo Errors: 1 Warnings: 0 Unknown: 0 ``` -------------------------------- ### Detect Unsafe SET search_path (PS018) Source: https://context7.com/timescale/pgspot/llms.txt Use pgspot to identify incorrectly quoted search_path settings that can lead to unintended schema resolution. The first example shows an unsafe setting, while the subsequent examples demonstrate correct configurations. ```bash # PS018 - Misquoted search_path pgspot < pgspot -h usage: pgspot [-h] [-a] [--proc-without-search-path PROC] [--summary-only] [--plpgsql | --no-plpgsql] [--explain EXPLAIN] [--ignore IGNORE] [--sql-accepting SQL_FN] [FILE ...] Spot vulnerabilities in PostgreSQL SQL scripts positional arguments: FILE file to check for vulnerabilities options: -h, --help show this help message and exit -a, --append append files before checking --proc-without-search-path PROC whitelist functions without explicit search_path --summary-only only print number of errors, warnings and unknowns --plpgsql, --no-plpgsql Analyze PLpgSQL code (default: True) --explain EXPLAIN Describe an error/warning code --ignore IGNORE Ignore error or warning code --ignore-lang LANG Ignore unknown procedural language --sql-accepting SQL_FN Specify one or more sql-accepting functions ``` -------------------------------- ### Analyze SQL-accepting functions Source: https://context7.com/timescale/pgspot/llms.txt Use the --sql-accepting flag to inform pgspot about functions that execute SQL strings, allowing for deeper analysis. ```bash # Specify that execute_sql accepts SQL as argument pgspot --sql-accepting execute_sql <&1); then echo "$output" EXIT_CODE=1 else # Check if there are any errors (not just warnings) if echo "$output" | grep -q "Errors: [1-9]"; then echo "$output" EXIT_CODE=1 else echo " PASSED" fi fi done if [ $EXIT_CODE -eq 0 ]; then echo "=== All security checks passed ===" else echo "=== Security issues found - please review ===" fi exit $EXIT_CODE # Usage: ./ci-security-check.sh ./sql/migrations ``` -------------------------------- ### Avoid CREATE OR REPLACE for Transforms Source: https://github.com/timescale/pgspot/blob/main/REFERENCE.md Use `CREATE ...` without `OR REPLACE` to prevent potential privilege escalation when creating transforms. This ensures consistency and security. ```sql CREATE OR REPLACE TRANSFORM rxid FOR LANGUAGE plpgsql(from sql with function f1); ``` ```sql CREATE TRANSFORM rxid FOR LANGUAGE plpgsql(from sql with function f1); ``` -------------------------------- ### Avoid Unsafe Schema Creation with IF NOT EXISTS Source: https://github.com/timescale/pgspot/blob/main/REFERENCE.md Use `CREATE SCHEMA` without `IF NOT EXISTS` to prevent attackers from pre-creating schemas and gaining ownership. This ensures that schema creation fails if the schema already exists, which is the desired secure behavior. ```sql CREATE SCHEMA IF NOT EXISTS my_schema; ``` ```sql CREATE SCHEMA my_schema; ``` -------------------------------- ### Secure Aggregate Creation with CREATE OR REPLACE Source: https://github.com/timescale/pgspot/blob/main/REFERENCE.md When using `CREATE OR REPLACE` for aggregates, ensure it's done within an extension-owned schema to prevent attackers from pre-creating objects and gaining ownership. Alternatively, use `CREATE` without `OR REPLACE`. ```sql CREATE OR REPLACE AGGREGATE public.aggregate(BASETYPE=my_type,SFUNC=agg_sfunc,STYPE=internal); ``` ```sql CREATE SCHEMA extension_schema; CREATE OR REPLACE AGGREGATE extension_schema.aggregate(BASETYPE=my_type,SFUNC=agg_sfunc,STYPE=internal); ``` ```sql CREATE AGGREGATE public.aggregate(SFUNC=agg_sfunc,STYPE=internal); ``` -------------------------------- ### Avoid `CREATE TABLE IF NOT EXISTS` in insecure schemas Source: https://github.com/timescale/pgspot/blob/main/REFERENCE.md Using `CREATE TABLE IF NOT EXISTS` in a schema not owned by the extension can allow an attacker to pre-create the table and gain ownership, leading to potential malicious code execution. Use `CREATE TABLE IF NOT EXISTS` in an extension-owned schema or `CREATE TABLE` without `IF NOT EXISTS`. ```sql CREATE TABLE IF NOT EXISTS public.test_table(col text); ``` ```sql CREATE SCHEMA extension_schema; CREATE TABLE IF NOT EXISTS extension_schema.test_table(col text); ``` ```sql CREATE TABLE public.test_table(col text); ``` -------------------------------- ### Analyze multiple files in append mode Source: https://context7.com/timescale/pgspot/llms.txt Use the -a or --append flag to maintain state across multiple files, which is useful for extension scripts. ```bash # Without append mode - each file is analyzed independently pgspot schema.sql functions.sql # With append mode - state is preserved across files pgspot -a schema.sql functions.sql ``` -------------------------------- ### Detecting unsafe function creation (PS002) Source: https://context7.com/timescale/pgspot/llms.txt pgspot flags CREATE OR REPLACE statements in schemas not owned by the extension to prevent function hijacking. ```bash # Unsafe - CREATE OR REPLACE in public schema pgspot <