securenow 5.10.2 → 5.11.1
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/CONSUMING-APPS-GUIDE.md +30 -0
- package/NPM_README.md +65 -0
- package/README.md +13 -0
- package/cidr.js +83 -0
- package/cli/auth.js +208 -208
- package/cli/config.js +117 -117
- package/cli/firewall.js +81 -0
- package/cli/fp.js +638 -0
- package/cli/security.js +4 -8
- package/cli.js +28 -1
- package/console-instrumentation.js +147 -147
- package/docs/ALL-FRAMEWORKS-QUICKSTART.md +40 -1
- package/docs/API-KEYS-GUIDE.md +215 -0
- package/docs/ENVIRONMENT-VARIABLES.md +880 -697
- package/docs/FIREWALL-GUIDE.md +388 -0
- package/docs/INDEX.md +8 -1
- package/firewall-cloud.js +212 -0
- package/firewall-iptables.js +139 -0
- package/firewall-tcp.js +58 -0
- package/firewall.js +235 -0
- package/free-trial-banner.js +174 -174
- package/nextjs-auto-capture.js +199 -199
- package/nextjs-middleware.js +186 -186
- package/nextjs-wrapper.js +158 -158
- package/nextjs.js +22 -2
- package/nuxt-server-plugin.mjs +400 -400
- package/package.json +30 -3
- package/resolve-ip.js +77 -0
- package/tracing.js +31 -56
- package/web-vite.mjs +239 -239
package/free-trial-banner.js
CHANGED
|
@@ -1,174 +1,174 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Free Trial Banner — auto-injects a visible "Testing Environment" banner
|
|
5
|
-
* into HTML pages served by apps using the SecureNow free trial instance.
|
|
6
|
-
*
|
|
7
|
-
* Opt-out: set SECURENOW_HIDE_BANNER=1
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const FREETRIAL_HOST = 'freetrial.securenow.ai';
|
|
11
|
-
|
|
12
|
-
function isFreeTrial(endpointBase) {
|
|
13
|
-
return !!endpointBase && endpointBase.includes(FREETRIAL_HOST);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/* istanbul ignore next — runs in browser, not Node */
|
|
17
|
-
function _bannerClientCode() {
|
|
18
|
-
if (window.__snBanner) return;
|
|
19
|
-
window.__snBanner = 1;
|
|
20
|
-
|
|
21
|
-
function create() {
|
|
22
|
-
if (document.getElementById('sn-ft-banner')) return;
|
|
23
|
-
|
|
24
|
-
var d = document.createElement('div');
|
|
25
|
-
d.id = 'sn-ft-banner';
|
|
26
|
-
d.style.cssText =
|
|
27
|
-
'position:fixed;top:0;left:0;right:0;z-index:2147483647;' +
|
|
28
|
-
'background:#FEF3CD;color:#856404;padding:10px 16px;' +
|
|
29
|
-
'font-family:system-ui,-apple-system,sans-serif;font-size:13px;' +
|
|
30
|
-
'text-align:center;border-bottom:2px solid #FFE69C;' +
|
|
31
|
-
'display:flex;align-items:center;justify-content:center;gap:6px;' +
|
|
32
|
-
'box-shadow:0 2px 8px rgba(0,0,0,0.12)';
|
|
33
|
-
|
|
34
|
-
var icon = document.createElement('span');
|
|
35
|
-
icon.textContent = '\u26a0\ufe0f';
|
|
36
|
-
d.appendChild(icon);
|
|
37
|
-
|
|
38
|
-
var msg = document.createElement('span');
|
|
39
|
-
var strong = document.createElement('strong');
|
|
40
|
-
strong.textContent = 'Testing Environment:';
|
|
41
|
-
msg.appendChild(strong);
|
|
42
|
-
msg.appendChild(document.createTextNode(
|
|
43
|
-
' Only add test applications. For production usage, '
|
|
44
|
-
));
|
|
45
|
-
|
|
46
|
-
var link = document.createElement('a');
|
|
47
|
-
link.href = 'https://app.securenow.ai/dashboard/settings/instances';
|
|
48
|
-
link.target = '_blank';
|
|
49
|
-
link.rel = 'noopener';
|
|
50
|
-
link.style.cssText = 'color:#664D03;font-weight:600;text-decoration:underline';
|
|
51
|
-
link.textContent = 'create a new production instance';
|
|
52
|
-
msg.appendChild(link);
|
|
53
|
-
msg.appendChild(document.createTextNode('.'));
|
|
54
|
-
d.appendChild(msg);
|
|
55
|
-
|
|
56
|
-
var upgradeBtn = document.createElement('a');
|
|
57
|
-
upgradeBtn.href = 'https://app.securenow.ai/dashboard/settings/instances';
|
|
58
|
-
upgradeBtn.target = '_blank';
|
|
59
|
-
upgradeBtn.rel = 'noopener';
|
|
60
|
-
upgradeBtn.textContent = '\u26a1 Upgrade';
|
|
61
|
-
upgradeBtn.style.cssText =
|
|
62
|
-
'display:inline-flex;align-items:center;gap:4px;' +
|
|
63
|
-
'background:#D97706;color:#fff;padding:4px 12px;border-radius:4px;' +
|
|
64
|
-
'font-size:12px;font-weight:600;text-decoration:none;margin-left:10px;' +
|
|
65
|
-
'white-space:nowrap;transition:background 0.15s';
|
|
66
|
-
upgradeBtn.onmouseover = function () { upgradeBtn.style.background = '#B45309'; };
|
|
67
|
-
upgradeBtn.onmouseout = function () { upgradeBtn.style.background = '#D97706'; };
|
|
68
|
-
d.appendChild(upgradeBtn);
|
|
69
|
-
|
|
70
|
-
var close = document.createElement('button');
|
|
71
|
-
close.textContent = '\u00d7';
|
|
72
|
-
close.style.cssText =
|
|
73
|
-
'background:none;border:none;color:#856404;font-size:18px;' +
|
|
74
|
-
'cursor:pointer;margin-left:12px;padding:0 4px;line-height:1';
|
|
75
|
-
close.onclick = function () { d.style.display = 'none'; };
|
|
76
|
-
d.appendChild(close);
|
|
77
|
-
|
|
78
|
-
document.body.prepend(d);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (document.readyState === 'loading') {
|
|
82
|
-
document.addEventListener('DOMContentLoaded', create);
|
|
83
|
-
} else {
|
|
84
|
-
create();
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
var BANNER_SCRIPT =
|
|
89
|
-
'<script data-securenow-banner>(' +
|
|
90
|
-
_bannerClientCode.toString() +
|
|
91
|
-
')()</scr' + 'ipt>';
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Monkey-patch http.ServerResponse to inject the banner script into HTML
|
|
95
|
-
* responses. Searches for `<head...>` and inserts the script right after it.
|
|
96
|
-
* Skips compressed responses and non-HTML content types.
|
|
97
|
-
*/
|
|
98
|
-
function patchHttpForBanner() {
|
|
99
|
-
try {
|
|
100
|
-
var http = require('http');
|
|
101
|
-
var _origWrite = http.ServerResponse.prototype.write;
|
|
102
|
-
var _origEnd = http.ServerResponse.prototype.end;
|
|
103
|
-
|
|
104
|
-
function maybeInject(res, chunk) {
|
|
105
|
-
if (res._snBannerDone || !chunk) return chunk;
|
|
106
|
-
|
|
107
|
-
if (res._snIsHtml === undefined) {
|
|
108
|
-
var ct = res.getHeader('content-type');
|
|
109
|
-
var ce = res.getHeader('content-encoding');
|
|
110
|
-
var csp = res.getHeader('content-security-policy');
|
|
111
|
-
res._snIsHtml = !!(ct && String(ct).includes('text/html') && !ce && !csp);
|
|
112
|
-
}
|
|
113
|
-
if (!res._snIsHtml) {
|
|
114
|
-
res._snBannerDone = true;
|
|
115
|
-
return chunk;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
var isStr = typeof chunk === 'string';
|
|
119
|
-
var isBuf = Buffer.isBuffer(chunk);
|
|
120
|
-
if (!isStr && !isBuf) return chunk;
|
|
121
|
-
|
|
122
|
-
var str = isStr ? chunk : chunk.toString('utf8');
|
|
123
|
-
var headIdx = str.indexOf('<head');
|
|
124
|
-
if (headIdx === -1) return chunk;
|
|
125
|
-
|
|
126
|
-
var gt = str.indexOf('>', headIdx);
|
|
127
|
-
if (gt === -1) return chunk;
|
|
128
|
-
|
|
129
|
-
res._snBannerDone = true;
|
|
130
|
-
var result = str.slice(0, gt + 1) + BANNER_SCRIPT + str.slice(gt + 1);
|
|
131
|
-
return isStr ? result : Buffer.from(result, 'utf8');
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
http.ServerResponse.prototype.write = function (chunk, encoding, cb) {
|
|
135
|
-
try {
|
|
136
|
-
var modified = maybeInject(this, chunk);
|
|
137
|
-
if (modified !== chunk) {
|
|
138
|
-
var enc = typeof encoding === 'function' ? 'utf8' : encoding;
|
|
139
|
-
var callback = typeof encoding === 'function' ? encoding : cb;
|
|
140
|
-
try {
|
|
141
|
-
if (this.getHeader('content-length')) {
|
|
142
|
-
this.setHeader('content-length', Buffer.byteLength(modified));
|
|
143
|
-
}
|
|
144
|
-
} catch (_) { /* headers already sent */ }
|
|
145
|
-
return _origWrite.call(this, modified, enc, callback);
|
|
146
|
-
}
|
|
147
|
-
} catch (_) { /* never break the app */ }
|
|
148
|
-
return _origWrite.call(this, chunk, encoding, cb);
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
http.ServerResponse.prototype.end = function (chunk, encoding, cb) {
|
|
152
|
-
try {
|
|
153
|
-
var modified = maybeInject(this, chunk);
|
|
154
|
-
if (modified !== chunk) {
|
|
155
|
-
var enc = typeof encoding === 'function' ? 'utf8' : encoding;
|
|
156
|
-
var callback = typeof encoding === 'function' ? encoding : cb;
|
|
157
|
-
try {
|
|
158
|
-
if (this.getHeader('content-length')) {
|
|
159
|
-
this.setHeader('content-length', Buffer.byteLength(modified));
|
|
160
|
-
}
|
|
161
|
-
} catch (_) { /* headers already sent */ }
|
|
162
|
-
return _origEnd.call(this, modified, enc, callback);
|
|
163
|
-
}
|
|
164
|
-
} catch (_) { /* never break the app */ }
|
|
165
|
-
return _origEnd.call(this, chunk, encoding, cb);
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
console.log('[securenow] Free trial banner injection enabled');
|
|
169
|
-
} catch (err) {
|
|
170
|
-
console.warn('[securenow] Could not setup free trial banner:', err.message);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
module.exports = { isFreeTrial, patchHttpForBanner, BANNER_SCRIPT };
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Free Trial Banner — auto-injects a visible "Testing Environment" banner
|
|
5
|
+
* into HTML pages served by apps using the SecureNow free trial instance.
|
|
6
|
+
*
|
|
7
|
+
* Opt-out: set SECURENOW_HIDE_BANNER=1
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const FREETRIAL_HOST = 'freetrial.securenow.ai';
|
|
11
|
+
|
|
12
|
+
function isFreeTrial(endpointBase) {
|
|
13
|
+
return !!endpointBase && endpointBase.includes(FREETRIAL_HOST);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/* istanbul ignore next — runs in browser, not Node */
|
|
17
|
+
function _bannerClientCode() {
|
|
18
|
+
if (window.__snBanner) return;
|
|
19
|
+
window.__snBanner = 1;
|
|
20
|
+
|
|
21
|
+
function create() {
|
|
22
|
+
if (document.getElementById('sn-ft-banner')) return;
|
|
23
|
+
|
|
24
|
+
var d = document.createElement('div');
|
|
25
|
+
d.id = 'sn-ft-banner';
|
|
26
|
+
d.style.cssText =
|
|
27
|
+
'position:fixed;top:0;left:0;right:0;z-index:2147483647;' +
|
|
28
|
+
'background:#FEF3CD;color:#856404;padding:10px 16px;' +
|
|
29
|
+
'font-family:system-ui,-apple-system,sans-serif;font-size:13px;' +
|
|
30
|
+
'text-align:center;border-bottom:2px solid #FFE69C;' +
|
|
31
|
+
'display:flex;align-items:center;justify-content:center;gap:6px;' +
|
|
32
|
+
'box-shadow:0 2px 8px rgba(0,0,0,0.12)';
|
|
33
|
+
|
|
34
|
+
var icon = document.createElement('span');
|
|
35
|
+
icon.textContent = '\u26a0\ufe0f';
|
|
36
|
+
d.appendChild(icon);
|
|
37
|
+
|
|
38
|
+
var msg = document.createElement('span');
|
|
39
|
+
var strong = document.createElement('strong');
|
|
40
|
+
strong.textContent = 'Testing Environment:';
|
|
41
|
+
msg.appendChild(strong);
|
|
42
|
+
msg.appendChild(document.createTextNode(
|
|
43
|
+
' Only add test applications. For production usage, '
|
|
44
|
+
));
|
|
45
|
+
|
|
46
|
+
var link = document.createElement('a');
|
|
47
|
+
link.href = 'https://app.securenow.ai/dashboard/settings/instances';
|
|
48
|
+
link.target = '_blank';
|
|
49
|
+
link.rel = 'noopener';
|
|
50
|
+
link.style.cssText = 'color:#664D03;font-weight:600;text-decoration:underline';
|
|
51
|
+
link.textContent = 'create a new production instance';
|
|
52
|
+
msg.appendChild(link);
|
|
53
|
+
msg.appendChild(document.createTextNode('.'));
|
|
54
|
+
d.appendChild(msg);
|
|
55
|
+
|
|
56
|
+
var upgradeBtn = document.createElement('a');
|
|
57
|
+
upgradeBtn.href = 'https://app.securenow.ai/dashboard/settings/instances';
|
|
58
|
+
upgradeBtn.target = '_blank';
|
|
59
|
+
upgradeBtn.rel = 'noopener';
|
|
60
|
+
upgradeBtn.textContent = '\u26a1 Upgrade';
|
|
61
|
+
upgradeBtn.style.cssText =
|
|
62
|
+
'display:inline-flex;align-items:center;gap:4px;' +
|
|
63
|
+
'background:#D97706;color:#fff;padding:4px 12px;border-radius:4px;' +
|
|
64
|
+
'font-size:12px;font-weight:600;text-decoration:none;margin-left:10px;' +
|
|
65
|
+
'white-space:nowrap;transition:background 0.15s';
|
|
66
|
+
upgradeBtn.onmouseover = function () { upgradeBtn.style.background = '#B45309'; };
|
|
67
|
+
upgradeBtn.onmouseout = function () { upgradeBtn.style.background = '#D97706'; };
|
|
68
|
+
d.appendChild(upgradeBtn);
|
|
69
|
+
|
|
70
|
+
var close = document.createElement('button');
|
|
71
|
+
close.textContent = '\u00d7';
|
|
72
|
+
close.style.cssText =
|
|
73
|
+
'background:none;border:none;color:#856404;font-size:18px;' +
|
|
74
|
+
'cursor:pointer;margin-left:12px;padding:0 4px;line-height:1';
|
|
75
|
+
close.onclick = function () { d.style.display = 'none'; };
|
|
76
|
+
d.appendChild(close);
|
|
77
|
+
|
|
78
|
+
document.body.prepend(d);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (document.readyState === 'loading') {
|
|
82
|
+
document.addEventListener('DOMContentLoaded', create);
|
|
83
|
+
} else {
|
|
84
|
+
create();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
var BANNER_SCRIPT =
|
|
89
|
+
'<script data-securenow-banner>(' +
|
|
90
|
+
_bannerClientCode.toString() +
|
|
91
|
+
')()</scr' + 'ipt>';
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Monkey-patch http.ServerResponse to inject the banner script into HTML
|
|
95
|
+
* responses. Searches for `<head...>` and inserts the script right after it.
|
|
96
|
+
* Skips compressed responses and non-HTML content types.
|
|
97
|
+
*/
|
|
98
|
+
function patchHttpForBanner() {
|
|
99
|
+
try {
|
|
100
|
+
var http = require('http');
|
|
101
|
+
var _origWrite = http.ServerResponse.prototype.write;
|
|
102
|
+
var _origEnd = http.ServerResponse.prototype.end;
|
|
103
|
+
|
|
104
|
+
function maybeInject(res, chunk) {
|
|
105
|
+
if (res._snBannerDone || !chunk) return chunk;
|
|
106
|
+
|
|
107
|
+
if (res._snIsHtml === undefined) {
|
|
108
|
+
var ct = res.getHeader('content-type');
|
|
109
|
+
var ce = res.getHeader('content-encoding');
|
|
110
|
+
var csp = res.getHeader('content-security-policy');
|
|
111
|
+
res._snIsHtml = !!(ct && String(ct).includes('text/html') && !ce && !csp);
|
|
112
|
+
}
|
|
113
|
+
if (!res._snIsHtml) {
|
|
114
|
+
res._snBannerDone = true;
|
|
115
|
+
return chunk;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
var isStr = typeof chunk === 'string';
|
|
119
|
+
var isBuf = Buffer.isBuffer(chunk);
|
|
120
|
+
if (!isStr && !isBuf) return chunk;
|
|
121
|
+
|
|
122
|
+
var str = isStr ? chunk : chunk.toString('utf8');
|
|
123
|
+
var headIdx = str.indexOf('<head');
|
|
124
|
+
if (headIdx === -1) return chunk;
|
|
125
|
+
|
|
126
|
+
var gt = str.indexOf('>', headIdx);
|
|
127
|
+
if (gt === -1) return chunk;
|
|
128
|
+
|
|
129
|
+
res._snBannerDone = true;
|
|
130
|
+
var result = str.slice(0, gt + 1) + BANNER_SCRIPT + str.slice(gt + 1);
|
|
131
|
+
return isStr ? result : Buffer.from(result, 'utf8');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
http.ServerResponse.prototype.write = function (chunk, encoding, cb) {
|
|
135
|
+
try {
|
|
136
|
+
var modified = maybeInject(this, chunk);
|
|
137
|
+
if (modified !== chunk) {
|
|
138
|
+
var enc = typeof encoding === 'function' ? 'utf8' : encoding;
|
|
139
|
+
var callback = typeof encoding === 'function' ? encoding : cb;
|
|
140
|
+
try {
|
|
141
|
+
if (this.getHeader('content-length')) {
|
|
142
|
+
this.setHeader('content-length', Buffer.byteLength(modified));
|
|
143
|
+
}
|
|
144
|
+
} catch (_) { /* headers already sent */ }
|
|
145
|
+
return _origWrite.call(this, modified, enc, callback);
|
|
146
|
+
}
|
|
147
|
+
} catch (_) { /* never break the app */ }
|
|
148
|
+
return _origWrite.call(this, chunk, encoding, cb);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
http.ServerResponse.prototype.end = function (chunk, encoding, cb) {
|
|
152
|
+
try {
|
|
153
|
+
var modified = maybeInject(this, chunk);
|
|
154
|
+
if (modified !== chunk) {
|
|
155
|
+
var enc = typeof encoding === 'function' ? 'utf8' : encoding;
|
|
156
|
+
var callback = typeof encoding === 'function' ? encoding : cb;
|
|
157
|
+
try {
|
|
158
|
+
if (this.getHeader('content-length')) {
|
|
159
|
+
this.setHeader('content-length', Buffer.byteLength(modified));
|
|
160
|
+
}
|
|
161
|
+
} catch (_) { /* headers already sent */ }
|
|
162
|
+
return _origEnd.call(this, modified, enc, callback);
|
|
163
|
+
}
|
|
164
|
+
} catch (_) { /* never break the app */ }
|
|
165
|
+
return _origEnd.call(this, chunk, encoding, cb);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
console.log('[securenow] Free trial banner injection enabled');
|
|
169
|
+
} catch (err) {
|
|
170
|
+
console.warn('[securenow] Could not setup free trial banner:', err.message);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
module.exports = { isFreeTrial, patchHttpForBanner, BANNER_SCRIPT };
|