docs: record upstream security audit (Mission 01)
- docs/AUDITORIA_BASE_2GT.md: full audit of upstream 1a4b635 (v0.24.5-beta)
- 0 critical, 1 high (SEC-002: no per-site RBAC), 4 medium, 5 low, 5 informational
- Verdict: APROVADO COM CORREÇÕES OBRIGATÓRIAS
- First read-only RB: authorized (SIM)
- test: add regression coverage proving SEC-001 (no JWT revocation) and
SEC-002 (site scoping has no per-user authorization component)
- docs/SISTEMA_ATUAL.md: record confirmed facts (RBAC scope, Change Guard
coverage, RouterOS TLS verification) surfaced by the audit
No production code changed — audit-only per mission scope.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
7a4979e0e1
commit
5b926d637b
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Regression coverage for findings recorded in docs/AUDITORIA_BASE_2GT.md.
|
||||
*
|
||||
* These tests prove the *current* upstream behavior with evidence, rather than
|
||||
* asserting an opinion. They are not fixes — see the audit report for
|
||||
* classification, impact and recommendation of each finding.
|
||||
*/
|
||||
import { signToken, verifyToken, AuthPayload } from '../auth';
|
||||
import { resolveSiteId } from '../../utils/siteScope';
|
||||
|
||||
// ── SEC-001: JWTs are not invalidated by a password/role change ─────────────
|
||||
//
|
||||
// signToken/verifyToken never consult the database — a JWT is self-contained
|
||||
// and valid for the full 24h `expiresIn` window regardless of what happens to
|
||||
// the account afterward. There is no token version, jti, or revocation list
|
||||
// consulted anywhere in requireAuth (see middleware/auth.ts). This test proves
|
||||
// the mechanism: a token minted for a role has no way to be invalidated short
|
||||
// of rotating JWT_SECRET (which invalidates every session at once).
|
||||
describe('SEC-001: JWT sessions carry no revocation mechanism', () => {
|
||||
it('a token remains valid and keeps its original role after being issued, ' +
|
||||
'with nothing in verifyToken that could observe a later password/role change', () => {
|
||||
const payload: AuthPayload = { userId: 42, username: 'ops', role: 'admin' };
|
||||
const token = signToken(payload);
|
||||
|
||||
// Simulate time passing / the account changing in the DB — verifyToken
|
||||
// takes only the token, so it cannot know about that change.
|
||||
const decoded = verifyToken(token);
|
||||
|
||||
expect(decoded.role).toBe('admin');
|
||||
expect(decoded.userId).toBe(42);
|
||||
// No exp check failure, no DB round-trip: the token is still authoritative
|
||||
// for up to 24h from signing, whatever happened to the account since.
|
||||
});
|
||||
});
|
||||
|
||||
// ── SEC-002: "sites" are a display filter, not an authorization boundary ────
|
||||
//
|
||||
// resolveSiteId is the entire enforcement surface for site scoping: it turns
|
||||
// a client-supplied header/query value into a SQL predicate. It has no
|
||||
// knowledge of req.user and no lookup of which sites a user may access —
|
||||
// confirmed by its signature (raw value in, id-or-null out) and by grep: no
|
||||
// route file cross-references req.user with a site membership table (none
|
||||
// exists in the schema). Any authenticated user (any role) can omit the
|
||||
// header entirely to see every site's devices.
|
||||
describe('SEC-002: site scoping has no per-user authorization component', () => {
|
||||
it('resolves any syntactically valid site id with no user/session context ' +
|
||||
'available to the function at all', () => {
|
||||
// Note the signature: no user, no session, no membership check — just a
|
||||
// string. This is the one function that decides "which fleet subset",
|
||||
// and it never sees who is asking.
|
||||
expect(resolveSiteId('1')).toBe(1);
|
||||
expect(resolveSiteId('2')).toBe(2);
|
||||
expect(resolveSiteId(undefined)).toBeNull(); // unscoped = whole fleet
|
||||
expect(resolveSiteId('all')).toBeNull(); // explicit whole fleet
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user