Skip to content

Implement Csp#361

Open
TheSyscall wants to merge 19 commits intomainfrom
cps
Open

Implement Csp#361
TheSyscall wants to merge 19 commits intomainfrom
cps

Conversation

@TheSyscall
Copy link
Copy Markdown

@TheSyscall TheSyscall commented Mar 23, 2026

Add a Csp class which represents the Content-Security-Policy header.

This new class can be used to manage the content security policy.
This class enforces default-src 'self' as a baseline for a secure web application.
The first nonce added to any directive is selected as THE nonce for the CSP.
Setting a nonce is not supported since a nonce could appear in any number of different directives.

@TheSyscall TheSyscall requested a review from Al2Klimov March 24, 2026 12:34
Al2Klimov

This comment was marked as resolved.

@TheSyscall TheSyscall requested a review from Al2Klimov March 25, 2026 11:43
Al2Klimov
Al2Klimov previously approved these changes Mar 31, 2026
Copy link
Copy Markdown
Member

@Al2Klimov Al2Klimov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested together with Icinga/icingaweb2#5477 (review).

@TheSyscall TheSyscall requested a review from Al2Klimov April 7, 2026 12:52
}
$parts = explode(' ', $directive, 2);
if (count($parts) < 2) {
continue;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider throwing InvalidArgumentException in this method whenever you encounter invalid syntax. The already called add() already throws InvalidArgumentException. You decide.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. This allows us to write better exception messages.

|| ! str_starts_with($policy, "'") && str_ends_with($policy, "'")
) {
throw new InvalidArgumentException(
"Quoted policy must be fully surrounded by single quotes. policy: $policy",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"Quoted policy must be fully surrounded by single quotes. policy: $policy",
"Quoted policy must be fully surrounded by single quotes. Policy: $policy",

Same below.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed

$parsedUrl = parse_url($url);

if (! isset($parsedUrl['host'])) {
throw new InvalidArgumentException("URL must specify a host. url: $url");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's an invalid argument, why it's allowed above? ('none', *)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good argument. Changed

$requestUri = ServerRequest::getUriFromGlobals();
if (
($scheme === null || $requestUri->getScheme() === $scheme)
&& $requestUri->getHost() === $parsedUrl['host']
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you aware that && has a higher precedence than ||?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes


$scheme = $parsedUrl['scheme'] ?? null;
if (in_array("'self'", $policies)) {
$requestUri = ServerRequest::getUriFromGlobals();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please tell me evaluateUrl() isn't actually needed at all. 🙈

Because, due to reverse proxies in front of IW2, $_SERVER is so unreliable that https://github.com/Icinga/icinga-sso-web/pull/3 JS had to resolve the absolute URL on the client side...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was implemented to support checking for user generated things navigation items and dashlets.
The idea was to give the users feedback on iframes that do not load or during the creation of new entries, specifically when using custom CSP.

return;
}

// scheme and scheme://*
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// scheme and scheme://*
// scheme: and scheme://*

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed comment

continue;
}

if ($scheme !== null && ($policy === $scheme . ':' || $policy === $scheme . '://')) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if ($scheme !== null && ($policy === $scheme . ':' || $policy === $scheme . '://')) {
if ($scheme !== null && ($policy === $scheme . ':' || $policy === $scheme . '://*')) {

(If I'm not mistaken.)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are not

return true;
}

// Note: https://*.example.com means https://example.com and https://sub.example.com
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then I'd explicitly check for the "."

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not possible for anything else to be there.
validatePolicy already prohibits this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants