LibWeb: Support Content-Security-Policy http-equiv state on meta element

This commit is contained in:
Luke Wilde 2024-11-26 14:04:49 +00:00 committed by Jelle Raaijmakers
commit e364443e60
Notes: github-actions[bot] 2025-05-23 14:40:23 +00:00
5 changed files with 60 additions and 0 deletions

View file

@ -206,6 +206,18 @@ SerializedPolicy Policy::serialize() const
};
}
void Policy::remove_directive(Badge<HTML::HTMLMetaElement>, FlyString const& name)
{
m_directives.remove_all_matching([&name](auto const& directive) {
return directive->name() == name;
});
}
void Policy::set_self_origin(Badge<HTML::HTMLMetaElement>, URL::Origin const& origin)
{
m_self_origin = origin;
}
void Policy::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);

View file

@ -54,6 +54,9 @@ public:
[[nodiscard]] GC::Ref<Policy> clone(GC::Heap&) const;
[[nodiscard]] SerializedPolicy serialize() const;
void remove_directive(Badge<HTML::HTMLMetaElement>, FlyString const& name);
void set_self_origin(Badge<HTML::HTMLMetaElement>, URL::Origin const& origin);
protected:
virtual void visit_edges(Cell::Visitor&) override;

View file

@ -79,6 +79,13 @@ HTML::SandboxingFlagSet PolicyList::csp_derived_sandboxing_flags() const
return HTML::SandboxingFlagSet {};
}
// https://w3c.github.io/webappsec-csp/#enforced
void PolicyList::enforce_policy(GC::Ref<Policy> policy)
{
// A policy is enforced or monitored for a global object by inserting it into the global objects CSP list.
m_policies.append(policy);
}
GC::Ref<PolicyList> PolicyList::clone(GC::Heap& heap) const
{
auto policy_list = heap.allocate<PolicyList>();

View file

@ -30,6 +30,9 @@ public:
[[nodiscard]] HTML::SandboxingFlagSet csp_derived_sandboxing_flags() const;
[[nodiscard]] GC::Ref<PolicyList> clone(GC::Heap&) const;
void enforce_policy(GC::Ref<Policy>);
[[nodiscard]] Vector<SerializedPolicy> serialize() const;
protected:

View file

@ -12,7 +12,10 @@
#include <LibWeb/CSS/PropertyID.h>
#include <LibWeb/CSS/StyleValues/CSSColorValue.h>
#include <LibWeb/CSS/StyleValues/ColorSchemeStyleValue.h>
#include <LibWeb/ContentSecurityPolicy/Directives/Names.h>
#include <LibWeb/ContentSecurityPolicy/PolicyList.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/HTML/HTMLHeadElement.h>
#include <LibWeb/HTML/HTMLMetaElement.h>
#include <LibWeb/Infra/CharacterTypes.h>
#include <LibWeb/Page/Page.h>
@ -143,6 +146,38 @@ void HTMLMetaElement::inserted()
document().set_pragma_set_default_language(language);
break;
}
case HttpEquivAttributeState::ContentSecurityPolicy: {
// https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-content-security-policy
// This pragma enforces a Content Security Policy on a Document. [CSP]
// 1. If the meta element is not a child of a head element, return.
if (!is<HTMLHeadElement>(parent()))
break;
// 2. If the meta element has no content attribute, or if that attribute's value is the empty string, then return.
auto input = get_attribute_value(AttributeNames::content);
if (input.is_empty())
break;
// 3. Let policy be the result of executing Content Security Policy's parse a serialized Content Security
// Policy algorithm on the meta element's content attribute's value, with a source of "meta", and a
// disposition of "enforce".
auto& realm = this->realm();
auto policy = ContentSecurityPolicy::Policy::parse_a_serialized_csp(realm.heap(), input, ContentSecurityPolicy::Policy::Source::Meta, ContentSecurityPolicy::Policy::Disposition::Enforce);
// 4. Remove all occurrences of the report-uri, frame-ancestors, and sandbox directives from policy.
policy->remove_directive({}, ContentSecurityPolicy::Directives::Names::ReportUri);
policy->remove_directive({}, ContentSecurityPolicy::Directives::Names::FrameAncestors);
policy->remove_directive({}, ContentSecurityPolicy::Directives::Names::Sandbox);
// FIXME: File spec issue stating the policy's self origin isn't set here.
policy->set_self_origin({}, document().origin());
// 5. Enforce the policy policy.
auto policy_list = ContentSecurityPolicy::PolicyList::from_object(realm.global_object());
VERIFY(policy_list);
policy_list->enforce_policy(policy);
break;
}
default:
dbgln("FIXME: Implement '{}' http-equiv state", get_attribute_value(AttributeNames::http_equiv));
break;