Header Hardening Set
Sends standard hardening headers for content type, frame policy, referrer policy, and permissions policy.
Function signature
ogSendSecurityHeaders(options = array())
Categories
- Security
Parameters
optionsHeader policy options. Recognized keys: `content_security_policy`, `dry_run`, `extra_headers`.Return value
Short public-safe status message.
- headers
Compatibility
Existing function name and call order preserved; metadata signature corrected to source.
Minimum PHP version: 7.4
Security notes
Validate request method, identity, permissions, and caller-owned allowlists before use; keep secrets out of public output.
Code
<?php
/*
* Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
* Free for personal and internal use. Paid project use requires visible credit
* to Jeffery L. Paris. Corporate use requires a paid license fee unless a
* separate written license states otherwise.
*/
/**
* Sends standard hardening headers for content type, frame policy, referrer policy, and permissions policy.
*
* Primary use case: Global bootstrap/header layer.
* Typical inputs: site policy options.
* Typical output: sent headers.
*
* Implementation note: Do not send conflicting duplicate headers.
*
* @param array $options Header policy options.
* @return array Structured result data with success, message, and data keys.
*/
function ogSendSecurityHeaders($options = array()) {
$result = array(
'success' => false,
'message' => '',
'data' => array()
);
if (!is_array($options)) {
$options = array();
}
$headers = array(
'X-Content-Type-Options' => 'nosniff',
'X-Frame-Options' => 'SAMEORIGIN',
'Referrer-Policy' => 'strict-origin-when-cross-origin',
'Permissions-Policy' => 'geolocation=(), microphone=(), camera=(), payment=()'
);
if (!empty($options['content_security_policy'])) {
$headers['Content-Security-Policy'] = trim((string)$options['content_security_policy']);
}
if (!empty($options['extra_headers']) && is_array($options['extra_headers'])) {
foreach ($options['extra_headers'] as $header_name => $header_value) {
$header_name = trim((string)$header_name);
$header_value = trim((string)$header_value);
if (preg_match('/^[A-Za-z0-9-]+$/', $header_name) && strpos($header_value, "\n") === false && strpos($header_value, "\r") === false) {
$headers[$header_name] = $header_value;
}
}
}
$sent = array();
$dry_run = false;
if (!empty($options['dry_run'])) {
$dry_run = true;
}
if (!$dry_run && headers_sent()) {
$result['message'] = 'Headers were already sent.';
$result['data'] = array('headers' => $headers, 'sent' => $sent);
return $result;
}
foreach ($headers as $header_name => $header_value) {
if (!$dry_run) {
header($header_name . ': ' . $header_value, true);
}
$sent[] = $header_name;
}
$result['success'] = true;
if ($dry_run) {
$result['message'] = 'Security headers prepared.';
} else {
$result['message'] = 'Security headers sent.';
}
$result['data'] = array(
'headers' => $headers,
'sent' => $sent,
'dry_run' => $dry_run
);
return $result;
}