Skip to content

Commit dc4e1bc

Browse files
johan-smitsctron
authored andcommitted
Add a nonce to the script elements. This allows CSP to pick
up the nonce value and include it into the header.
1 parent 54ddcb0 commit dc4e1bc

File tree

7 files changed

+32
-10
lines changed

7 files changed

+32
-10
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ once_cell = "1"
5151
open = "5"
5252
oxipng = "9"
5353
parking_lot = "0.12"
54+
rand = "0.8.5"
5455
remove_dir_all = "0.8"
5556
reqwest = { version = "0.12", default-features = false, features = ["stream", "trust-dns"] }
5657
sha2 = "0.10"

src/common/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ pub mod html_rewrite;
33

44
use anyhow::{anyhow, bail, Context, Result};
55
use async_recursion::async_recursion;
6+
use base64::{engine::general_purpose, Engine};
67
use console::Emoji;
78
use once_cell::sync::Lazy;
9+
use rand::RngCore;
810
use std::collections::HashSet;
911
use std::ffi::OsStr;
1012
use std::fmt::Debug;
@@ -262,3 +264,12 @@ pub fn path_to_href(path: impl AsRef<Path>) -> String {
262264
.collect::<Vec<_>>();
263265
path.join("/")
264266
}
267+
268+
/// A nonce random generator for script and style
269+
///
270+
/// https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce
271+
pub fn nonce() -> String {
272+
let mut buffer = [0u8; 16];
273+
rand::rngs::OsRng.fill_bytes(&mut buffer);
274+
general_purpose::STANDARD.encode(buffer)
275+
}

src/pipelines/inline.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use super::{trunk_id_selector, AssetFile, Attrs, TrunkAssetPipelineOutput, ATTR_HREF, ATTR_TYPE};
44
use crate::common::html_rewrite::Document;
5+
use crate::common::nonce;
56
use anyhow::{bail, Context, Result};
67
use std::path::PathBuf;
78
use std::str::FromStr;
@@ -125,9 +126,13 @@ impl InlineOutput {
125126
pub async fn finalize(self, dom: &mut Document) -> Result<()> {
126127
let html = match self.content_type {
127128
ContentType::Html | ContentType::Svg => self.content,
128-
ContentType::Css => format!(r#"<style>{}</style>"#, self.content),
129-
ContentType::Js => format!(r#"<script>{}</script>"#, self.content),
130-
ContentType::Module => format!(r#"<script type="module">{}</script>"#, self.content),
129+
ContentType::Css => format!(r#"<style nonce="{}">{}</style>"#, nonce(), self.content),
130+
ContentType::Js => format!(r#"<script nonce="{}">{}</script>"#, nonce(), self.content),
131+
ContentType::Module => format!(
132+
r#"<script type="module" nonce="{}">{}</script>"#,
133+
nonce(),
134+
self.content
135+
),
131136
};
132137

133138
dom.replace_with_html(&trunk_id_selector(self.id), &html)

src/pipelines/rust/output.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::super::trunk_id_selector;
22
use crate::{
3-
common::html_rewrite::Document,
3+
common::{html_rewrite::Document, nonce},
44
config::{CrossOrigin, RtcBuild},
55
pipelines::rust::{sri::SriBuilder, RustAppType},
66
};
@@ -134,6 +134,8 @@ window.{bindings} = bindings;
134134
false => ("", String::new()),
135135
};
136136

137+
let nonce = nonce();
138+
137139
// the code to fire the `TrunkApplicationStarted` event
138140
let fire = r#"
139141
dispatchEvent(new CustomEvent("TrunkApplicationStarted", {detail: {wasm}}));
@@ -142,7 +144,7 @@ dispatchEvent(new CustomEvent("TrunkApplicationStarted", {detail: {wasm}}));
142144
match &self.initializer {
143145
None => format!(
144146
r#"
145-
<script type="module">
147+
<script type="module" nonce="{nonce}">
146148
import init{import} from '{base}{js}';
147149
const wasm = await init('{base}{wasm}');
148150
@@ -152,7 +154,7 @@ const wasm = await init('{base}{wasm}');
152154
),
153155
Some(initializer) => format!(
154156
r#"
155-
<script type="module">
157+
<script type="module" nonce="{nonce}">
156158
{init}
157159
158160
import init{import} from '{base}{js}';

src/pipelines/sass.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use super::{
55
ATTR_INLINE, ATTR_NO_MINIFY,
66
};
77
use crate::{
8-
common::{self, dist_relative, html_rewrite::Document, target_path},
8+
common::{self, dist_relative, html_rewrite::Document, nonce, target_path},
99
config::RtcBuild,
1010
processing::integrity::{IntegrityType, OutputDigest},
1111
tools::{self, Application},
@@ -208,7 +208,8 @@ impl SassOutput {
208208
let html = match self.css_ref {
209209
// Insert the inlined CSS into a `<style>` tag.
210210
CssRef::Inline(css) => format!(
211-
r#"<style {attrs}>{css}</style>"#,
211+
r#"<style {attrs} nonce="{}">{css}</style>"#,
212+
nonce(),
212213
attrs = AttrWriter::new(&self.attrs, AttrWriter::EXCLUDE_CSS_INLINE)
213214
),
214215
// Link to the CSS file.

src/pipelines/tailwind_css.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use super::{
55
ATTR_INLINE, ATTR_NO_MINIFY,
66
};
77
use crate::{
8-
common::{self, dist_relative, html_rewrite::Document, target_path},
8+
common::{self, dist_relative, html_rewrite::Document, nonce, target_path},
99
config::RtcBuild,
1010
processing::integrity::{IntegrityType, OutputDigest},
1111
tools::{self, Application},
@@ -176,7 +176,8 @@ impl TailwindCssOutput {
176176
let html = match self.css_ref {
177177
// Insert the inlined CSS into a `<style>` tag.
178178
CssRef::Inline(css) => format!(
179-
r#"<style {attrs}>{css}</style>"#,
179+
r#"<style {attrs} nonce="{}">{css}</style>"#,
180+
nonce(),
180181
attrs = AttrWriter::new(&self.attrs, AttrWriter::EXCLUDE_CSS_INLINE)
181182
),
182183
// Link to the CSS file.

0 commit comments

Comments
 (0)