Last verified: 2026-06-26. Combines the public responsible-disclosure policy with the internal auth/secrets/incident reference.
Do NOT open a public GitHub issue for security vulnerabilities. Email
security@satelink.network (48h acknowledgement, 7d triage). Include: description, repro steps,
impact, optional fix.
In scope: smart contracts (NodeRegistryV2, SplitEngine, RevenueVault, RevenueDistributor, ClaimsContract, ClaimsWithdrawals, EpochAnchor, EligibilityPolicy, GovernanceTimelock), node edge agent, API authn/authz, settlement & claims flows, epoch anchoring / Merkle verification. Out of scope: social engineering, physical access, third-party deps (report upstream), test/mock contracts (MockUSDT), gas-limit DoS.
Severity: Critical = direct fund loss; High = protocol disruption / RBAC bypass;
Medium = limited/conditional; Low = informational. No formal bounty yet; safe harbor for
good-faith research. Contact: security@satelink.network · hello@satelink.network · discord.gg/satelink.
- Admin routes (
/admin/*):X-Admin-Token==ADMIN_SECRET_TOKEN(requireAdminAuth,apps/api/src/admin/admin_router.js). No token / wrong token → 401. Missing env → 503. - User routes: JWT (
requireJWT/requireRole). - Frontend → admin:
apps/web/src/app/api/admin-proxy/route.jsinjectsADMIN_TOKENserver-side; the token never reaches the browser. Only/admin/*is forwarded (no open relay).
.envfiles are not committed (only.env.example). Secrets live in Railway env.- Never hardcode secrets — use
process.env, hard-fail if missing. /admin/configreturns key names and non-secret values only — never secret values.- Read the admin token from
railway variables --service Satelink-api --kv(table view truncates).
- Admin-proxy token-prefix leak (was VERIFIED):
admin-proxy/route.jsloggedtoken?.substring(0,6)in twoconsole.logstatements. Removed. No token/credential is logged anymore.
admin-proxy/route.jsstill has two non-credential debug logs, incl. one that logs the full upstream admin response (console.log('[DEBUG Proxy] Upstream data:', data)) into server logs — recommend removing (logs customer/revenue data, though not secrets).- Backend has
console.logacross ~180 files (audit §9). A blanket sweep was deliberately not done on this branch: high-risk churn on the load-bearing API, unreviewable diff. Should be a separate, scoped change (convert error logs →console.error, drop debug logs, syntax- check each file).
SETTLEMENT_DRY_RUN=1— never flip to 0 autonomously. Requires signer funded + real revenue$0.50 + explicit human decision. Settlement is currently NOT broadcasting (signerBalance null).
- INC-013 (critical, resolved): signer drain — 1,878 phantom settlement TX. The
1,878 TXfigure is historical and must never appear as a fabricated live UI metric. - INC-014 (high, resolved): phantom billing — test/phantom volume counted as real revenue.
Fixed by
is_test_datafiltering + phantom-epoch (is_phantom) exclusion. - INC-012 (high, resolved): Redis OOM.
- Never drop/truncate any table. Never delete
agent/memory/. Read-only psql for inspection.