javascript.chrome-remote-interface.security.audit.chrome-remote-interface-compilescript-injection.chrome-remote-interface-compilescript-injection

Author
2,176
Download Count*
License
If unverified user data can reach the compileScript
method it can result in Server-Side Request Forgery vulnerabilities
Run Locally
Run in CI
Defintion
rules:
- id: chrome-remote-interface-compilescript-injection
message: If unverified user data can reach the `compileScript` method it can
result in Server-Side Request Forgery vulnerabilities
metadata:
owasp:
- A10:2021 - Server-Side Request Forgery (SSRF)
cwe:
- "CWE-918: Server-Side Request Forgery (SSRF)"
category: security
technology:
- chrome-remote-interface
references:
- https://github.com/cyrus-and/chrome-remote-interface
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- vuln
likelihood: MEDIUM
impact: MEDIUM
confidence: MEDIUM
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
languages:
- javascript
- typescript
severity: WARNING
mode: taint
pattern-sources:
- patterns:
- pattern-inside: function ... (..., $ARG,...) {...}
- focus-metavariable: $ARG
pattern-sinks:
- patterns:
- pattern-either:
- pattern-inside: |
require('chrome-remote-interface');
...
- pattern-inside: |
import 'chrome-remote-interface';
...
- pattern-either:
- pattern: |
$RUNTIME.compileScript({expression: $SINK},...)
- pattern: |
$RUNTIME.evaluate({expression: $SINK},...)
- pattern: |
$PAGE.navigate({url: $SINK},...)
- pattern: |
$RUNTIME.printToPDF({headerTemplate: $SINK},...)
- pattern: |
$RUNTIME.printToPDF({footerTemplate: $SINK},...)
- pattern: |
$PAGE.setDocumentContent({html: $SINK},...)
- focus-metavariable: $SINK
Examples
chrome-remote-interface-compilescript-injection.js
const CDP = require('chrome-remote-interface');
async function example(userInput) {
let client;
try {
client = await CDP();
const {Runtime} = client;
const script1 = "document.querySelector('p').textContent"
// ok:chrome-remote-interface-compilescript-injection
const result = await Runtime.compileScript({expression: script1, sourceURL:"", persistScript:false, executionContextId:1});
// ruleid:chrome-remote-interface-compilescript-injection
const result2 = await Runtime.compileScript({expression: userInput, sourceURL:"", persistScript:false, executionContextId:1});
// ruleid:chrome-remote-interface-compilescript-injection
const result3 = await Runtime.compileScript({expression: 'var x = 123;' + userInput, sourceURL:"", persistScript:false, executionContextId:1});
} catch (err) {
console.error(err);
} finally {
if (client) {
await client.close();
}
}
}
async function example2(userInput) {
let client;
try {
client = await CDP();
const {Runtime} = client;
const script1 = "document.querySelector('p').textContent"
// ok:chrome-remote-interface-compilescript-injection
const result = await Runtime.evaluate({expression: script1});
// ruleid:chrome-remote-interface-compilescript-injection
const result2 = await Runtime.evaluate({expression: userInput});
// ruleid:chrome-remote-interface-compilescript-injection
const result3 = await Runtime.evaluate({expression: 'var x = 123;' + userInput});
} catch (err) {
console.error(err);
} finally {
if (client) {
await client.close();
}
}
}
async function example3(userInput) {
let client;
try {
client = await CDP();
const {Network, Page} = client;
Network.requestWillBeSent((params) => {
console.log(params.request.url);
});
await Network.enable();
await Page.enable();
// ok:chrome-remote-interface-compilescript-injection
await Page.navigate({url: 'https://github.com'});
// ruleid:chrome-remote-interface-compilescript-injection
await Page.navigate({url: userInput});
await Page.loadEventFired();
} catch (err) {
console.error(err);
} finally {
if (client) {
await client.close();
}
}
}
function example4(userInput) {
CDP(async (client) => {
const {Page} = client;
try {
await Page.enable();
await Page.navigate({url: 'https://github.com'});
await Page.loadEventFired();
// ok:chrome-remote-interface-compilescript-injection
const result = await Page.printToPDF({landscape: true, printBackground: true, headerTemplate: '<h1>Title</h1>'});
// ruleid:chrome-remote-interface-compilescript-injection
const result2 = await Page.printToPDF({landscape: true, printBackground: true, footerTemplate: userInput});
// ruleid:chrome-remote-interface-compilescript-injection
const result3 = await Page.printToPDF({landscape: true, printBackground: true, headerTemplate: '<h1>' + userInput + '</h1>'});
fs.writeFileSync('page.pdf', Buffer.from(data, 'base64'));
} catch (err) {
console.error(err);
} finally {
await client.close();
}
}).on('error', (err) => {
console.error(err);
});
}
function example5(userInput) {
CDP(async (client) => {
const {Page} = client;
try {
const {frameId} = await Page.navigate({url: 'about:blank'});
const html = '<html>test</html>';
// ok:chrome-remote-interface-compilescript-injection
await Page.setDocumentContent({frameId, html});
// ruleid:chrome-remote-interface-compilescript-injection
await Page.setDocumentContent({frameId, html: userInput});
} catch (err) {
console.error(err);
client.close();
}
}).on('error', (err) => {
console.error(err);
});
}
Short Link: https://sg.run/J9kj