@socketsecurity/cli-with-sentry 1.0.90 → 1.0.91
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +64 -76
- package/dist/cli.js.map +1 -1
- package/dist/constants.js +4 -4
- package/dist/constants.js.map +1 -1
- package/dist/utils.js +2 -2
- package/dist/utils.js.map +1 -1
- package/external/@coana-tech/cli/cli.mjs +38654 -38600
- package/external/@coana-tech/cli/reachability-analyzers-cli.mjs +39 -32
- package/package.json +7 -7
- package/translations.json +32 -8
|
@@ -94989,16 +94989,17 @@ import { join as join13, resolve as resolve10, sep } from "path";
|
|
|
94989
94989
|
var { uniq: uniq5 } = import_lodash11.default;
|
|
94990
94990
|
var GoCodeAwareVulnerabilityScanner = class {
|
|
94991
94991
|
projectDir;
|
|
94992
|
-
|
|
94992
|
+
options;
|
|
94993
94993
|
name = "GOANA";
|
|
94994
|
-
constructor(projectDir,
|
|
94994
|
+
constructor(projectDir, options = {}) {
|
|
94995
94995
|
this.projectDir = projectDir;
|
|
94996
|
-
this.
|
|
94996
|
+
this.options = options;
|
|
94997
94997
|
}
|
|
94998
94998
|
async runAnalysis(vulns, heuristic, _analyzesAllVulns) {
|
|
94999
94999
|
logger.info("Started instantiating Go code-aware analysis");
|
|
95000
95000
|
if (!existsSync9(join13(this.projectDir, "go.mod")))
|
|
95001
95001
|
throw new Error("go.mod file not found in the project directory");
|
|
95002
|
+
const { timeoutInSeconds, memoryLimitInMB } = this.options;
|
|
95002
95003
|
const tmpDir = await createTmpDirectory("goana-output");
|
|
95003
95004
|
const vulnsOutputFile = join13(tmpDir, "vulns.json");
|
|
95004
95005
|
const diagnosticsOutputFile = join13(tmpDir, "diagnostics.json");
|
|
@@ -95008,7 +95009,10 @@ var GoCodeAwareVulnerabilityScanner = class {
|
|
|
95008
95009
|
-output-vulnerabilities ${vulnsOutputFile}
|
|
95009
95010
|
-output-diagnostics ${diagnosticsOutputFile}
|
|
95010
95011
|
-topk=4 ${heuristic.includeTests && "-tests"}
|
|
95011
|
-
${this.projectDir} ${vulnAccPaths}`, void 0, {
|
|
95012
|
+
${this.projectDir} ${vulnAccPaths}`, void 0, {
|
|
95013
|
+
timeout: timeoutInSeconds ? timeoutInSeconds * 1e3 : void 0,
|
|
95014
|
+
env: memoryLimitInMB ? { ...process.env, GOMEMLIMIT: `${memoryLimitInMB}MB` } : void 0
|
|
95015
|
+
});
|
|
95012
95016
|
if (error) {
|
|
95013
95017
|
logger.error("Error running Go code-aware analysis", error);
|
|
95014
95018
|
const timeout = !!error.killed;
|
|
@@ -95045,7 +95049,7 @@ ${stderr}`);
|
|
|
95045
95049
|
await rm4(tmpDir, { recursive: true, force: true });
|
|
95046
95050
|
}
|
|
95047
95051
|
}
|
|
95048
|
-
static async runOnDependencyChain([first2, ...rest], vuln,
|
|
95052
|
+
static async runOnDependencyChain([first2, ...rest], vuln, options = {}) {
|
|
95049
95053
|
assert4(first2.version);
|
|
95050
95054
|
const { Dir, GoMod } = JSON.parse(await runCommandResolveStdOut(cmdt`go mod download -json ${first2.packageName}@v${first2.version}`));
|
|
95051
95055
|
const projectDir = await createTmpDirectory("go-run-on-dependency-chain-");
|
|
@@ -95062,7 +95066,7 @@ ${stderr}`);
|
|
|
95062
95066
|
await runGoModTidy(projectDir);
|
|
95063
95067
|
}
|
|
95064
95068
|
const heuristic = GoanaHeuristics.NO_TESTS;
|
|
95065
|
-
const result = await new this(projectDir,
|
|
95069
|
+
const result = await new this(projectDir, options).runAnalysis([vuln], heuristic, true);
|
|
95066
95070
|
if (result.type === "error")
|
|
95067
95071
|
return {
|
|
95068
95072
|
error: result.message,
|
|
@@ -95078,7 +95082,7 @@ ${stderr}`);
|
|
|
95078
95082
|
await rm4(projectDir, { recursive: true, force: true });
|
|
95079
95083
|
}
|
|
95080
95084
|
}
|
|
95081
|
-
static async runOnAlreadyDownloadedPackages(packages, vuln,
|
|
95085
|
+
static async runOnAlreadyDownloadedPackages(packages, vuln, options = {}) {
|
|
95082
95086
|
for (const pkg of packages)
|
|
95083
95087
|
assert4(existsSync9(join13(pkg, "go.mod")), `${pkg} does not contain a go.mod file`);
|
|
95084
95088
|
const [app, ...dependencies] = packages;
|
|
@@ -95095,7 +95099,7 @@ ${stderr}`);
|
|
|
95095
95099
|
await runGoModTidy(projectDir);
|
|
95096
95100
|
}
|
|
95097
95101
|
const heuristic = GoanaHeuristics.NO_TESTS;
|
|
95098
|
-
const result = await new this(projectDir,
|
|
95102
|
+
const result = await new this(projectDir, options).runAnalysis([vuln], heuristic, true);
|
|
95099
95103
|
if (result.type === "error")
|
|
95100
95104
|
return {
|
|
95101
95105
|
error: result.message,
|
|
@@ -96170,7 +96174,10 @@ async function analyzePackages(ecosystem, packages, vulnerability, options) {
|
|
|
96170
96174
|
break;
|
|
96171
96175
|
case "GO":
|
|
96172
96176
|
analysisName = "Goana";
|
|
96173
|
-
result = await GoCodeAwareVulnerabilityScanner.runOnDependencyChain(packages, vulnerability,
|
|
96177
|
+
result = await GoCodeAwareVulnerabilityScanner.runOnDependencyChain(packages, vulnerability, {
|
|
96178
|
+
timeoutInSeconds: options?.timeoutInSeconds ?? 60,
|
|
96179
|
+
memoryLimitInMB: options?.memoryLimitInMB ?? 16384
|
|
96180
|
+
});
|
|
96174
96181
|
break;
|
|
96175
96182
|
case "RUST":
|
|
96176
96183
|
analysisName = "Rustica";
|
|
@@ -96215,7 +96222,10 @@ async function analyzeAlreadyInstalledPackages(ecosystem, packages, vulnerabilit
|
|
|
96215
96222
|
break;
|
|
96216
96223
|
case "GO":
|
|
96217
96224
|
analysisName = "Goana";
|
|
96218
|
-
result = await GoCodeAwareVulnerabilityScanner.runOnAlreadyDownloadedPackages(packages, vulnerability,
|
|
96225
|
+
result = await GoCodeAwareVulnerabilityScanner.runOnAlreadyDownloadedPackages(packages, vulnerability, {
|
|
96226
|
+
timeoutInSeconds: options?.timeoutInSeconds ?? 60,
|
|
96227
|
+
memoryLimitInMB: options?.memoryLimitInMB ?? 16384
|
|
96228
|
+
});
|
|
96219
96229
|
break;
|
|
96220
96230
|
case "RUST":
|
|
96221
96231
|
analysisName = "Rustica";
|
|
@@ -96270,7 +96280,7 @@ async function getVersion(analysisName) {
|
|
|
96270
96280
|
// dist/whole-program-code-aware-vulnerability-scanner/python/python-code-aware-vulnerability-scanner.js
|
|
96271
96281
|
var import_semver2 = __toESM(require_semver2(), 1);
|
|
96272
96282
|
var { omit, once: once3, pick, sortedUniq, uniqBy } = import_lodash14.default;
|
|
96273
|
-
var PythonCodeAwareVulnerabilityScanner = class
|
|
96283
|
+
var PythonCodeAwareVulnerabilityScanner = class {
|
|
96274
96284
|
state;
|
|
96275
96285
|
projectDir;
|
|
96276
96286
|
name = "MAMBALADE";
|
|
@@ -96295,9 +96305,7 @@ var PythonCodeAwareVulnerabilityScanner = class _PythonCodeAwareVulnerabilitySca
|
|
|
96295
96305
|
async runAnalysis(vulns, heuristic, analyzesAllVulns) {
|
|
96296
96306
|
if (!this.virtualEnvInfo)
|
|
96297
96307
|
throw new Error("Virtual environment not set up");
|
|
96298
|
-
|
|
96299
|
-
await this.setupMambalade();
|
|
96300
|
-
}
|
|
96308
|
+
this.mambaladeVenvPath ??= await setupMambalade();
|
|
96301
96309
|
logger.info("Started instantiating Python code-aware analysis");
|
|
96302
96310
|
logger.debug(`Trying to find files to analyze from projectDir: ${this.projectDir}`);
|
|
96303
96311
|
const { rootWorkingDir, reachabilityAnalysisOptions } = this.state;
|
|
@@ -96429,7 +96437,7 @@ ${msg}`;
|
|
|
96429
96437
|
logger.info(`Copying ${app} to ${projectDir}`);
|
|
96430
96438
|
await cp5(app, projectDir, { recursive: true });
|
|
96431
96439
|
fileMappings.set(projectDir, app);
|
|
96432
|
-
const scanner = new
|
|
96440
|
+
const scanner = new this({
|
|
96433
96441
|
rootWorkingDir: projectTmpDir,
|
|
96434
96442
|
reachabilityAnalysisOptions: options
|
|
96435
96443
|
}, projectTmpDir);
|
|
@@ -96608,22 +96616,6 @@ ${msg}`;
|
|
|
96608
96616
|
getVirtualEnvInfo() {
|
|
96609
96617
|
return this.virtualEnvInfo;
|
|
96610
96618
|
}
|
|
96611
|
-
async setupMambalade() {
|
|
96612
|
-
const venvDir = await createTmpDirectory("mambalade-venv");
|
|
96613
|
-
logger.info("Creating Mambalade virtual environment");
|
|
96614
|
-
const pythonInterpreter = await getPythonInterpreter();
|
|
96615
|
-
await exec(cmdt`${pythonInterpreter} -SIm venv ${venvDir}`);
|
|
96616
|
-
const mambaladeWheelsPath = join15(COANA_REPOS_PATH(), "mambalade", "dist");
|
|
96617
|
-
const wheelFiles = await readdir3(mambaladeWheelsPath);
|
|
96618
|
-
const mambaladeWheels = wheelFiles.filter((f2) => f2.endsWith(".whl")).map((f2) => join15(mambaladeWheelsPath, f2));
|
|
96619
|
-
if (mambaladeWheels.length === 0) {
|
|
96620
|
-
throw new Error(`No mambalade wheel files found in ${mambaladeWheelsPath}`);
|
|
96621
|
-
}
|
|
96622
|
-
logger.info(`Installing mambalade wheels: ${mambaladeWheels.join(", ")}`);
|
|
96623
|
-
await exec(cmdt`${venvDir}/bin/pip install --no-deps ${mambaladeWheels}`);
|
|
96624
|
-
this.mambaladeVenvPath = venvDir;
|
|
96625
|
-
logger.info("Mambalade virtual environment setup complete");
|
|
96626
|
-
}
|
|
96627
96619
|
// async [Symbol.asyncDispose]() {
|
|
96628
96620
|
async cleanup() {
|
|
96629
96621
|
if (this.virtualEnvInfo?.temporary) {
|
|
@@ -96684,6 +96676,21 @@ async function getPythonInterpreter() {
|
|
|
96684
96676
|
return "python3";
|
|
96685
96677
|
throw new Error(`No Python ${pythonVersionRequired} interpreter found`);
|
|
96686
96678
|
}
|
|
96679
|
+
async function setupMambalade() {
|
|
96680
|
+
const venvDir = await createTmpDirectory("mambalade-venv");
|
|
96681
|
+
logger.info("Creating Mambalade virtual environment");
|
|
96682
|
+
const pythonInterpreter = await getPythonInterpreter();
|
|
96683
|
+
await exec(cmdt`${pythonInterpreter} -SIm venv ${venvDir}`);
|
|
96684
|
+
const mambaladeWheelsPath = join15(COANA_REPOS_PATH(), "mambalade", "dist");
|
|
96685
|
+
const wheelFiles = await readdir3(mambaladeWheelsPath);
|
|
96686
|
+
const mambaladeWheels = wheelFiles.filter((f2) => f2.endsWith(".whl")).map((f2) => join15(mambaladeWheelsPath, f2));
|
|
96687
|
+
if (!mambaladeWheels.length)
|
|
96688
|
+
throw new Error(`No mambalade wheel files found in ${mambaladeWheelsPath}`);
|
|
96689
|
+
logger.info(`Installing mambalade wheels: ${mambaladeWheels.join(", ")}`);
|
|
96690
|
+
await exec(cmdt`${venvDir}/bin/pip install --no-deps ${mambaladeWheels}`);
|
|
96691
|
+
logger.info("Mambalade virtual environment setup complete");
|
|
96692
|
+
return venvDir;
|
|
96693
|
+
}
|
|
96687
96694
|
|
|
96688
96695
|
// dist/whole-program-code-aware-vulnerability-scanner/python/phantom-deps.js
|
|
96689
96696
|
var { uniq: uniq8 } = import_lodash15.default;
|
|
@@ -97208,7 +97215,7 @@ var GoAnalyzer = class {
|
|
|
97208
97215
|
const vulnerablePackages = uniq9(vulns.flatMap((v) => v.vulnerabilityAccessPaths.map((vap) => vap.split(":")[0])));
|
|
97209
97216
|
const irrelevantPackages = new Set(await getIrrelevantPackages(this.projectDir, vulnerablePackages));
|
|
97210
97217
|
const [unreachableVulns, otherVulns] = partition2(vulns, (v) => v.vulnerabilityAccessPaths.every((vap) => irrelevantPackages.has(vap.split(":")[0])));
|
|
97211
|
-
const res = otherVulns.length ? await analyzeWithHeuristics(this.state, otherVulns, [GoanaHeuristics.DEFAULT], false, new GoCodeAwareVulnerabilityScanner(this.projectDir, this.state.reachabilityAnalysisOptions
|
|
97218
|
+
const res = otherVulns.length ? await analyzeWithHeuristics(this.state, otherVulns, [GoanaHeuristics.DEFAULT], false, new GoCodeAwareVulnerabilityScanner(this.projectDir, this.state.reachabilityAnalysisOptions), analysisMetadataCollector, statusUpdater) : [];
|
|
97212
97219
|
if (unreachableVulns.length) {
|
|
97213
97220
|
const heuristicName = GoanaHeuristics.IMPORT_REACHABILITY.name;
|
|
97214
97221
|
const detectedOccurrences = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@socketsecurity/cli-with-sentry",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.91",
|
|
4
4
|
"description": "CLI for Socket.dev, includes Sentry error handling, otherwise identical to the regular `socket` package",
|
|
5
5
|
"homepage": "https://github.com/SocketDev/socket-cli",
|
|
6
6
|
"license": "MIT",
|
|
@@ -85,8 +85,8 @@
|
|
|
85
85
|
"@babel/preset-typescript": "7.27.1",
|
|
86
86
|
"@babel/runtime": "7.28.3",
|
|
87
87
|
"@biomejs/biome": "2.2.0",
|
|
88
|
-
"@coana-tech/cli": "14.11.
|
|
89
|
-
"@cyclonedx/cdxgen": "11.
|
|
88
|
+
"@coana-tech/cli": "14.11.13",
|
|
89
|
+
"@cyclonedx/cdxgen": "11.6.0",
|
|
90
90
|
"@dotenvx/dotenvx": "1.48.4",
|
|
91
91
|
"@eslint/compat": "1.3.2",
|
|
92
92
|
"@eslint/js": "9.33.0",
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
"@types/semver": "7.7.0",
|
|
127
127
|
"@types/which": "3.0.4",
|
|
128
128
|
"@types/yargs-parser": "21.0.3",
|
|
129
|
-
"@typescript-eslint/parser": "8.
|
|
129
|
+
"@typescript-eslint/parser": "8.40.0",
|
|
130
130
|
"@typescript/native-preview": "7.0.0-dev.20250529.1",
|
|
131
131
|
"@vitest/coverage-v8": "3.2.4",
|
|
132
132
|
"blessed": "0.1.81",
|
|
@@ -159,18 +159,18 @@
|
|
|
159
159
|
"npm-package-arg": "13.0.0",
|
|
160
160
|
"npm-run-all2": "8.0.4",
|
|
161
161
|
"open": "10.2.0",
|
|
162
|
-
"oxlint": "1.
|
|
162
|
+
"oxlint": "1.12.0",
|
|
163
163
|
"pony-cause": "2.1.11",
|
|
164
164
|
"registry-auth-token": "5.1.0",
|
|
165
165
|
"registry-url": "7.2.0",
|
|
166
|
-
"rollup": "4.46.
|
|
166
|
+
"rollup": "4.46.3",
|
|
167
167
|
"semver": "7.7.2",
|
|
168
168
|
"synp": "1.9.14",
|
|
169
169
|
"terminal-link": "2.1.1",
|
|
170
170
|
"tiny-updater": "3.5.3",
|
|
171
171
|
"trash": "9.0.0",
|
|
172
172
|
"type-coverage": "2.29.7",
|
|
173
|
-
"typescript-eslint": "8.
|
|
173
|
+
"typescript-eslint": "8.40.0",
|
|
174
174
|
"unplugin-purge-polyfills": "0.1.0",
|
|
175
175
|
"vitest": "3.2.4",
|
|
176
176
|
"which": "5.0.0",
|
package/translations.json
CHANGED
|
@@ -169,7 +169,7 @@
|
|
|
169
169
|
"emoji": "🎈"
|
|
170
170
|
},
|
|
171
171
|
"gitDependency": {
|
|
172
|
-
"description": "Contains a dependency which resolves to a remote git URL. Dependencies fetched from git URLs are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.",
|
|
172
|
+
"description": "Contains a dependency which resolves to a remote git URL. Dependencies fetched from git URLs are not immutable and can be used to inject untrusted code or reduce the likelihood of a reproducible install.",
|
|
173
173
|
"suggestion": "Publish the git dependency to npm or a private package repository and consume it from there.",
|
|
174
174
|
"title": "Git dependency",
|
|
175
175
|
"emoji": "🍣"
|
|
@@ -212,7 +212,7 @@
|
|
|
212
212
|
},
|
|
213
213
|
"highEntropyStrings": {
|
|
214
214
|
"description": "Contains high entropy strings. This could be a sign of encrypted data, leaked secrets or obfuscated code.",
|
|
215
|
-
"suggestion": "Please inspect these strings to check if
|
|
215
|
+
"suggestion": "Please inspect these strings to check if they are benign. Maintainers should clarify the purpose and existence of high entropy strings if there is a legitimate purpose.",
|
|
216
216
|
"title": "High entropy strings",
|
|
217
217
|
"emoji": "⚠️"
|
|
218
218
|
},
|
|
@@ -277,7 +277,7 @@
|
|
|
277
277
|
"emoji": "⚠️"
|
|
278
278
|
},
|
|
279
279
|
"malware": {
|
|
280
|
-
"description": "This package is malware.
|
|
280
|
+
"description": "This package is identified as malware. It has been flagged either by Socket's AI scanner and confirmed by our threat research team, or is listed as malicious in security databases and other sources.",
|
|
281
281
|
"title": "Known malware",
|
|
282
282
|
"suggestion": "It is strongly recommended that malware is removed from your codebase.",
|
|
283
283
|
"emoji": "☠️"
|
|
@@ -391,7 +391,7 @@
|
|
|
391
391
|
"emoji": "⚠️"
|
|
392
392
|
},
|
|
393
393
|
"noV1": {
|
|
394
|
-
"description": "Package is not semver
|
|
394
|
+
"description": "Package is not semver \u003E=1. This means it is not stable and does not support ^ ranges.",
|
|
395
395
|
"suggestion": "If the package sees any general use, it should begin releasing at version 1.0.0 or later to benefit from semver.",
|
|
396
396
|
"title": "No v1",
|
|
397
397
|
"emoji": "⚠️"
|
|
@@ -488,7 +488,7 @@
|
|
|
488
488
|
},
|
|
489
489
|
"suspiciousString": {
|
|
490
490
|
"description": "This package contains suspicious text patterns which are commonly associated with bad behavior.",
|
|
491
|
-
"suggestion": "The package code should be reviewed before installing",
|
|
491
|
+
"suggestion": "The package code should be reviewed before installing.",
|
|
492
492
|
"title": "Suspicious strings",
|
|
493
493
|
"emoji": "⚠️"
|
|
494
494
|
},
|
|
@@ -560,7 +560,7 @@
|
|
|
560
560
|
},
|
|
561
561
|
"unstableOwnership": {
|
|
562
562
|
"description": "A new collaborator has begun publishing package versions. Package stability and security risk may be elevated.",
|
|
563
|
-
"suggestion": "Try to reduce the
|
|
563
|
+
"suggestion": "Try to reduce the number of authors you depend on to reduce the risk to malicious actors gaining access to your supply chain. Packages should remove inactive collaborators with publishing rights from packages on npm.",
|
|
564
564
|
"title": "Unstable ownership",
|
|
565
565
|
"emoji": "⚠️"
|
|
566
566
|
},
|
|
@@ -571,8 +571,8 @@
|
|
|
571
571
|
"emoji": "⚠️"
|
|
572
572
|
},
|
|
573
573
|
"urlStrings": {
|
|
574
|
-
"description": "Package contains fragments of external URLs or IP addresses, which
|
|
575
|
-
"suggestion": "
|
|
574
|
+
"description": "Package contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.",
|
|
575
|
+
"suggestion": "Review all remote URLs to ensure they are intentional, pointing to trusted sources, and not being used for data exfiltration or loading untrusted code at runtime.",
|
|
576
576
|
"title": "URL strings",
|
|
577
577
|
"emoji": "⚠️"
|
|
578
578
|
},
|
|
@@ -587,6 +587,30 @@
|
|
|
587
587
|
"suggestion": "Packages should remove unnecessary zero width unicode characters and use their visible counterparts.",
|
|
588
588
|
"title": "Zero width unicode chars",
|
|
589
589
|
"emoji": "⚠️"
|
|
590
|
+
},
|
|
591
|
+
"chromePermission": {
|
|
592
|
+
"description": "This Chrome extension uses the '{permission}' permission.",
|
|
593
|
+
"suggestion": "Does this extensions need these permissions? Read more about what they mean at https://developer.chrome.com/docs/extensions/reference/permissions-list",
|
|
594
|
+
"title": "Chrome Extension Permission",
|
|
595
|
+
"emoji": "⚠️"
|
|
596
|
+
},
|
|
597
|
+
"chromeHostPermission": {
|
|
598
|
+
"description": "This Chrome extension requests access to '{host}'.",
|
|
599
|
+
"suggestion": "Review the host permission request and ensure it's necessary for the extension's functionality. Consider if the extension could work with more restrictive host permissions.",
|
|
600
|
+
"title": "Chrome Extension Host Permission",
|
|
601
|
+
"emoji": "⚠️"
|
|
602
|
+
},
|
|
603
|
+
"chromeWildcardHostPermission": {
|
|
604
|
+
"description": "This Chrome extension requests broad access to websites with the pattern '{host}'.",
|
|
605
|
+
"suggestion": "Wildcard host permissions like '*://*/*' give the extension access to all websites. This is a significant security risk and should be carefully reviewed. Consider if the extension could work with more restrictive host permissions.",
|
|
606
|
+
"title": "Chrome Extension Wildcard Host Permission",
|
|
607
|
+
"emoji": "⚠️"
|
|
608
|
+
},
|
|
609
|
+
"chromeContentScript": {
|
|
610
|
+
"description": "This Chrome extension includes a content script '{scriptFile}' that runs on websites matching '{matches}'.",
|
|
611
|
+
"suggestion": "Content scripts can modify web pages and access page content. Review the content script code to understand what it does on the websites it targets.",
|
|
612
|
+
"title": "Chrome Extension Content Script",
|
|
613
|
+
"emoji": "⚠️"
|
|
590
614
|
}
|
|
591
615
|
}
|
|
592
616
|
}
|