ploughshares/README_headers_testing.md

3.5 KiB

API Headers Testing Scripts

This directory contains scripts for testing the security headers and API compatibility of the Ploughshares application.

Scripts Overview

  1. test_headers.sh - Tests general HTTP headers for both UI and API endpoints
  2. test_api_curl.sh - Tests API endpoints with various curl commands and parameters
  3. test_api_headers.sh - Specifically analyzes security headers for API compatibility

Usage

All scripts accept an optional URL parameter. If not provided, they default to http://localhost:5005.

# Test against local development environment
./test_headers.sh

# Test against production
./test_headers.sh https://ploughshares.nixc.us

Security Headers Analysis

The scripts check for the following important headers:

Content Security Policy (CSP)

  • Ensures unsafe-inline and unsafe-eval are present for API compatibility
  • Verifies connect-src includes wildcard (*) for API access
  • Checks critical protections like object-src: 'none' and frame-ancestors: 'none'

CORS Headers

  • Access-Control-Allow-Origin
  • Access-Control-Allow-Methods
  • Access-Control-Allow-Headers

Resource Policies

  • Cross-Origin-Resource-Policy should be cross-origin for API endpoints
  • Cross-Origin-Resource-Policy should be same-origin for UI endpoints

Troubleshooting

If API requests are failing, check the following:

  1. CSP Issues: The Content-Security-Policy header must include:

    • 'unsafe-inline' and 'unsafe-eval' in script-src
    • * in connect-src
    • data: and blob: in appropriate directives
  2. CORS Issues: API endpoints must have:

    • Access-Control-Allow-Origin: * (or specific origins)
    • Access-Control-Allow-Methods with appropriate HTTP methods
    • Access-Control-Allow-Headers with at least Content-Type and Authorization
  3. Resource Policy Issues: API endpoints should have:

    • Cross-Origin-Resource-Policy: cross-origin

Current Configuration

The current configuration uses a permissive CSP that works for both UI and API routes:

csp = {
    'default-src': ["'self'", "'unsafe-inline'", "'unsafe-eval'", "data:", "blob:"],
    'script-src': ["'self'", "'unsafe-inline'", "'unsafe-eval'"] + ([f"'sha256-{CSP_JS_HASH}'"] if CSP_JS_HASH else []),
    'style-src': ["'self'", "'unsafe-inline'"] + 
                ([f"'sha256-{CSP_CSS_HASH}'"] if CSP_CSS_HASH else []) + 
                ([f"'sha256-{CSP_CUSTOM_CSS_HASH}'"] if CSP_CUSTOM_CSS_HASH else []),
    'img-src': ["'self'", "data:", "blob:"],
    'font-src': ["'self'", "data:"],
    'connect-src': ["'self'", "*"],
    'manifest-src': "'self'",
    'object-src': "'none'",  # Still explicitly disallow objects
    'frame-ancestors': "'none'",  # Still prevent framing
    'base-uri': "'self'",
    'form-action': "'self'"
}

CORS headers are added for API routes in an after_request handler:

@app.after_request
def add_api_headers(response):
    if request.path.startswith('/api/'):
        # Add CORS headers for API routes
        response.headers['Access-Control-Allow-Origin'] = '*'
        response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS'
        response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
        response.headers['Cross-Origin-Resource-Policy'] = 'cross-origin'
    else:
        # For UI routes, add additional security headers
        for header, value in additional_headers.items():
            response.headers[header] = value
    
    return response