diff --git a/.changeset/quiet-assets-repair.md b/.changeset/quiet-assets-repair.md
new file mode 100644
index 00000000000..b2fc82bd864
--- /dev/null
+++ b/.changeset/quiet-assets-repair.md
@@ -0,0 +1,5 @@
+---
+'@shopify/app': patch
+---
+
+Avoid flagging static theme asset script tags in app doctor.
diff --git a/packages/app/src/cli/services/app-doctor-engine/rules/liquid-rules.ts b/packages/app/src/cli/services/app-doctor-engine/rules/liquid-rules.ts
index 9a3840c7b0c..22865b74c1f 100644
--- a/packages/app/src/cli/services/app-doctor-engine/rules/liquid-rules.ts
+++ b/packages/app/src/cli/services/app-doctor-engine/rules/liquid-rules.ts
@@ -66,6 +66,7 @@ function liquidExecutableContextVisitor(file: SourceFile) {
const context = liquidOutputContext(ancestors)
if (context !== 'javascript' && context !== 'executable_attribute') return undefined
if (context === 'javascript' && filterNames(node).includes('json')) return undefined
+ if (isStaticScriptAssetUrl(node, ancestors)) return undefined
return [
makeLiquidIssue(
'UNSAFE_INNERHTML',
@@ -118,6 +119,14 @@ function attributeName(attribute: AttributeNode): string {
return attribute.name.map((part) => ('value' in part && typeof part.value === 'string' ? part.value : '')).join('')
}
+function isStaticScriptAssetUrl(node: LiquidVariableOutput, ancestors: LiquidHtmlNode[]): boolean {
+ const script = ancestors.find((ancestor) => ancestor.type === 'HtmlRawNode' && ancestor.name === 'script')
+ const attribute = ancestors.find((ancestor): ancestor is AttributeNode => ancestor.type.startsWith('Attr'))
+ if (!script || !attribute || attributeName(attribute).toLowerCase() !== 'src') return false
+
+ return /^(['"])(?:\\.|(?!\1)[^\\\n])+\1\s*\|\s*asset_url\s*$/.test(outputSource(node).trim())
+}
+
function outputSource(node: LiquidVariableOutput): string {
return typeof node.markup === 'string' ? node.markup : node.markup.rawSource
}
diff --git a/packages/app/src/cli/services/app-doctor-engine/tests/rule-analysis.test.ts b/packages/app/src/cli/services/app-doctor-engine/tests/rule-analysis.test.ts
index 9ffd21b8913..8c5eb680125 100644
--- a/packages/app/src/cli/services/app-doctor-engine/tests/rule-analysis.test.ts
+++ b/packages/app/src/cli/services/app-doctor-engine/tests/rule-analysis.test.ts
@@ -707,8 +707,16 @@ describe('Liquid public AST analysis', () => {
])
expect(ordinary.issues).toEqual([])
+ const staticAsset = scanLiquidSecurity([
+ source('', 'extensions/theme/blocks/chat.liquid'),
+ ])
+ expect(staticAsset.issues).toEqual([])
+
const script = scanLiquidSecurity([
- source('', 'extensions/theme/blocks/script.liquid'),
+ source(
+ '',
+ 'extensions/theme/blocks/script.liquid',
+ ),
])
expect(script.issues.map((finding) => finding.id)).toEqual(['LIQUID_UNSAFE_RENDER', 'UNSAFE_INNERHTML'])
})