Skip to content

Commit

Permalink
Merge branch 'observatory' into next
Browse files Browse the repository at this point in the history
  • Loading branch information
caugner committed Jan 31, 2024
2 parents 4a663e1 + 35b9d94 commit ec54441
Show file tree
Hide file tree
Showing 29 changed files with 1,894 additions and 22 deletions.
1 change: 1 addition & 0 deletions build/spas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ export async function buildSPAs(options: {

const SPAs = [
{ prefix: "play", pageTitle: "Playground | MDN" },
{ prefix: "observatory", pageTitle: "HTTP Observatory | MDN" },
{ prefix: "search", pageTitle: "Search" },
{ prefix: "plus", pageTitle: MDN_PLUS_TITLE },
{
Expand Down
4 changes: 4 additions & 0 deletions client/public/assets/observatory/assessment.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions client/public/assets/observatory/mdn.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions client/public/assets/observatory/scanning.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions client/public/assets/observatory/security.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions client/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const Translations = React.lazy(() => import("./translations"));
const WritersHomepage = React.lazy(() => import("./writers-homepage"));
const Sitemap = React.lazy(() => import("./sitemap"));
const Playground = React.lazy(() => import("./playground"));
const Observatory = React.lazy(() => import("./observatory"));

function Layout({ pageType, children }) {
const { pathname } = useLocation();
Expand Down Expand Up @@ -246,6 +247,14 @@ export function App(appProps: HydrationData) {
</LazyStandardLayout>
}
/>
<Route
path="observatory/*"
element={
<LazyStandardLayout>
<Observatory />
</LazyStandardLayout>
}
/>
<Route
path="/search"
element={
Expand Down
1 change: 1 addition & 0 deletions client/src/assets/icons/alert-circle-check.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions client/src/assets/icons/alert-circle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions client/src/assets/icons/check-circle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 1 addition & 2 deletions client/src/document/molecules/tooltip/index.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
@use "../../../ui/vars" as *;

.info-tooltip {
align-items: center;
cursor: pointer;
display: inline-flex;
position: relative;

.icon {
Expand All @@ -19,6 +17,7 @@
color: var(--text-primary);
font-size: smaller;
left: 50%;
margin-top: 0.25rem;
max-width: min(100vw, 20rem);
padding: 0.5rem;
position: absolute;
Expand Down
4 changes: 4 additions & 0 deletions client/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,7 @@ export function survey_rates(surveyKey: string): {
);
return { rateFrom, rateTill };
}

export const OBSERVATORY_API_URL =
process.env.REACT_APP_OBSERVATORY_API_URL ||
"https://stage.observatory.mdn.nonprod.webservices.mozgcp.net";
272 changes: 272 additions & 0 deletions client/src/observatory/csp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
import { InfoTooltip } from "../document/molecules/tooltip";
import { Icon } from "../ui/atoms/icon";
import { ObservatoryResult } from "./types";

export default function ObservatoryCSP({
result,
}: {
result: ObservatoryResult;
}) {
const policy = result.tests["content-security-policy"]?.policy;
return policy ? (
<>
<h2>Content Security Policy Analysis</h2>
<figure className="scroll-container">
<table className="fancy csp">
<thead>
<tr>
<th>Test</th>
<th>Pass</th>
<th>Info</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Blocks execution of inline JavaScript by not allowing{" "}
<code>'unsafe-inline'</code> inside <code>script-src</code>
</td>
<td>
<Icon
name={!policy.unsafeInline ? "check-circle" : "alert-circle"}
/>
<span className="visually-hidden">
{!policy.unsafeInline ? "Passed" : "Failed"}
</span>
</td>
<td>
<InfoTooltip>
Blocking the execution of inline JavaScript provides CSP's
strongest protection against cross-site scripting attacks.
Moving JavaScript to external files can also help make your
site more maintainable.
</InfoTooltip>
</td>
</tr>
<tr>
<td>
Blocks execution of JavaScript's <code>eval()</code> function by
not allowing <code>'unsafe-eval'</code> inside{" "}
<code>script-src</code>
</td>
<td>
<Icon
name={!policy.unsafeEval ? "check-circle" : "alert-circle"}
/>
<span className="visually-hidden">
{!policy.unsafeEval ? "Passed" : "Failed"}
</span>
</td>
<td>
<InfoTooltip>
Blocking the use of JavaScript's <code>eval()</code> function
can help prevent the execution of untrusted code.
</InfoTooltip>
</td>
</tr>
<tr>
<td>
Blocks execution of plug-ins, using <code>object-src</code>{" "}
restrictions
</td>
<td>
<Icon
name={!policy.unsafeObjects ? "check-circle" : "alert-circle"}
/>
<span className="visually-hidden">
{!policy.unsafeObjects ? "Passed" : "Failed"}
</span>
</td>
<td>
<InfoTooltip>
Blocking the execution of plug-ins via{" "}
<code>object-src 'none'</code> or as inherited from{" "}
<code>default-src</code> can prevent attackers from loading
Flash or Java in the context of your page.
</InfoTooltip>
</td>
</tr>
<tr>
<td>
Blocks inline styles by not allowing{" "}
<code>'unsafe-inline'</code> inside <code>style-src</code>
</td>
<td>
<Icon
name={
!policy.unsafeInlineStyle ? "check-circle" : "alert-circle"
}
/>
<span className="visually-hidden">
{!policy.unsafeInlineStyle ? "Passed" : "Failed"}
</span>
</td>
<td>
<InfoTooltip>
Blocking inline styles can help prevent attackers from
modifying the contents or appearance of your page. Moving
styles to external stylesheets can also help make your site
more maintainable.
</InfoTooltip>
</td>
</tr>
<tr>
<td>Blocks loading of active content over HTTP or FTP</td>
<td>
<Icon
name={
!policy.insecureSchemeActive
? "check-circle"
: "alert-circle"
}
/>
<span className="visually-hidden">
{!policy.insecureSchemeActive ? "Passed" : "Failed"}
</span>
</td>
<td>
<InfoTooltip>
Loading JavaScript or plugins can allow a man-in-the-middle to
execute arbitrary code or your website. Restricting your
policy and changing links to HTTPS can help prevent this.
</InfoTooltip>
</td>
</tr>
<tr>
<td>Blocks loading of passive content over HTTP or FTP</td>
<td>
<Icon
name={
!policy.insecureSchemePassive
? "check-circle"
: "alert-circle"
}
/>
<span className="visually-hidden">
{!policy.insecureSchemePassive ? "Passed" : "Failed"}
</span>
</td>
<td>
<InfoTooltip>
This site's Content Security Policy allows the loading of
passive content such as images or videos over insecure
protocols such as HTTP or FTP. Consider changing them to load
them over HTTPS.
</InfoTooltip>
</td>
</tr>
<tr>
<td>
Clickjacking protection, using <code>frame-ancestors</code>
</td>
<td>
<Icon
name={
policy.antiClickjacking ? "check-circle" : "alert-circle"
}
/>
<span className="visually-hidden">
{policy.antiClickjacking ? "Passed" : "Failed"}
</span>
</td>
<td>
<InfoTooltip>
The use of CSP's <code>frame-ancestors</code> directive offers
fine-grained control over who can frame your site.
</InfoTooltip>
</td>
</tr>
<tr>
<td>
Deny by default, using <code>default-src 'none'</code>
</td>
<td>
<Icon
name={policy.defaultNone ? "check-circle" : "alert-circle"}
/>
<span className="visually-hidden">
{policy.defaultNone ? "Passed" : "Failed"}
</span>
</td>
<td>
<InfoTooltip>
Denying by default using <code>default-src 'none'</code>can
ensure that your Content Security Policy doesn't allow the
loading of resources you didn't intend to allow.
</InfoTooltip>
</td>
</tr>
<tr>
<td>
Restricts use of the <code>&lt;base&gt;</code> tag by using{" "}
<code>base-uri 'none'</code>, <code>base-uri 'self'</code>, or
specific origins
</td>
<td>
<Icon
name={
!policy.insecureBaseUri ? "check-circle" : "alert-circle"
}
/>
<span className="visually-hidden">
{!policy.insecureBaseUri ? "Passed" : "Failed"}
</span>
</td>
<td>
<InfoTooltip>
The <code>base</code> tag can be used to trick your site into
loading scripts from untrusted origins.
</InfoTooltip>
</td>
</tr>
<tr>
<td>
Restricts where <code>&lt;form&gt;</code> contents may be
submitted by using <code>form-action 'none'</code>,{" "}
<code>form-action 'self'</code>, or specific URIs
</td>
<td>
<Icon
name={
!policy.insecureFormAction ? "check-circle" : "alert-circle"
}
/>
<span className="visually-hidden">
{!policy.insecureFormAction ? "Passed" : "Failed"}
</span>
</td>
<td>
<InfoTooltip>
Malicious JavaScript or content injection could modify where
sensitive form data is submitted to or create additional forms
for data exfiltration.
</InfoTooltip>
</td>
</tr>
<tr>
<td>
Uses CSP3's <code>'strict-dynamic'</code> directive to allow
dynamic script loading (optional)
</td>
{policy.strictDynamic ? (
<td>
<Icon name="check-circle" />
<span className="visually-hidden">"Passed"</span>
</td>
) : (
<td>-</td>
)}
<td>
<InfoTooltip>
<code>'strict-dynamic'</code> lets you use a JavaScript shim
loader to load all your site's JavaScript dynamically, without
having to track <code>script-src</code> origins.
</InfoTooltip>
</td>
</tr>
</tbody>
</table>
</figure>
</>
) : null;
}
Loading

0 comments on commit ec54441

Please sign in to comment.