cleartoship 0.12.1 → 0.12.2
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/README.md +2 -2
- package/action.yml +2 -2
- package/dist/scanners/community.js +33 -0
- package/dist/types.d.ts +1 -0
- package/dist/utils/detect.js +6 -0
- package/examples/security.yml +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -251,7 +251,7 @@ jobs:
|
|
|
251
251
|
runs-on: ubuntu-latest
|
|
252
252
|
steps:
|
|
253
253
|
- uses: actions/checkout@v7
|
|
254
|
-
- uses: murtazaozdemir/cleartoship@v0.12.
|
|
254
|
+
- uses: murtazaozdemir/cleartoship@v0.12.2
|
|
255
255
|
with:
|
|
256
256
|
fail-on: critical
|
|
257
257
|
comment: true
|
|
@@ -273,7 +273,7 @@ above `fail-on`) for use in later steps. The comment is *sticky* — re-runs edi
|
|
|
273
273
|
the same comment instead of piling up.
|
|
274
274
|
|
|
275
275
|
By default the action runs the scanner version its own ref declares, so
|
|
276
|
-
`@v0.12.
|
|
276
|
+
`@v0.12.2` runs `cleartoship@0.12.2` and pinning the ref pins the behaviour. If
|
|
277
277
|
that version is not on the registry, it builds from its own checkout instead, so
|
|
278
278
|
`uses: …@ref` works against an unpublished commit.
|
|
279
279
|
|
package/action.yml
CHANGED
|
@@ -29,7 +29,7 @@ inputs:
|
|
|
29
29
|
version:
|
|
30
30
|
description: >-
|
|
31
31
|
Version of the cleartoship npm package to run. Defaults to the version this
|
|
32
|
-
action's own ref declares, so `uses: …@v0.12.
|
|
32
|
+
action's own ref declares, so `uses: …@v0.12.2` runs cleartoship@0.12.2. Set
|
|
33
33
|
`latest` to always track the newest release, or `local` to build from the checkout.
|
|
34
34
|
required: false
|
|
35
35
|
default: ''
|
|
@@ -76,7 +76,7 @@ runs:
|
|
|
76
76
|
run: |
|
|
77
77
|
# With no version pinned, run the exact version this action's checkout
|
|
78
78
|
# declares. That keeps the action ref and the scanner in lockstep:
|
|
79
|
-
# `uses: <owner>/cleartoship@v0.12.
|
|
79
|
+
# `uses: <owner>/cleartoship@v0.12.2` runs cleartoship@0.12.2 instead of
|
|
80
80
|
# whatever npm happens to tag `latest` at the time.
|
|
81
81
|
ver="$INPUT_VERSION"
|
|
82
82
|
if [ -z "$ver" ]; then
|
|
@@ -254,6 +254,20 @@ const MATCH_GUARDS = {
|
|
|
254
254
|
// cannot tell whether the auth check is already there, and CTS001 can:
|
|
255
255
|
// matching on the module's own vocabulary keeps this from contradicting it.
|
|
256
256
|
VG1025: (_match, source) => !/\b(auth\.getUser|getServerSession|getServerAuthSession|requireUser|requireAuth|requireUserId|currentUser|handleSessionToken|verifyRequest|getSession)\s*\(/.test(source),
|
|
257
|
+
// `jwt.sign(payload, getJwtSecret(), { expiresIn: TOKEN_EXPIRY })` was
|
|
258
|
+
// reported as a token without expiry: the pattern's `[^)]` scan for
|
|
259
|
+
// `expiresIn` stops at the first `)`, which here belongs to `getJwtSecret()`.
|
|
260
|
+
// Read the whole call before saying the option is absent.
|
|
261
|
+
VG061: (_match, source, index) => !/\b(expiresIn|exp\s*:|setExpirationTime)\b/.test(source.slice(index, index + 300)),
|
|
262
|
+
// The "sink" half of the upload rule matched the word *upload* inside a
|
|
263
|
+
// sentence — "Please upload a CSV file exported from Shopify". A filename
|
|
264
|
+
// reaching a string is not a filename reaching a filesystem.
|
|
265
|
+
VG993: (match, source, index, spans) => !isInside(spans, index + match.length - 1, 'string'),
|
|
266
|
+
// A login endpoint is server code. This fired on `<Link href="/login">Back to
|
|
267
|
+
// sign in</Link>` in a client page, where "verify" and "login" are words in
|
|
268
|
+
// markup rather than a password comparison behind an HTTP handler.
|
|
269
|
+
VG148: (match, source) => !/^\s*(['"])use client\1/m.test(source.slice(0, 400)) &&
|
|
270
|
+
/(bcrypt\.compare|argon2\.verify|\b(compare|verify|verifyPassword)\s*\()/.test(match),
|
|
257
271
|
// SSRF is a *server* being made to fetch a URL it should not. A module marked
|
|
258
272
|
// `'use client'` runs in the browser, where the request leaves the user's own
|
|
259
273
|
// machine and crosses no trust boundary of yours.
|
|
@@ -298,6 +312,25 @@ function inapplicable(ctx) {
|
|
|
298
312
|
ids.add('VG132');
|
|
299
313
|
why.push('VG132 body-size limit (Next.js sets one by default)');
|
|
300
314
|
}
|
|
315
|
+
// A rule that names a platform cannot apply to a project that does not use
|
|
316
|
+
// it. "Supabase Auth Missing Middleware" was reported against an app with no
|
|
317
|
+
// Supabase dependency at all — advice about a library it does not import.
|
|
318
|
+
for (const [name, present, keyword] of [
|
|
319
|
+
['Supabase', ctx.framework.supabase, /supabase/i],
|
|
320
|
+
['Firebase', ctx.framework.firebase, /firebase|firestore/i],
|
|
321
|
+
]) {
|
|
322
|
+
if (present)
|
|
323
|
+
continue;
|
|
324
|
+
let n = 0;
|
|
325
|
+
for (const rule of GUARDVIBE_RULES) {
|
|
326
|
+
if (keyword.test(rule.name) || keyword.test(rule.description)) {
|
|
327
|
+
ids.add(rule.id);
|
|
328
|
+
n++;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (n > 0)
|
|
332
|
+
why.push(`${n} ${name} rules (no ${name} dependency)`);
|
|
333
|
+
}
|
|
301
334
|
return { ids, why };
|
|
302
335
|
}
|
|
303
336
|
/**
|
package/dist/types.d.ts
CHANGED
package/dist/utils/detect.js
CHANGED
|
@@ -56,6 +56,10 @@ export function detectFramework(root, files) {
|
|
|
56
56
|
python: exists(join(root, 'requirements.txt')) ||
|
|
57
57
|
exists(join(root, 'pyproject.toml')),
|
|
58
58
|
reactNative,
|
|
59
|
+
firebase: hasDep(pkg, 'firebase') ||
|
|
60
|
+
hasDep(pkg, 'firebase-admin') ||
|
|
61
|
+
hasDep(pkg, '@firebase/app') ||
|
|
62
|
+
exists(join(root, 'firebase.json')),
|
|
59
63
|
describe() {
|
|
60
64
|
const parts = [];
|
|
61
65
|
if (this.nextjs === 'app-router')
|
|
@@ -80,6 +84,8 @@ export function detectFramework(root, files) {
|
|
|
80
84
|
parts.push('Python');
|
|
81
85
|
if (this.reactNative)
|
|
82
86
|
parts.push('React Native');
|
|
87
|
+
if (this.firebase)
|
|
88
|
+
parts.push('Firebase');
|
|
83
89
|
return parts.length ? parts.join(' + ') : 'generic JavaScript/TypeScript';
|
|
84
90
|
},
|
|
85
91
|
};
|
package/examples/security.yml
CHANGED
|
@@ -22,7 +22,7 @@ jobs:
|
|
|
22
22
|
runs-on: ubuntu-latest
|
|
23
23
|
steps:
|
|
24
24
|
- uses: actions/checkout@v7
|
|
25
|
-
- uses: murtazaozdemir/cleartoship@v0.12.
|
|
25
|
+
- uses: murtazaozdemir/cleartoship@v0.12.2
|
|
26
26
|
with:
|
|
27
27
|
fail-on: critical # block the PR only on criticals
|
|
28
28
|
comment: true # post a summary comment on the PR
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cleartoship",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.2",
|
|
4
4
|
"description": "The 30-second pre-launch security clearance for AI-built & vibe-coded apps. Catches missing Server Action auth, Supabase RLS holes, hallucinated npm packages and leaked keys.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"security",
|